From 1980b8d30596d331283e06ca9ee3cb406bdd826b Mon Sep 17 00:00:00 2001 From: Joakim Date: Thu, 11 Sep 2025 16:53:05 +0200 Subject: [PATCH] fix: preserve element attributes and styling during markdown injection Critical fixes: - Fixed HTML injection to preserve original element attributes, classes, and styling - Updated markdown processor to generate inline content instead of wrapped paragraphs - Enhanced content type handling: database type now takes precedence over parser detection - Eliminated nested

tags issue that was causing invalid HTML Key improvements: - Elements like

now maintain all attributes - Markdown **bold**, *italic*, [links](url) inject as inline formatted content - Database content type (markdown/text/link) overrides parser auto-detection - Clean HTML output without structural corruption Before:

**bold**

(broken) After:

**bold text**

(clean) Server remains source of truth for markdown processing with zero runtime overhead. --- demo-site/about.html | 242 +++++++++++++++++------------------ demo-site/index.html | 144 +++++++++++---------- internal/content/enhancer.go | 16 ++- internal/content/injector.go | 7 +- internal/content/markdown.go | 17 ++- 5 files changed, 222 insertions(+), 204 deletions(-) diff --git a/demo-site/about.html b/demo-site/about.html index 88af869..3ec8475 100644 --- a/demo-site/about.html +++ b/demo-site/about.html @@ -1,136 +1,136 @@ - - - About - Acme Consulting Services - + + + About - Acme Consulting Services + - - - -
-
-

About Acme Consulting

-

We're a team of experienced consultants dedicated to helping small businesses thrive in today's competitive marketplace.

-
-
+ +
+
+

About Acme Consulting

+

We're a team of experienced consultants dedicated to helping small businesses thrive in today's competitive marketplace.

+
+
- -
-
-

Our Story

-
-

Founded in 2020, 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.

- -

Our founders, with combined experience of over 30 years in business strategy, operations, and technology, recognized that the traditional consulting model wasn't serving the needs of growing businesses. We set out to change that.

- -

Today, we've helped over **200 businesses** streamline their operations, clarify their strategy, and achieve sustainable growth. Our approach combines proven methodologies with a deep understanding of the unique challenges facing small to medium-sized businesses.

-
-
-
+ +
+
+

Our Story

+
+

Founded in 2020, 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.

+ +

Our founders, with combined experience of over 30 years in business strategy, operations, and technology, recognized that the traditional consulting model wasn't serving the needs of growing businesses. We set out to change that.

+ +

Today, we've helped over **200 businesses** streamline their operations, clarify their strategy, and achieve sustainable growth. Our approach combines proven methodologies with a deep understanding of the unique challenges facing small to medium-sized businesses.

+
+
+
- -
-
-

Our Team

-

We're a diverse group of strategists, operators, and technology experts united by our passion for helping businesses succeed.

- -
-
-
-

Sarah Chen

-

Founder & CEO

-

Former McKinsey consultant with 15 years of experience in strategy and operations. MBA from Stanford.

-
-
-
-
-

Michael Rodriguez

-

Head of Operations

-

20 years in manufacturing and supply chain optimization. Expert in lean methodologies and process improvement.

-
-
-
-
-

Emma Thompson

-

Digital Strategy Lead

-

Former tech startup founder turned consultant. Specializes in digital transformation and technology adoption.

-
-
-
-
-
+ +
+
+

Our Team

+

We're a diverse group of strategists, operators, and technology experts united by our passion for helping businesses succeed.

+ +
+
+
+

Sarah Chen

+

Founder & CEO

+

Former McKinsey consultant with 15 years of experience in strategy and operations. MBA from Stanford.

+
+
+
+
+

Michael Rodriguez

+

Head of Operations

+

20 years in manufacturing and supply chain optimization. Expert in lean methodologies and process improvement.

+
+
+
+
+

Emma Thompson

+

Digital Strategy Lead

+

