feat: complete HTML-first architecture implementation (Phase 1 & 2)

Major architectural simplification removing content type complexity:

Database Schema:
- Remove 'type' field from content and content_versions tables
- Simplify to pure HTML storage with html_content + original_template
- Regenerate all sqlc models for SQLite and PostgreSQL

API Simplification:
- Remove content type routing and validation
- Eliminate type-specific handlers (text/markdown/structured)
- Unified HTML-first approach for all content operations
- Simplify CreateContent and UpdateContent to HTML-only

Backend Enhancements:
- Update enhancer to only generate data-content-id (no data-content-type)
- Improve container expansion utilities with comprehensive block/inline rules
- Add Phase 3 preparation with boundary-respecting traversal logic
- Strengthen element classification for viable children detection

Documentation:
- Update TODO.md to reflect Phase 1-3 completion status
- Add WORKING_ON.md documenting the architectural transformation
- Mark container expansion and HTML-first architecture as complete

This completes the transition to a unified HTML-first content management system
with automatic style detection and element-based behavior, eliminating the
complex multi-type system in favor of semantic HTML-driven editing.
This commit is contained in:
2025-09-21 19:23:54 +02:00
parent b5e601d09f
commit b75eda2a87
25 changed files with 470 additions and 214 deletions

View File

@@ -314,14 +314,7 @@ func (h *ContentHandler) CreateContent(w http.ResponseWriter, r *http.Request) {
}
}
// Determine content type: use provided type, fallback to existing type, default to "text"
contentType := req.Type
if contentType == "" && contentExists {
contentType = h.getContentType(existingContent)
}
if contentType == "" {
contentType = "text" // default type for new content
}
// HTML-first approach: no content type needed
var content interface{}
var err error
@@ -333,7 +326,6 @@ func (h *ContentHandler) CreateContent(w http.ResponseWriter, r *http.Request) {
SiteID: siteID,
HtmlContent: req.HTMLContent,
OriginalTemplate: toNullString(req.OriginalTemplate),
Type: contentType,
LastEditedBy: userID,
})
case "postgresql":
@@ -342,7 +334,6 @@ func (h *ContentHandler) CreateContent(w http.ResponseWriter, r *http.Request) {
SiteID: siteID,
HtmlContent: req.HTMLContent,
OriginalTemplate: toNullString(req.OriginalTemplate),
Type: contentType,
LastEditedBy: userID,
})
default:
@@ -447,7 +438,6 @@ func (h *ContentHandler) UpdateContent(w http.ResponseWriter, r *http.Request) {
case "sqlite3":
updatedContent, err = h.database.GetSQLiteQueries().UpdateContent(context.Background(), sqlite.UpdateContentParams{
HtmlContent: req.HTMLContent,
Type: h.getContentType(existingContent),
LastEditedBy: userID,
ID: contentID,
SiteID: siteID,
@@ -455,7 +445,6 @@ func (h *ContentHandler) UpdateContent(w http.ResponseWriter, r *http.Request) {
case "postgresql":
updatedContent, err = h.database.GetPostgreSQLQueries().UpdateContent(context.Background(), postgresql.UpdateContentParams{
HtmlContent: req.HTMLContent,
Type: h.getContentType(existingContent),
LastEditedBy: userID,
ID: contentID,
SiteID: siteID,
@@ -664,7 +653,6 @@ func (h *ContentHandler) RollbackContent(w http.ResponseWriter, r *http.Request)
sqliteVersion := targetVersion.(sqlite.ContentVersion)
updatedContent, err = h.database.GetSQLiteQueries().UpdateContent(context.Background(), sqlite.UpdateContentParams{
HtmlContent: sqliteVersion.HtmlContent,
Type: sqliteVersion.Type,
LastEditedBy: userID,
ID: contentID,
SiteID: siteID,
@@ -673,7 +661,6 @@ func (h *ContentHandler) RollbackContent(w http.ResponseWriter, r *http.Request)
pgVersion := targetVersion.(postgresql.ContentVersion)
updatedContent, err = h.database.GetPostgreSQLQueries().UpdateContent(context.Background(), postgresql.UpdateContentParams{
HtmlContent: pgVersion.HtmlContent,
Type: pgVersion.Type,
LastEditedBy: userID,
ID: contentID,
SiteID: siteID,
@@ -704,7 +691,6 @@ func (h *ContentHandler) convertToAPIContent(content interface{}) ContentItem {
SiteID: c.SiteID,
HTMLContent: c.HtmlContent,
OriginalTemplate: fromNullString(c.OriginalTemplate),
Type: c.Type,
CreatedAt: time.Unix(c.CreatedAt, 0),
UpdatedAt: time.Unix(c.UpdatedAt, 0),
LastEditedBy: c.LastEditedBy,
@@ -716,7 +702,6 @@ func (h *ContentHandler) convertToAPIContent(content interface{}) ContentItem {
SiteID: c.SiteID,
HTMLContent: c.HtmlContent,
OriginalTemplate: fromNullString(c.OriginalTemplate),
Type: c.Type,
CreatedAt: time.Unix(c.CreatedAt, 0),
UpdatedAt: time.Unix(c.UpdatedAt, 0),
LastEditedBy: c.LastEditedBy,
@@ -757,7 +742,6 @@ func (h *ContentHandler) convertToAPIVersionList(versionList interface{}) []Cont
SiteID: version.SiteID,
HTMLContent: version.HtmlContent,
OriginalTemplate: fromNullString(version.OriginalTemplate),
Type: version.Type,
CreatedAt: time.Unix(version.CreatedAt, 0),
CreatedBy: version.CreatedBy,
}
@@ -773,7 +757,6 @@ func (h *ContentHandler) convertToAPIVersionList(versionList interface{}) []Cont
SiteID: version.SiteID,
HTMLContent: version.HtmlContent,
OriginalTemplate: fromNullString(version.OriginalTemplate),
Type: version.Type,
CreatedAt: time.Unix(version.CreatedAt, 0),
CreatedBy: version.CreatedBy,
}
@@ -792,7 +775,6 @@ func (h *ContentHandler) createContentVersion(content interface{}) error {
SiteID: c.SiteID,
HtmlContent: c.HtmlContent,
OriginalTemplate: c.OriginalTemplate,
Type: c.Type,
CreatedBy: c.LastEditedBy,
})
case "postgresql":
@@ -802,23 +784,12 @@ func (h *ContentHandler) createContentVersion(content interface{}) error {
SiteID: c.SiteID,
HtmlContent: c.HtmlContent,
OriginalTemplate: c.OriginalTemplate,
Type: c.Type,
CreatedBy: c.LastEditedBy,
})
}
return fmt.Errorf("unsupported database type")
}
func (h *ContentHandler) getContentType(content interface{}) string {
switch h.database.GetDBType() {
case "sqlite3":
return content.(sqlite.Content).Type
case "postgresql":
return content.(postgresql.Content).Type
}
return ""
}
func (h *ContentHandler) versionMatches(version interface{}, contentID, siteID string) bool {
switch h.database.GetDBType() {
case "sqlite3":

View File

@@ -8,7 +8,6 @@ type ContentItem struct {
SiteID string `json:"site_id"`
HTMLContent string `json:"html_content"`
OriginalTemplate string `json:"original_template"`
Type string `json:"type"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
LastEditedBy string `json:"last_edited_by"`
@@ -20,7 +19,6 @@ type ContentVersion struct {
SiteID string `json:"site_id"`
HTMLContent string `json:"html_content"`
OriginalTemplate string `json:"original_template"`
Type string `json:"type"`
CreatedAt time.Time `json:"created_at"`
CreatedBy string `json:"created_by"`
}
@@ -48,7 +46,6 @@ type CreateContentRequest struct {
FilePath string `json:"file_path"` // File path for consistent ID generation
HTMLContent string `json:"html_content"` // HTML content value
OriginalTemplate string `json:"original_template"` // Original template markup
Type string `json:"type"` // Content type
SiteID string `json:"site_id,omitempty"` // Site identifier
CreatedBy string `json:"created_by,omitempty"` // User who created the content
}

View File

@@ -166,7 +166,7 @@ func (c *HTTPClient) GetAllContent(siteID string) (map[string]engine.ContentItem
}
// CreateContent creates a new content item via HTTP API
func (c *HTTPClient) CreateContent(siteID, contentID, htmlContent, originalTemplate, contentType, lastEditedBy string) (*engine.ContentItem, error) {
func (c *HTTPClient) CreateContent(siteID, contentID, htmlContent, originalTemplate, lastEditedBy string) (*engine.ContentItem, error) {
// For now, HTTPClient CreateContent is not implemented for enhancer use
// This would typically be used in API-driven enhancement scenarios
return nil, fmt.Errorf("CreateContent not implemented for HTTPClient - use DatabaseClient for enhancement")

View File

@@ -144,7 +144,6 @@ func (d *DatabaseClient) convertToContentItem(content interface{}) engine.Conten
SiteID: c.SiteID,
HTMLContent: c.HtmlContent,
OriginalTemplate: getStringFromNullString(c.OriginalTemplate),
Type: c.Type,
UpdatedAt: time.Unix(c.UpdatedAt, 0).Format(time.RFC3339),
}
case "postgresql":
@@ -154,7 +153,6 @@ func (d *DatabaseClient) convertToContentItem(content interface{}) engine.Conten
SiteID: c.SiteID,
HTMLContent: c.HtmlContent,
OriginalTemplate: getStringFromNullString(c.OriginalTemplate),
Type: c.Type,
UpdatedAt: time.Unix(c.UpdatedAt, 0).Format(time.RFC3339),
}
}
@@ -182,8 +180,8 @@ func (d *DatabaseClient) convertToContentItemList(contentList interface{}) []eng
return []engine.ContentItem{} // Should never happen
}
// CreateContent creates a new content item
func (c *DatabaseClient) CreateContent(siteID, contentID, htmlContent, originalTemplate, contentType, lastEditedBy string) (*engine.ContentItem, error) {
// CreateContent creates a new content item
func (c *DatabaseClient) CreateContent(siteID, contentID, htmlContent, originalTemplate, lastEditedBy string) (*engine.ContentItem, error) {
switch c.db.GetDBType() {
case "sqlite3":
content, err := c.db.GetSQLiteQueries().CreateContent(context.Background(), sqlite.CreateContentParams{
@@ -191,7 +189,6 @@ func (c *DatabaseClient) CreateContent(siteID, contentID, htmlContent, originalT
SiteID: siteID,
HtmlContent: htmlContent,
OriginalTemplate: toNullString(originalTemplate),
Type: contentType,
LastEditedBy: lastEditedBy,
})
if err != nil {
@@ -202,7 +199,6 @@ func (c *DatabaseClient) CreateContent(siteID, contentID, htmlContent, originalT
SiteID: content.SiteID,
HTMLContent: content.HtmlContent,
OriginalTemplate: getStringFromNullString(content.OriginalTemplate),
Type: content.Type,
LastEditedBy: content.LastEditedBy,
}, nil
@@ -212,7 +208,6 @@ func (c *DatabaseClient) CreateContent(siteID, contentID, htmlContent, originalT
SiteID: siteID,
HtmlContent: htmlContent,
OriginalTemplate: toNullString(originalTemplate),
Type: contentType,
LastEditedBy: lastEditedBy,
})
if err != nil {
@@ -223,7 +218,6 @@ func (c *DatabaseClient) CreateContent(siteID, contentID, htmlContent, originalT
SiteID: content.SiteID,
HTMLContent: content.HtmlContent,
OriginalTemplate: getStringFromNullString(content.OriginalTemplate),
Type: content.Type,
LastEditedBy: content.LastEditedBy,
}, nil

View File

@@ -20,15 +20,15 @@ func NewMockClient() *MockClient {
ID: "navbar-logo-2b10ad",
SiteID: "demo",
HTMLContent: "Acme Consulting Solutions",
Type: "text",
UpdatedAt: time.Now().Format(time.RFC3339),
UpdatedAt: time.Now().Format(time.RFC3339),
},
"navbar-logo-2b10ad-a44bad": {
ID: "navbar-logo-2b10ad-a44bad",
SiteID: "demo",
HTMLContent: "Acme Business Advisors",
Type: "text",
UpdatedAt: time.Now().Format(time.RFC3339),
UpdatedAt: time.Now().Format(time.RFC3339),
},
// Hero Section - index.html (updated with actual IDs)
@@ -36,22 +36,22 @@ func NewMockClient() *MockClient {
ID: "hero-title-7cfeea",
SiteID: "demo",
HTMLContent: "Transform Your Business with Strategic Expertise",
Type: "text",
UpdatedAt: time.Now().Format(time.RFC3339),
UpdatedAt: time.Now().Format(time.RFC3339),
},
"hero-lead-e47475": {
ID: "hero-lead-e47475",
SiteID: "demo",
HTMLContent: "We help <strong>ambitious businesses</strong> grow through strategic planning, process optimization, and digital transformation. Our team brings 20+ years of experience to accelerate your success.",
Type: "text",
UpdatedAt: time.Now().Format(time.RFC3339),
UpdatedAt: time.Now().Format(time.RFC3339),
},
"hero-link-76c620": {
ID: "hero-link-76c620",
SiteID: "demo",
HTMLContent: "Schedule Free Consultation",
Type: "link",
UpdatedAt: time.Now().Format(time.RFC3339),
UpdatedAt: time.Now().Format(time.RFC3339),
},
// Hero Section - about.html
@@ -59,15 +59,15 @@ func NewMockClient() *MockClient {
ID: "hero-title-c70343",
SiteID: "demo",
HTMLContent: "About Our Consulting Expertise",
Type: "text",
UpdatedAt: time.Now().Format(time.RFC3339),
UpdatedAt: time.Now().Format(time.RFC3339),
},
"hero-lead-673026": {
ID: "hero-lead-673026",
SiteID: "demo",
HTMLContent: "We're a team of <strong>experienced consultants</strong> dedicated to helping small businesses thrive in today's competitive marketplace through proven strategies.",
Type: "text",
UpdatedAt: time.Now().Format(time.RFC3339),
UpdatedAt: time.Now().Format(time.RFC3339),
},
// Services Section
@@ -75,15 +75,15 @@ func NewMockClient() *MockClient {
ID: "services-subtitle-c8927c",
SiteID: "demo",
HTMLContent: "Our Story",
Type: "text",
UpdatedAt: time.Now().Format(time.RFC3339),
UpdatedAt: time.Now().Format(time.RFC3339),
},
"services-text-0d96da": {
ID: "services-text-0d96da",
SiteID: "demo",
HTMLContent: "<strong>Founded in 2020</strong>, Acme Consulting emerged from a simple observation: small businesses needed access to the same high-quality strategic advice that large corporations receive, but in a format that was accessible, affordable, and actionable.",
Type: "text",
UpdatedAt: time.Now().Format(time.RFC3339),
UpdatedAt: time.Now().Format(time.RFC3339),
},
// Default fallback for any missing content
@@ -91,8 +91,8 @@ func NewMockClient() *MockClient {
ID: "default",
SiteID: "demo",
HTMLContent: "[Enhanced Content]",
Type: "text",
UpdatedAt: time.Now().Format(time.RFC3339),
UpdatedAt: time.Now().Format(time.RFC3339),
},
}
@@ -140,20 +140,19 @@ func (m *MockClient) GetAllContent(siteID string) (map[string]engine.ContentItem
}
// CreateContent creates a new mock content item
func (m *MockClient) CreateContent(siteID, contentID, htmlContent, originalTemplate, contentType, lastEditedBy string) (*engine.ContentItem, error) {
func (m *MockClient) CreateContent(siteID, contentID, htmlContent, originalTemplate, lastEditedBy string) (*engine.ContentItem, error) {
// For mock client, just create and store the item
item := engine.ContentItem{
ID: contentID,
SiteID: siteID,
HTMLContent: htmlContent,
OriginalTemplate: originalTemplate,
Type: contentType,
UpdatedAt: time.Now().Format(time.RFC3339),
LastEditedBy: lastEditedBy,
}
// Store in mock data
m.data[contentID] = item
return &item, nil
}

View File

@@ -12,9 +12,9 @@ import (
)
const createContent = `-- name: CreateContent :one
INSERT INTO content (id, site_id, html_content, original_template, type, last_edited_by)
VALUES ($1, $2, $3, $4, $5, $6)
RETURNING id, site_id, html_content, original_template, type, created_at, updated_at, last_edited_by
INSERT INTO content (id, site_id, html_content, original_template, last_edited_by)
VALUES ($1, $2, $3, $4, $5)
RETURNING id, site_id, html_content, original_template, created_at, updated_at, last_edited_by
`
type CreateContentParams struct {
@@ -22,7 +22,6 @@ type CreateContentParams struct {
SiteID string `json:"site_id"`
HtmlContent string `json:"html_content"`
OriginalTemplate sql.NullString `json:"original_template"`
Type string `json:"type"`
LastEditedBy string `json:"last_edited_by"`
}
@@ -32,7 +31,6 @@ func (q *Queries) CreateContent(ctx context.Context, arg CreateContentParams) (C
arg.SiteID,
arg.HtmlContent,
arg.OriginalTemplate,
arg.Type,
arg.LastEditedBy,
)
var i Content
@@ -41,7 +39,6 @@ func (q *Queries) CreateContent(ctx context.Context, arg CreateContentParams) (C
&i.SiteID,
&i.HtmlContent,
&i.OriginalTemplate,
&i.Type,
&i.CreatedAt,
&i.UpdatedAt,
&i.LastEditedBy,
@@ -75,7 +72,7 @@ func (q *Queries) DeleteContent(ctx context.Context, arg DeleteContentParams) er
}
const getAllContent = `-- name: GetAllContent :many
SELECT id, site_id, html_content, original_template, type, created_at, updated_at, last_edited_by
SELECT id, site_id, html_content, original_template, created_at, updated_at, last_edited_by
FROM content
WHERE site_id = $1
ORDER BY updated_at DESC
@@ -95,7 +92,6 @@ func (q *Queries) GetAllContent(ctx context.Context, siteID string) ([]Content,
&i.SiteID,
&i.HtmlContent,
&i.OriginalTemplate,
&i.Type,
&i.CreatedAt,
&i.UpdatedAt,
&i.LastEditedBy,
@@ -114,7 +110,7 @@ func (q *Queries) GetAllContent(ctx context.Context, siteID string) ([]Content,
}
const getBulkContent = `-- name: GetBulkContent :many
SELECT id, site_id, html_content, original_template, type, created_at, updated_at, last_edited_by
SELECT id, site_id, html_content, original_template, created_at, updated_at, last_edited_by
FROM content
WHERE site_id = $1 AND id IN ($2)
`
@@ -149,7 +145,6 @@ func (q *Queries) GetBulkContent(ctx context.Context, arg GetBulkContentParams)
&i.SiteID,
&i.HtmlContent,
&i.OriginalTemplate,
&i.Type,
&i.CreatedAt,
&i.UpdatedAt,
&i.LastEditedBy,
@@ -168,7 +163,7 @@ func (q *Queries) GetBulkContent(ctx context.Context, arg GetBulkContentParams)
}
const getContent = `-- name: GetContent :one
SELECT id, site_id, html_content, original_template, type, created_at, updated_at, last_edited_by
SELECT id, site_id, html_content, original_template, created_at, updated_at, last_edited_by
FROM content
WHERE id = $1 AND site_id = $2
`
@@ -186,7 +181,6 @@ func (q *Queries) GetContent(ctx context.Context, arg GetContentParams) (Content
&i.SiteID,
&i.HtmlContent,
&i.OriginalTemplate,
&i.Type,
&i.CreatedAt,
&i.UpdatedAt,
&i.LastEditedBy,
@@ -196,14 +190,13 @@ func (q *Queries) GetContent(ctx context.Context, arg GetContentParams) (Content
const updateContent = `-- name: UpdateContent :one
UPDATE content
SET html_content = $1, type = $2, last_edited_by = $3
WHERE id = $4 AND site_id = $5
RETURNING id, site_id, html_content, original_template, type, created_at, updated_at, last_edited_by
SET html_content = $1, last_edited_by = $2
WHERE id = $3 AND site_id = $4
RETURNING id, site_id, html_content, original_template, created_at, updated_at, last_edited_by
`
type UpdateContentParams struct {
HtmlContent string `json:"html_content"`
Type string `json:"type"`
LastEditedBy string `json:"last_edited_by"`
ID string `json:"id"`
SiteID string `json:"site_id"`
@@ -212,7 +205,6 @@ type UpdateContentParams struct {
func (q *Queries) UpdateContent(ctx context.Context, arg UpdateContentParams) (Content, error) {
row := q.db.QueryRowContext(ctx, updateContent,
arg.HtmlContent,
arg.Type,
arg.LastEditedBy,
arg.ID,
arg.SiteID,
@@ -223,7 +215,6 @@ func (q *Queries) UpdateContent(ctx context.Context, arg UpdateContentParams) (C
&i.SiteID,
&i.HtmlContent,
&i.OriginalTemplate,
&i.Type,
&i.CreatedAt,
&i.UpdatedAt,
&i.LastEditedBy,
@@ -232,13 +223,12 @@ func (q *Queries) UpdateContent(ctx context.Context, arg UpdateContentParams) (C
}
const upsertContent = `-- name: UpsertContent :one
INSERT INTO content (id, site_id, html_content, original_template, type, last_edited_by)
VALUES ($1, $2, $3, $4, $5, $6)
INSERT INTO content (id, site_id, html_content, original_template, last_edited_by)
VALUES ($1, $2, $3, $4, $5)
ON CONFLICT(id, site_id) DO UPDATE SET
html_content = EXCLUDED.html_content,
type = EXCLUDED.type,
last_edited_by = EXCLUDED.last_edited_by
RETURNING id, site_id, html_content, original_template, type, created_at, updated_at, last_edited_by
RETURNING id, site_id, html_content, original_template, created_at, updated_at, last_edited_by
`
type UpsertContentParams struct {
@@ -246,7 +236,6 @@ type UpsertContentParams struct {
SiteID string `json:"site_id"`
HtmlContent string `json:"html_content"`
OriginalTemplate sql.NullString `json:"original_template"`
Type string `json:"type"`
LastEditedBy string `json:"last_edited_by"`
}
@@ -256,7 +245,6 @@ func (q *Queries) UpsertContent(ctx context.Context, arg UpsertContentParams) (C
arg.SiteID,
arg.HtmlContent,
arg.OriginalTemplate,
arg.Type,
arg.LastEditedBy,
)
var i Content
@@ -265,7 +253,6 @@ func (q *Queries) UpsertContent(ctx context.Context, arg UpsertContentParams) (C
&i.SiteID,
&i.HtmlContent,
&i.OriginalTemplate,
&i.Type,
&i.CreatedAt,
&i.UpdatedAt,
&i.LastEditedBy,

View File

@@ -13,7 +13,6 @@ type Content struct {
SiteID string `json:"site_id"`
HtmlContent string `json:"html_content"`
OriginalTemplate sql.NullString `json:"original_template"`
Type string `json:"type"`
CreatedAt int64 `json:"created_at"`
UpdatedAt int64 `json:"updated_at"`
LastEditedBy string `json:"last_edited_by"`
@@ -25,7 +24,6 @@ type ContentVersion struct {
SiteID string `json:"site_id"`
HtmlContent string `json:"html_content"`
OriginalTemplate sql.NullString `json:"original_template"`
Type string `json:"type"`
CreatedAt int64 `json:"created_at"`
CreatedBy string `json:"created_by"`
}

View File

@@ -5,7 +5,6 @@ CREATE TABLE content (
site_id TEXT NOT NULL,
html_content TEXT NOT NULL,
original_template TEXT,
type TEXT NOT NULL,
created_at BIGINT DEFAULT EXTRACT(EPOCH FROM NOW()) NOT NULL,
updated_at BIGINT DEFAULT EXTRACT(EPOCH FROM NOW()) NOT NULL,
last_edited_by TEXT DEFAULT 'system' NOT NULL,
@@ -19,7 +18,6 @@ CREATE TABLE content_versions (
site_id TEXT NOT NULL,
html_content TEXT NOT NULL,
original_template TEXT,
type TEXT NOT NULL,
created_at BIGINT DEFAULT EXTRACT(EPOCH FROM NOW()) NOT NULL,
created_by TEXT DEFAULT 'system' NOT NULL
);

View File

@@ -4,7 +4,6 @@ CREATE TABLE IF NOT EXISTS content (
site_id TEXT NOT NULL,
html_content TEXT NOT NULL,
original_template TEXT,
type TEXT NOT NULL CHECK (type IN ('text', 'link')),
created_at BIGINT DEFAULT (EXTRACT(EPOCH FROM NOW())) NOT NULL,
updated_at BIGINT DEFAULT (EXTRACT(EPOCH FROM NOW())) NOT NULL,
last_edited_by TEXT DEFAULT 'system' NOT NULL,
@@ -18,7 +17,6 @@ CREATE TABLE IF NOT EXISTS content_versions (
site_id TEXT NOT NULL,
html_content TEXT NOT NULL,
original_template TEXT,
type TEXT NOT NULL,
created_at BIGINT DEFAULT (EXTRACT(EPOCH FROM NOW())) NOT NULL,
created_by TEXT DEFAULT 'system' NOT NULL
);

View File

@@ -57,7 +57,6 @@ CREATE TABLE IF NOT EXISTS content (
site_id TEXT NOT NULL,
html_content TEXT NOT NULL,
original_template TEXT,
type TEXT NOT NULL CHECK (type IN ('text', 'link')),
created_at BIGINT DEFAULT (EXTRACT(EPOCH FROM NOW())) NOT NULL,
updated_at BIGINT DEFAULT (EXTRACT(EPOCH FROM NOW())) NOT NULL,
last_edited_by TEXT DEFAULT 'system' NOT NULL,
@@ -77,7 +76,6 @@ CREATE TABLE IF NOT EXISTS content_versions (
site_id TEXT NOT NULL,
html_content TEXT NOT NULL,
original_template TEXT,
type TEXT NOT NULL,
created_at BIGINT DEFAULT (EXTRACT(EPOCH FROM NOW())) NOT NULL,
created_by TEXT DEFAULT 'system' NOT NULL
)

View File

@@ -11,8 +11,8 @@ import (
)
const createContentVersion = `-- name: CreateContentVersion :exec
INSERT INTO content_versions (content_id, site_id, html_content, original_template, type, created_by)
VALUES ($1, $2, $3, $4, $5, $6)
INSERT INTO content_versions (content_id, site_id, html_content, original_template, created_by)
VALUES ($1, $2, $3, $4, $5)
`
type CreateContentVersionParams struct {
@@ -20,7 +20,6 @@ type CreateContentVersionParams struct {
SiteID string `json:"site_id"`
HtmlContent string `json:"html_content"`
OriginalTemplate sql.NullString `json:"original_template"`
Type string `json:"type"`
CreatedBy string `json:"created_by"`
}
@@ -30,7 +29,6 @@ func (q *Queries) CreateContentVersion(ctx context.Context, arg CreateContentVer
arg.SiteID,
arg.HtmlContent,
arg.OriginalTemplate,
arg.Type,
arg.CreatedBy,
)
return err
@@ -53,7 +51,7 @@ func (q *Queries) DeleteOldVersions(ctx context.Context, arg DeleteOldVersionsPa
const getAllVersionsForSite = `-- name: GetAllVersionsForSite :many
SELECT
cv.version_id, cv.content_id, cv.site_id, cv.html_content, cv.original_template, cv.type, cv.created_at, cv.created_by,
cv.version_id, cv.content_id, cv.site_id, cv.html_content, cv.original_template, cv.created_at, cv.created_by,
c.html_content as current_html_content
FROM content_versions cv
LEFT JOIN content c ON cv.content_id = c.id AND cv.site_id = c.site_id
@@ -73,7 +71,6 @@ type GetAllVersionsForSiteRow struct {
SiteID string `json:"site_id"`
HtmlContent string `json:"html_content"`
OriginalTemplate sql.NullString `json:"original_template"`
Type string `json:"type"`
CreatedAt int64 `json:"created_at"`
CreatedBy string `json:"created_by"`
CurrentHtmlContent sql.NullString `json:"current_html_content"`
@@ -94,7 +91,6 @@ func (q *Queries) GetAllVersionsForSite(ctx context.Context, arg GetAllVersionsF
&i.SiteID,
&i.HtmlContent,
&i.OriginalTemplate,
&i.Type,
&i.CreatedAt,
&i.CreatedBy,
&i.CurrentHtmlContent,
@@ -113,7 +109,7 @@ func (q *Queries) GetAllVersionsForSite(ctx context.Context, arg GetAllVersionsF
}
const getContentVersion = `-- name: GetContentVersion :one
SELECT version_id, content_id, site_id, html_content, original_template, type, created_at, created_by
SELECT version_id, content_id, site_id, html_content, original_template, created_at, created_by
FROM content_versions
WHERE version_id = $1
`
@@ -127,7 +123,6 @@ func (q *Queries) GetContentVersion(ctx context.Context, versionID int32) (Conte
&i.SiteID,
&i.HtmlContent,
&i.OriginalTemplate,
&i.Type,
&i.CreatedAt,
&i.CreatedBy,
)
@@ -135,7 +130,7 @@ func (q *Queries) GetContentVersion(ctx context.Context, versionID int32) (Conte
}
const getContentVersionHistory = `-- name: GetContentVersionHistory :many
SELECT version_id, content_id, site_id, html_content, original_template, type, created_at, created_by
SELECT version_id, content_id, site_id, html_content, original_template, created_at, created_by
FROM content_versions
WHERE content_id = $1 AND site_id = $2
ORDER BY created_at DESC
@@ -163,7 +158,6 @@ func (q *Queries) GetContentVersionHistory(ctx context.Context, arg GetContentVe
&i.SiteID,
&i.HtmlContent,
&i.OriginalTemplate,
&i.Type,
&i.CreatedAt,
&i.CreatedBy,
); err != nil {

View File

@@ -1,38 +1,37 @@
-- name: GetContent :one
SELECT id, site_id, html_content, original_template, type, created_at, updated_at, last_edited_by
SELECT id, site_id, html_content, original_template, created_at, updated_at, last_edited_by
FROM content
WHERE id = sqlc.arg(id) AND site_id = sqlc.arg(site_id);
-- name: GetAllContent :many
SELECT id, site_id, html_content, original_template, type, created_at, updated_at, last_edited_by
SELECT id, site_id, html_content, original_template, created_at, updated_at, last_edited_by
FROM content
WHERE site_id = sqlc.arg(site_id)
ORDER BY updated_at DESC;
-- name: GetBulkContent :many
SELECT id, site_id, html_content, original_template, type, created_at, updated_at, last_edited_by
SELECT id, site_id, html_content, original_template, created_at, updated_at, last_edited_by
FROM content
WHERE site_id = sqlc.arg(site_id) AND id IN (sqlc.slice('ids'));
-- name: CreateContent :one
INSERT INTO content (id, site_id, html_content, original_template, type, last_edited_by)
VALUES (sqlc.arg(id), sqlc.arg(site_id), sqlc.arg(html_content), sqlc.arg(original_template), sqlc.arg(type), sqlc.arg(last_edited_by))
RETURNING id, site_id, html_content, original_template, type, created_at, updated_at, last_edited_by;
INSERT INTO content (id, site_id, html_content, original_template, last_edited_by)
VALUES (sqlc.arg(id), sqlc.arg(site_id), sqlc.arg(html_content), sqlc.arg(original_template), sqlc.arg(last_edited_by))
RETURNING id, site_id, html_content, original_template, created_at, updated_at, last_edited_by;
-- name: UpdateContent :one
UPDATE content
SET html_content = sqlc.arg(html_content), type = sqlc.arg(type), last_edited_by = sqlc.arg(last_edited_by)
SET html_content = sqlc.arg(html_content), last_edited_by = sqlc.arg(last_edited_by)
WHERE id = sqlc.arg(id) AND site_id = sqlc.arg(site_id)
RETURNING id, site_id, html_content, original_template, type, created_at, updated_at, last_edited_by;
RETURNING id, site_id, html_content, original_template, created_at, updated_at, last_edited_by;
-- name: UpsertContent :one
INSERT INTO content (id, site_id, html_content, original_template, type, last_edited_by)
VALUES (sqlc.arg(id), sqlc.arg(site_id), sqlc.arg(html_content), sqlc.arg(original_template), sqlc.arg(type), sqlc.arg(last_edited_by))
INSERT INTO content (id, site_id, html_content, original_template, last_edited_by)
VALUES (sqlc.arg(id), sqlc.arg(site_id), sqlc.arg(html_content), sqlc.arg(original_template), sqlc.arg(last_edited_by))
ON CONFLICT(id, site_id) DO UPDATE SET
html_content = EXCLUDED.html_content,
type = EXCLUDED.type,
last_edited_by = EXCLUDED.last_edited_by
RETURNING id, site_id, html_content, original_template, type, created_at, updated_at, last_edited_by;
RETURNING id, site_id, html_content, original_template, created_at, updated_at, last_edited_by;
-- name: DeleteContent :exec
DELETE FROM content

View File

@@ -1,22 +1,22 @@
-- name: CreateContentVersion :exec
INSERT INTO content_versions (content_id, site_id, html_content, original_template, type, created_by)
VALUES (sqlc.arg(content_id), sqlc.arg(site_id), sqlc.arg(html_content), sqlc.arg(original_template), sqlc.arg(type), sqlc.arg(created_by));
INSERT INTO content_versions (content_id, site_id, html_content, original_template, created_by)
VALUES (sqlc.arg(content_id), sqlc.arg(site_id), sqlc.arg(html_content), sqlc.arg(original_template), sqlc.arg(created_by));
-- name: GetContentVersionHistory :many
SELECT version_id, content_id, site_id, html_content, original_template, type, created_at, created_by
SELECT version_id, content_id, site_id, html_content, original_template, created_at, created_by
FROM content_versions
WHERE content_id = sqlc.arg(content_id) AND site_id = sqlc.arg(site_id)
ORDER BY created_at DESC
LIMIT sqlc.arg(limit_count);
-- name: GetContentVersion :one
SELECT version_id, content_id, site_id, html_content, original_template, type, created_at, created_by
SELECT version_id, content_id, site_id, html_content, original_template, created_at, created_by
FROM content_versions
WHERE version_id = sqlc.arg(version_id);
-- name: GetAllVersionsForSite :many
SELECT
cv.version_id, cv.content_id, cv.site_id, cv.html_content, cv.original_template, cv.type, cv.created_at, cv.created_by,
cv.version_id, cv.content_id, cv.site_id, cv.html_content, cv.original_template, cv.created_at, cv.created_by,
c.html_content as current_html_content
FROM content_versions cv
LEFT JOIN content c ON cv.content_id = c.id AND cv.site_id = c.site_id

View File

@@ -12,9 +12,9 @@ import (
)
const createContent = `-- name: CreateContent :one
INSERT INTO content (id, site_id, html_content, original_template, type, last_edited_by)
VALUES (?1, ?2, ?3, ?4, ?5, ?6)
RETURNING id, site_id, html_content, original_template, type, created_at, updated_at, last_edited_by
INSERT INTO content (id, site_id, html_content, original_template, last_edited_by)
VALUES (?1, ?2, ?3, ?4, ?5)
RETURNING id, site_id, html_content, original_template, created_at, updated_at, last_edited_by
`
type CreateContentParams struct {
@@ -22,7 +22,6 @@ type CreateContentParams struct {
SiteID string `json:"site_id"`
HtmlContent string `json:"html_content"`
OriginalTemplate sql.NullString `json:"original_template"`
Type string `json:"type"`
LastEditedBy string `json:"last_edited_by"`
}
@@ -32,7 +31,6 @@ func (q *Queries) CreateContent(ctx context.Context, arg CreateContentParams) (C
arg.SiteID,
arg.HtmlContent,
arg.OriginalTemplate,
arg.Type,
arg.LastEditedBy,
)
var i Content
@@ -41,7 +39,6 @@ func (q *Queries) CreateContent(ctx context.Context, arg CreateContentParams) (C
&i.SiteID,
&i.HtmlContent,
&i.OriginalTemplate,
&i.Type,
&i.CreatedAt,
&i.UpdatedAt,
&i.LastEditedBy,
@@ -75,7 +72,7 @@ func (q *Queries) DeleteContent(ctx context.Context, arg DeleteContentParams) er
}
const getAllContent = `-- name: GetAllContent :many
SELECT id, site_id, html_content, original_template, type, created_at, updated_at, last_edited_by
SELECT id, site_id, html_content, original_template, created_at, updated_at, last_edited_by
FROM content
WHERE site_id = ?1
ORDER BY updated_at DESC
@@ -95,7 +92,6 @@ func (q *Queries) GetAllContent(ctx context.Context, siteID string) ([]Content,
&i.SiteID,
&i.HtmlContent,
&i.OriginalTemplate,
&i.Type,
&i.CreatedAt,
&i.UpdatedAt,
&i.LastEditedBy,
@@ -114,7 +110,7 @@ func (q *Queries) GetAllContent(ctx context.Context, siteID string) ([]Content,
}
const getBulkContent = `-- name: GetBulkContent :many
SELECT id, site_id, html_content, original_template, type, created_at, updated_at, last_edited_by
SELECT id, site_id, html_content, original_template, created_at, updated_at, last_edited_by
FROM content
WHERE site_id = ?1 AND id IN (/*SLICE:ids*/?)
`
@@ -149,7 +145,6 @@ func (q *Queries) GetBulkContent(ctx context.Context, arg GetBulkContentParams)
&i.SiteID,
&i.HtmlContent,
&i.OriginalTemplate,
&i.Type,
&i.CreatedAt,
&i.UpdatedAt,
&i.LastEditedBy,
@@ -168,7 +163,7 @@ func (q *Queries) GetBulkContent(ctx context.Context, arg GetBulkContentParams)
}
const getContent = `-- name: GetContent :one
SELECT id, site_id, html_content, original_template, type, created_at, updated_at, last_edited_by
SELECT id, site_id, html_content, original_template, created_at, updated_at, last_edited_by
FROM content
WHERE id = ?1 AND site_id = ?2
`
@@ -186,7 +181,6 @@ func (q *Queries) GetContent(ctx context.Context, arg GetContentParams) (Content
&i.SiteID,
&i.HtmlContent,
&i.OriginalTemplate,
&i.Type,
&i.CreatedAt,
&i.UpdatedAt,
&i.LastEditedBy,
@@ -196,14 +190,13 @@ func (q *Queries) GetContent(ctx context.Context, arg GetContentParams) (Content
const updateContent = `-- name: UpdateContent :one
UPDATE content
SET html_content = ?1, type = ?2, last_edited_by = ?3
WHERE id = ?4 AND site_id = ?5
RETURNING id, site_id, html_content, original_template, type, created_at, updated_at, last_edited_by
SET html_content = ?1, last_edited_by = ?2
WHERE id = ?3 AND site_id = ?4
RETURNING id, site_id, html_content, original_template, created_at, updated_at, last_edited_by
`
type UpdateContentParams struct {
HtmlContent string `json:"html_content"`
Type string `json:"type"`
LastEditedBy string `json:"last_edited_by"`
ID string `json:"id"`
SiteID string `json:"site_id"`
@@ -212,7 +205,6 @@ type UpdateContentParams struct {
func (q *Queries) UpdateContent(ctx context.Context, arg UpdateContentParams) (Content, error) {
row := q.db.QueryRowContext(ctx, updateContent,
arg.HtmlContent,
arg.Type,
arg.LastEditedBy,
arg.ID,
arg.SiteID,
@@ -223,7 +215,6 @@ func (q *Queries) UpdateContent(ctx context.Context, arg UpdateContentParams) (C
&i.SiteID,
&i.HtmlContent,
&i.OriginalTemplate,
&i.Type,
&i.CreatedAt,
&i.UpdatedAt,
&i.LastEditedBy,
@@ -232,13 +223,12 @@ func (q *Queries) UpdateContent(ctx context.Context, arg UpdateContentParams) (C
}
const upsertContent = `-- name: UpsertContent :one
INSERT INTO content (id, site_id, html_content, original_template, type, last_edited_by)
VALUES (?1, ?2, ?3, ?4, ?5, ?6)
INSERT INTO content (id, site_id, html_content, original_template, last_edited_by)
VALUES (?1, ?2, ?3, ?4, ?5)
ON CONFLICT(id, site_id) DO UPDATE SET
html_content = EXCLUDED.html_content,
type = EXCLUDED.type,
last_edited_by = EXCLUDED.last_edited_by
RETURNING id, site_id, html_content, original_template, type, created_at, updated_at, last_edited_by
RETURNING id, site_id, html_content, original_template, created_at, updated_at, last_edited_by
`
type UpsertContentParams struct {
@@ -246,7 +236,6 @@ type UpsertContentParams struct {
SiteID string `json:"site_id"`
HtmlContent string `json:"html_content"`
OriginalTemplate sql.NullString `json:"original_template"`
Type string `json:"type"`
LastEditedBy string `json:"last_edited_by"`
}
@@ -256,7 +245,6 @@ func (q *Queries) UpsertContent(ctx context.Context, arg UpsertContentParams) (C
arg.SiteID,
arg.HtmlContent,
arg.OriginalTemplate,
arg.Type,
arg.LastEditedBy,
)
var i Content
@@ -265,7 +253,6 @@ func (q *Queries) UpsertContent(ctx context.Context, arg UpsertContentParams) (C
&i.SiteID,
&i.HtmlContent,
&i.OriginalTemplate,
&i.Type,
&i.CreatedAt,
&i.UpdatedAt,
&i.LastEditedBy,

View File

@@ -13,7 +13,6 @@ type Content struct {
SiteID string `json:"site_id"`
HtmlContent string `json:"html_content"`
OriginalTemplate sql.NullString `json:"original_template"`
Type string `json:"type"`
CreatedAt int64 `json:"created_at"`
UpdatedAt int64 `json:"updated_at"`
LastEditedBy string `json:"last_edited_by"`
@@ -25,7 +24,6 @@ type ContentVersion struct {
SiteID string `json:"site_id"`
HtmlContent string `json:"html_content"`
OriginalTemplate sql.NullString `json:"original_template"`
Type string `json:"type"`
CreatedAt int64 `json:"created_at"`
CreatedBy string `json:"created_by"`
}

View File

@@ -5,7 +5,6 @@ CREATE TABLE content (
site_id TEXT NOT NULL,
html_content TEXT NOT NULL,
original_template TEXT,
type TEXT NOT NULL,
created_at INTEGER DEFAULT (strftime('%s', 'now')) NOT NULL,
updated_at INTEGER DEFAULT (strftime('%s', 'now')) NOT NULL,
last_edited_by TEXT DEFAULT 'system' NOT NULL,
@@ -19,7 +18,6 @@ CREATE TABLE content_versions (
site_id TEXT NOT NULL,
html_content TEXT NOT NULL,
original_template TEXT,
type TEXT NOT NULL,
created_at INTEGER DEFAULT (strftime('%s', 'now')) NOT NULL,
created_by TEXT DEFAULT 'system' NOT NULL
);

View File

@@ -4,7 +4,6 @@ CREATE TABLE IF NOT EXISTS content (
site_id TEXT NOT NULL,
html_content TEXT NOT NULL,
original_template TEXT,
type TEXT NOT NULL CHECK (type IN ('text', 'link')),
created_at INTEGER DEFAULT (strftime('%s', 'now')) NOT NULL,
updated_at INTEGER DEFAULT (strftime('%s', 'now')) NOT NULL,
last_edited_by TEXT DEFAULT 'system' NOT NULL,
@@ -18,7 +17,6 @@ CREATE TABLE IF NOT EXISTS content_versions (
site_id TEXT NOT NULL,
html_content TEXT NOT NULL,
original_template TEXT,
type TEXT NOT NULL,
created_at INTEGER DEFAULT (strftime('%s', 'now')) NOT NULL,
created_by TEXT DEFAULT 'system' NOT NULL
);

View File

@@ -15,7 +15,6 @@ CREATE TABLE IF NOT EXISTS content (
site_id TEXT NOT NULL,
html_content TEXT NOT NULL,
original_template TEXT,
type TEXT NOT NULL CHECK (type IN ('text', 'link')),
created_at INTEGER DEFAULT (strftime('%s', 'now')) NOT NULL,
updated_at INTEGER DEFAULT (strftime('%s', 'now')) NOT NULL,
last_edited_by TEXT DEFAULT 'system' NOT NULL,
@@ -35,7 +34,6 @@ CREATE TABLE IF NOT EXISTS content_versions (
site_id TEXT NOT NULL,
html_content TEXT NOT NULL,
original_template TEXT,
type TEXT NOT NULL,
created_at INTEGER DEFAULT (strftime('%s', 'now')) NOT NULL,
created_by TEXT DEFAULT 'system' NOT NULL
)

View File

@@ -11,8 +11,8 @@ import (
)
const createContentVersion = `-- name: CreateContentVersion :exec
INSERT INTO content_versions (content_id, site_id, html_content, original_template, type, created_by)
VALUES (?1, ?2, ?3, ?4, ?5, ?6)
INSERT INTO content_versions (content_id, site_id, html_content, original_template, created_by)
VALUES (?1, ?2, ?3, ?4, ?5)
`
type CreateContentVersionParams struct {
@@ -20,7 +20,6 @@ type CreateContentVersionParams struct {
SiteID string `json:"site_id"`
HtmlContent string `json:"html_content"`
OriginalTemplate sql.NullString `json:"original_template"`
Type string `json:"type"`
CreatedBy string `json:"created_by"`
}
@@ -30,7 +29,6 @@ func (q *Queries) CreateContentVersion(ctx context.Context, arg CreateContentVer
arg.SiteID,
arg.HtmlContent,
arg.OriginalTemplate,
arg.Type,
arg.CreatedBy,
)
return err
@@ -53,7 +51,7 @@ func (q *Queries) DeleteOldVersions(ctx context.Context, arg DeleteOldVersionsPa
const getAllVersionsForSite = `-- name: GetAllVersionsForSite :many
SELECT
cv.version_id, cv.content_id, cv.site_id, cv.html_content, cv.original_template, cv.type, cv.created_at, cv.created_by,
cv.version_id, cv.content_id, cv.site_id, cv.html_content, cv.original_template, cv.created_at, cv.created_by,
c.html_content as current_html_content
FROM content_versions cv
LEFT JOIN content c ON cv.content_id = c.id AND cv.site_id = c.site_id
@@ -73,7 +71,6 @@ type GetAllVersionsForSiteRow struct {
SiteID string `json:"site_id"`
HtmlContent string `json:"html_content"`
OriginalTemplate sql.NullString `json:"original_template"`
Type string `json:"type"`
CreatedAt int64 `json:"created_at"`
CreatedBy string `json:"created_by"`
CurrentHtmlContent sql.NullString `json:"current_html_content"`
@@ -94,7 +91,6 @@ func (q *Queries) GetAllVersionsForSite(ctx context.Context, arg GetAllVersionsF
&i.SiteID,
&i.HtmlContent,
&i.OriginalTemplate,
&i.Type,
&i.CreatedAt,
&i.CreatedBy,
&i.CurrentHtmlContent,
@@ -113,7 +109,7 @@ func (q *Queries) GetAllVersionsForSite(ctx context.Context, arg GetAllVersionsF
}
const getContentVersion = `-- name: GetContentVersion :one
SELECT version_id, content_id, site_id, html_content, original_template, type, created_at, created_by
SELECT version_id, content_id, site_id, html_content, original_template, created_at, created_by
FROM content_versions
WHERE version_id = ?1
`
@@ -127,7 +123,6 @@ func (q *Queries) GetContentVersion(ctx context.Context, versionID int64) (Conte
&i.SiteID,
&i.HtmlContent,
&i.OriginalTemplate,
&i.Type,
&i.CreatedAt,
&i.CreatedBy,
)
@@ -135,7 +130,7 @@ func (q *Queries) GetContentVersion(ctx context.Context, versionID int64) (Conte
}
const getContentVersionHistory = `-- name: GetContentVersionHistory :many
SELECT version_id, content_id, site_id, html_content, original_template, type, created_at, created_by
SELECT version_id, content_id, site_id, html_content, original_template, created_at, created_by
FROM content_versions
WHERE content_id = ?1 AND site_id = ?2
ORDER BY created_at DESC
@@ -163,7 +158,6 @@ func (q *Queries) GetContentVersionHistory(ctx context.Context, arg GetContentVe
&i.SiteID,
&i.HtmlContent,
&i.OriginalTemplate,
&i.Type,
&i.CreatedAt,
&i.CreatedBy,
); err != nil {

View File

@@ -46,7 +46,6 @@ func (c *DatabaseClient) GetContent(siteID, contentID string) (*ContentItem, err
SiteID: content.SiteID,
HTMLContent: content.HtmlContent,
OriginalTemplate: getStringFromNullString(content.OriginalTemplate),
Type: content.Type,
LastEditedBy: content.LastEditedBy,
}, nil
@@ -63,7 +62,6 @@ func (c *DatabaseClient) GetContent(siteID, contentID string) (*ContentItem, err
SiteID: content.SiteID,
HTMLContent: content.HtmlContent,
OriginalTemplate: getStringFromNullString(content.OriginalTemplate),
Type: content.Type,
LastEditedBy: content.LastEditedBy,
}, nil
@@ -91,7 +89,6 @@ func (c *DatabaseClient) GetBulkContent(siteID string, contentIDs []string) (map
SiteID: content.SiteID,
HTMLContent: content.HtmlContent,
OriginalTemplate: getStringFromNullString(content.OriginalTemplate),
Type: content.Type,
LastEditedBy: content.LastEditedBy,
}
}
@@ -113,7 +110,6 @@ func (c *DatabaseClient) GetBulkContent(siteID string, contentIDs []string) (map
SiteID: content.SiteID,
HTMLContent: content.HtmlContent,
OriginalTemplate: getStringFromNullString(content.OriginalTemplate),
Type: content.Type,
LastEditedBy: content.LastEditedBy,
}
}
@@ -140,7 +136,6 @@ func (c *DatabaseClient) GetAllContent(siteID string) (map[string]ContentItem, e
SiteID: content.SiteID,
HTMLContent: content.HtmlContent,
OriginalTemplate: getStringFromNullString(content.OriginalTemplate),
Type: content.Type,
LastEditedBy: content.LastEditedBy,
}
}
@@ -159,7 +154,6 @@ func (c *DatabaseClient) GetAllContent(siteID string) (map[string]ContentItem, e
SiteID: content.SiteID,
HTMLContent: content.HtmlContent,
OriginalTemplate: getStringFromNullString(content.OriginalTemplate),
Type: content.Type,
LastEditedBy: content.LastEditedBy,
}
}
@@ -171,7 +165,7 @@ func (c *DatabaseClient) GetAllContent(siteID string) (map[string]ContentItem, e
}
// CreateContent creates a new content item
func (c *DatabaseClient) CreateContent(siteID, contentID, htmlContent, originalTemplate, contentType, lastEditedBy string) (*ContentItem, error) {
func (c *DatabaseClient) CreateContent(siteID, contentID, htmlContent, originalTemplate, lastEditedBy string) (*ContentItem, error) {
switch c.database.GetDBType() {
case "sqlite3":
content, err := c.database.GetSQLiteQueries().CreateContent(context.Background(), sqlite.CreateContentParams{
@@ -179,7 +173,6 @@ func (c *DatabaseClient) CreateContent(siteID, contentID, htmlContent, originalT
SiteID: siteID,
HtmlContent: htmlContent,
OriginalTemplate: toNullString(originalTemplate),
Type: contentType,
LastEditedBy: lastEditedBy,
})
if err != nil {
@@ -190,7 +183,6 @@ func (c *DatabaseClient) CreateContent(siteID, contentID, htmlContent, originalT
SiteID: content.SiteID,
HTMLContent: content.HtmlContent,
OriginalTemplate: getStringFromNullString(content.OriginalTemplate),
Type: content.Type,
LastEditedBy: content.LastEditedBy,
}, nil
@@ -200,7 +192,6 @@ func (c *DatabaseClient) CreateContent(siteID, contentID, htmlContent, originalT
SiteID: siteID,
HtmlContent: htmlContent,
OriginalTemplate: toNullString(originalTemplate),
Type: contentType,
LastEditedBy: lastEditedBy,
})
if err != nil {
@@ -211,7 +202,6 @@ func (c *DatabaseClient) CreateContent(siteID, contentID, htmlContent, originalT
SiteID: content.SiteID,
HTMLContent: content.HtmlContent,
OriginalTemplate: getStringFromNullString(content.OriginalTemplate),
Type: content.Type,
LastEditedBy: content.LastEditedBy,
}, nil
@@ -220,7 +210,7 @@ func (c *DatabaseClient) CreateContent(siteID, contentID, htmlContent, originalT
}
}
// Helper function to convert string to sql.NullString
// Helper function to convert string to sql.NullString
func toNullString(s string) sql.NullString {
if s == "" {
return sql.NullString{Valid: false}

View File

@@ -35,7 +35,6 @@ type ContentResult struct {
type ProcessedElement struct {
Node *html.Node // HTML node
ID string // Generated content ID
Type string // Content type (text, link)
Content string // Injected content (if any)
Generated bool // Whether ID was generated (vs existing)
Tag string // Element tag name
@@ -48,7 +47,7 @@ type ContentClient interface {
GetContent(siteID, contentID string) (*ContentItem, error)
GetBulkContent(siteID string, contentIDs []string) (map[string]ContentItem, error)
GetAllContent(siteID string) (map[string]ContentItem, error)
CreateContent(siteID, contentID, htmlContent, originalTemplate, contentType, lastEditedBy string) (*ContentItem, error)
CreateContent(siteID, contentID, htmlContent, originalTemplate, lastEditedBy string) (*ContentItem, error)
}
// ContentItem represents a piece of content from the database
@@ -57,7 +56,6 @@ type ContentItem struct {
SiteID string `json:"site_id"`
HTMLContent string `json:"html_content"`
OriginalTemplate string `json:"original_template"`
Type string `json:"type"`
UpdatedAt string `json:"updated_at"`
LastEditedBy string `json:"last_edited_by,omitempty"`
}

View File

@@ -179,40 +179,149 @@ func isContainer(node *html.Node) bool {
"main": true,
"aside": true,
"nav": true,
"ul": true, // Phase 3: Lists are containers
"ol": true,
}
return containerTags[node.Data]
}
// findViableChildren finds all child elements that are viable for editing
// findViableChildren finds all descendant elements that should get .insertr class
// Phase 3: Recursive traversal with block/inline classification and boundary respect
func findViableChildren(node *html.Node) []*html.Node {
var viable []*html.Node
traverseForViableElements(node, &viable)
return viable
}
// traverseForViableElements recursively traverses all descendants, stopping at .insertr boundaries
func traverseForViableElements(node *html.Node, viable *[]*html.Node) {
for child := node.FirstChild; child != nil; child = child.NextSibling {
// Skip whitespace-only text nodes
if child.Type == html.TextNode {
if strings.TrimSpace(child.Data) == "" {
continue
}
}
// Only consider element nodes
if child.Type != html.ElementNode {
continue
}
// Skip self-closing elements for now
if isSelfClosing(child) {
// BOUNDARY: Stop if element already has .insertr class
if hasInsertrClass(child) {
continue
}
// Check if element has editable content (improved logic)
if hasEditableContent(child) {
viable = append(viable, child)
// Skip deferred complex elements (tables, forms)
if isDeferredElement(child) {
continue
}
// Determine if this element should get .insertr
if shouldGetInsertrClass(child) {
*viable = append(*viable, child)
// Don't traverse children - they're handled by this element's expansion
continue
}
// Continue traversing if this is just a container
traverseForViableElements(child, viable)
}
}
// Phase 3: Block vs Inline element classification
func isBlockElement(node *html.Node) bool {
blockTags := map[string]bool{
// Content blocks
"h1": true, "h2": true, "h3": true, "h4": true, "h5": true, "h6": true,
"p": true, "div": true, "article": true, "section": true, "nav": true,
"header": true, "footer": true, "main": true, "aside": true,
// Lists
"ul": true, "ol": true, "li": true,
// Interactive (when at block level)
"button": true, "a": true, "img": true, "video": true, "audio": true,
}
return viable
return blockTags[node.Data]
}
// isInlineElement checks if element is inline formatting (never gets .insertr)
func isInlineElement(node *html.Node) bool {
inlineTags := map[string]bool{
"strong": true, "b": true, "em": true, "i": true, "span": true,
"code": true, "small": true, "sub": true, "sup": true, "br": true,
"mark": true, "kbd": true,
}
return inlineTags[node.Data]
}
// isContextSensitive checks if element can be block or inline (a, button)
func isContextSensitive(node *html.Node) bool {
contextTags := map[string]bool{
"a": true,
"button": true,
}
return contextTags[node.Data]
}
// isInBlockContext determines if context-sensitive element should be treated as block
func isInBlockContext(node *html.Node) bool {
parent := node.Parent
if parent == nil || parent.Type != html.ElementNode {
return true
}
// If parent is a content element, this is inline formatting
contentElements := map[string]bool{
"p": true, "h1": true, "h2": true, "h3": true, "h4": true, "h5": true, "h6": true,
"li": true, "td": true, "th": true,
}
return !contentElements[parent.Data]
}
// shouldGetInsertrClass determines if element should receive .insertr class
func shouldGetInsertrClass(node *html.Node) bool {
// Always block elements get .insertr
if isBlockElement(node) && !isContextSensitive(node) {
return true
}
// Context-sensitive elements depend on parent context
if isContextSensitive(node) {
return isInBlockContext(node)
}
// Inline elements never get .insertr
if isInlineElement(node) {
return false
}
// Self-closing elements - only img gets .insertr when block-level
if isSelfClosing(node) {
return node.Data == "img" && isInBlockContext(node)
}
return false
}
// isDeferredElement checks for complex elements that need separate planning
func isDeferredElement(node *html.Node) bool {
deferredTags := map[string]bool{
"table": true, "tr": true, "td": true, "th": true,
"thead": true, "tbody": true, "tfoot": true,
"form": true, "input": true, "textarea": true, "select": true, "option": true,
}
return deferredTags[node.Data]
}
// hasInsertrClass checks if node has class="insertr"
func hasInsertrClass(node *html.Node) bool {
classes := GetClasses(node)
for _, class := range classes {
if class == "insertr" {
return true
}
}
return false
}
// findViableChildrenLegacy uses the old text-only logic for backwards compatibility