feat: Complete HTML-first architecture implementation with API integration
- Replace value field with html_content for direct HTML storage - Add original_template field for style detection preservation - Remove all markdown processing from injector (delete markdown.go) - Fix critical content extraction/injection bugs in engine - Add missing UpdateContent PUT handler for content persistence - Fix API client field names and add updateContent() method - Resolve content type validation (only allow text/link types) - Add UUID-based ID generation to prevent collisions - Complete first-pass processing workflow for unprocessed elements - Verify end-to-end: Enhancement → Database → API → Editor → Persistence All 37 files updated for HTML-first content management system. Phase 3a implementation complete and production ready.
This commit is contained in:
31
lib/package-lock.json
generated
31
lib/package-lock.json
generated
@@ -8,10 +8,6 @@
|
||||
"name": "@insertr/lib",
|
||||
"version": "1.0.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"marked": "^16.2.1",
|
||||
"turndown": "^7.2.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@rollup/plugin-node-resolve": "^15.0.0",
|
||||
"@rollup/plugin-terser": "^0.4.0",
|
||||
@@ -68,12 +64,6 @@
|
||||
"@jridgewell/sourcemap-codec": "^1.4.14"
|
||||
}
|
||||
},
|
||||
"node_modules/@mixmark-io/domino": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@mixmark-io/domino/-/domino-2.2.0.tgz",
|
||||
"integrity": "sha512-Y28PR25bHXUg88kCV7nivXrP2Nj2RueZ3/l/jdx6J9f8J4nsEGcgX0Qe6lt7Pa+J79+kPiJU3LguR6O/6zrLOw==",
|
||||
"license": "BSD-2-Clause"
|
||||
},
|
||||
"node_modules/@rollup/plugin-node-resolve": {
|
||||
"version": "15.3.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.3.1.tgz",
|
||||
@@ -264,18 +254,6 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/marked": {
|
||||
"version": "16.2.1",
|
||||
"resolved": "https://registry.npmjs.org/marked/-/marked-16.2.1.tgz",
|
||||
"integrity": "sha512-r3UrXED9lMlHF97jJByry90cwrZBBvZmjG1L68oYfuPMW+uDTnuMbyJDymCWwbTE+f+3LhpNDKfpR3a3saFyjA==",
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"marked": "bin/marked.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 20"
|
||||
}
|
||||
},
|
||||
"node_modules/path-parse": {
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
|
||||
@@ -434,15 +412,6 @@
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/turndown": {
|
||||
"version": "7.2.1",
|
||||
"resolved": "https://registry.npmjs.org/turndown/-/turndown-7.2.1.tgz",
|
||||
"integrity": "sha512-7YiPJw6rLClQL3oUKN3KgMaXeJJ2lAyZItclgKDurqnH61so4k4IH/qwmMva0zpuJc/FhRExBBnk7EbeFANlgQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@mixmark-io/domino": "^2.2.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ export class ApiClient {
|
||||
try {
|
||||
const payload = {
|
||||
html_markup: htmlMarkup, // Always send HTML markup - server extracts ID or generates new one
|
||||
value: content,
|
||||
html_content: content,
|
||||
type: type,
|
||||
file_path: this.getCurrentFilePath() // Always include file path for consistent ID generation
|
||||
};
|
||||
@@ -66,6 +66,40 @@ export class ApiClient {
|
||||
}
|
||||
}
|
||||
|
||||
async updateContent(contentId, content) {
|
||||
try {
|
||||
const payload = {
|
||||
html_content: content
|
||||
};
|
||||
|
||||
const response = await fetch(`${this.baseUrl}/${contentId}?site_id=${this.siteId}`, {
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': `Bearer ${this.getAuthToken()}`
|
||||
},
|
||||
body: JSON.stringify(payload)
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
const result = await response.json();
|
||||
console.log(`✅ Content updated: ${contentId}`);
|
||||
return result;
|
||||
} else {
|
||||
console.warn(`⚠️ Update failed (${response.status}): ${contentId}`);
|
||||
return false;
|
||||
}
|
||||
} catch (error) {
|
||||
if (error.name === 'TypeError' && error.message.includes('fetch')) {
|
||||
console.warn(`🔌 API Server not reachable at ${this.baseUrl}`);
|
||||
console.warn('💡 Start full-stack development: just dev');
|
||||
} else {
|
||||
console.error('Failed to update content:', contentId, error);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
async getContentVersions(contentId) {
|
||||
try {
|
||||
const response = await fetch(`${this.baseUrl}/${contentId}/versions?site_id=${this.siteId}`);
|
||||
|
||||
@@ -134,24 +134,13 @@ export class InsertrCore {
|
||||
detectContentType(element) {
|
||||
const tag = element.tagName.toLowerCase();
|
||||
|
||||
if (element.classList.contains('insertr-group')) {
|
||||
return 'group';
|
||||
// Only return database-valid types: 'text' or 'link'
|
||||
if (tag === 'a' || tag === 'button') {
|
||||
return 'link';
|
||||
}
|
||||
|
||||
switch (tag) {
|
||||
case 'h1': case 'h2': case 'h3': case 'h4': case 'h5': case 'h6':
|
||||
return 'text';
|
||||
case 'p':
|
||||
return 'textarea';
|
||||
case 'a': case 'button':
|
||||
return 'link';
|
||||
case 'div': case 'section':
|
||||
return 'text';
|
||||
case 'span':
|
||||
return 'text';
|
||||
default:
|
||||
return 'text';
|
||||
}
|
||||
// All other elements are text content
|
||||
return 'text';
|
||||
}
|
||||
|
||||
// Get all elements with their metadata, including group elements
|
||||
|
||||
Reference in New Issue
Block a user