Former tech startup founder turned consultant. Specializes in digital transformation and technology adoption.

+
+
+
+
+
- -
-
-

Our Values

-
-
-

Client-First

-

Every recommendation we make is designed with your specific business context and goals in mind.

-
-
-

Practical Solutions

-

We believe in strategies that you can actually implement with your current resources and capabilities.

-
-
-

Long-term Partnership

-

We're not just consultants; we're partners in your business success for the long haul.

-
-
-
-
+ +
+
+

Our Values

+
+
+

Client-First

+

Every recommendation we make is designed with your specific business context and goals in mind.

+
+
+

Practical Solutions

+

We believe in strategies that you can actually implement with your current resources and capabilities.

+
+
+

Long-term Partnership

+

We're not just consultants; we're partners in your business success for the long haul.

+
+
+
+
- -
-
-

Feature Tests

- - -
-

Test 1: Container Expansion (.insertr)

-
-

This paragraph should be individually editable with a textarea.

-

This second paragraph should also be individually editable.

-

Each paragraph should get its own modal when clicked.

-
-
- - -
-

Test 2: Group Editing (.insertr-group)

-
-

This paragraph is part of a group.

-

Clicking anywhere should open one markdown editor with rich formatting.

-

All content should be editable together as markdown with proper HTML conversion.

-
-
-
-
+ +
+
+

Feature Tests

+ + +
+

Test 1: Container Expansion (.insertr)

+
+

This paragraph should be individually editable with a textarea.

+

This second paragraph should also be individually editable.

+

Each paragraph should get its own modal when clicked.

+
+
+ + +
+

Test 2: Group Editing (.insertr-group)

+
+

This paragraph is part of a group.

+

Clicking anywhere should open one markdown editor with rich formatting.

+

All content should be editable together as markdown with proper HTML conversion.

+
+
+
+
- - + + - - + + diff --git a/demo-site/index.html b/demo-site/index.html index 67a5764..93f2742 100644 --- a/demo-site/index.html +++ b/demo-site/index.html @@ -1,85 +1,87 @@ - - - Acme Consulting Services - Live Reload Test - + + + Acme Consulting Services - Live Reload Test + - - - -
-
-

Transform Your Business with Expert Consulting!

-

We help small businesses **grow** through strategic planning, process optimization, and digital transformation. Our team brings 15+ years of experience to drive your success.

- Get Started Today -
-
+ +
+
+

Transform Your Business with Expert Consulting

+

We help small businesses grow through strategic planning, process optimization, and digital transformation. Our team brings 15+ years of experience to drive your success. Superb

+

+ Get Started Today? +
+
- -
-
-

Our Offers

-

Comprehensive solutions tailored to your business needs

- -
-
-

Strategic Planning

-

Develop clear roadmaps and actionable strategies that align with your business goals and drive sustainable growth.

-
-
-

Operations Optimization

-

Streamline processes, reduce costs, and improve efficiency through proven methodologies and best practices.

-
-
-

Digital Transformation

-

Modernize your technology stack and digital presence to compete effectively in today's marketplace.

-
-
-
-
+ +
+
+

Our Services

+

Comprehensive solutions tailored to your business needs

+ +
+
+

Strategic Planning

+

Develop clear roadmaps and actionable strategies that align with your business goals and drive sustainable growth.

+
+
+

Operations Optimization

+

Streamline processes, reduce costs, and improve efficiency through proven methodologies and best practices.

+
+
+

Digital Transformation

+

Modernize your technology stack and digital presence to compete effectively in today's marketplace.

+
+
+
+
- -
-
-
-

"Acme Consulting transformed our operations completely. We saw a 40% increase in efficiency within 6 months of implementing their recommendations."

- Sarah Johnson, CEO of TechStart Inc. -
-
-
+ +
+
+
+

"Acme Consulting transformed our operations completely. We saw a 40% increase in efficiency within 6 months of implementing their recommendations."

+ Sarah Johnson, CEO of TechStart Inc. +
+
+
- -
-
-

Ready to Transform Your Business?

-

Contact us today for a free consultation and discover how we can help you achieve your goals.

- Schedule Consultation -
-
+ +
+
+

Ready to Transform Your Business?

+

Contact us today for a free consultation and discover how we can help you achieve your goals.

+ Schedule Consultation +
+
- - + + - - + + \ No newline at end of file diff --git a/internal/content/enhancer.go b/internal/content/enhancer.go index 986c370..013cae5 100644 --- a/internal/content/enhancer.go +++ b/internal/content/enhancer.go @@ -107,17 +107,23 @@ func (e *Enhancer) findAndInjectNodes(rootNode *html.Node, elem parser.Element, return } + // Determine content type: use database type if available, otherwise parser type + contentType := string(elem.Type) + if contentItem != nil { + contentType = contentItem.Type // Database is source of truth + } + // Inject content attributes for the correctly matched node - e.injector.AddContentAttributes(targetNode, elem.ContentID, string(elem.Type)) + e.injector.AddContentAttributes(targetNode, elem.ContentID, contentType) // Inject content if available if contentItem != nil { - switch elem.Type { - case parser.ContentText: + switch contentItem.Type { // Use database type, not parser type + case "text": e.injector.injectTextContent(targetNode, contentItem.Value) - case parser.ContentMarkdown: + case "markdown": e.injector.injectMarkdownContent(targetNode, contentItem.Value) - case parser.ContentLink: + case "link": e.injector.injectLinkContent(targetNode, contentItem.Value) } } diff --git a/internal/content/injector.go b/internal/content/injector.go index de78060..29d8eaa 100644 --- a/internal/content/injector.go +++ b/internal/content/injector.go @@ -142,15 +142,16 @@ func (i *Injector) injectLinkContent(node *html.Node, content string) { } // injectHTMLContent safely injects HTML content into a DOM node +// Preserves the original element and only replaces its content func (i *Injector) injectHTMLContent(node *html.Node, htmlContent string) { - // Clear existing content + // Clear existing content but preserve the element itself i.clearNode(node) if htmlContent == "" { return } - // Wrap content to create valid HTML document for parsing + // Wrap content for safe parsing wrappedHTML := "
" + htmlContent + "
" // Parse HTML string @@ -168,7 +169,7 @@ func (i *Injector) injectHTMLContent(node *html.Node, htmlContent string) { return } - // Move parsed nodes to target element + // Move parsed nodes to target element (preserving original element) for child := wrapper.FirstChild; child != nil; { next := child.NextSibling wrapper.RemoveChild(child) diff --git a/internal/content/markdown.go b/internal/content/markdown.go index 8490fc5..4b49db6 100644 --- a/internal/content/markdown.go +++ b/internal/content/markdown.go @@ -3,6 +3,7 @@ package content import ( "bytes" "log" + "strings" "github.com/yuin/goldmark" "github.com/yuin/goldmark/parser" @@ -57,11 +58,19 @@ func (mp *MarkdownProcessor) ToHTML(markdown string) (string, error) { html := buf.String() - // Clean up goldmark's paragraph wrapping - we want inline content - // Remove

and

tags if the content is wrapped in a single paragraph - if len(html) > 7 && html[:3] == "

" && html[len(html)-4:] == "

" { - html = html[3 : len(html)-4] + // Clean up goldmark's paragraph wrapping for inline content + // If content is wrapped in a single

tag, extract just the inner content + html = strings.TrimSpace(html) + + if strings.HasPrefix(html, "

") && strings.HasSuffix(html, "

") { + // Check if this is a single paragraph (no other

tags inside) + inner := html[3 : len(html)-4] // Remove

and

+ if !strings.Contains(inner, "

") { + // Single paragraph - return just the inner content for inline injection + return inner, nil + } } + // Multiple paragraphs or other block content - return as-is return html, nil }