@webmate-studio/builder 0.2.51 → 0.2.53

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webmate-studio/builder",
3
- "version": "0.2.51",
3
+ "version": "0.2.53",
4
4
  "type": "module",
5
5
  "description": "Webmate Studio Component Builder",
6
6
  "keywords": [
@@ -35,11 +35,14 @@
35
35
  "@webmate-studio/core": "^0.2.7",
36
36
  "@webmate-studio/parser": "^0.2.8",
37
37
  "dom-serializer": "^2.0.0",
38
+ "dompurify": "^3.3.0",
38
39
  "esbuild": "^0.19.0",
39
40
  "esbuild-svelte": "^0.9.3",
40
41
  "glob": "^10.3.0",
41
42
  "htmlparser2": "^9.0.0",
43
+ "jsdom": "^27.0.1",
42
44
  "lit": "^3.3.1",
45
+ "marked": "^17.0.1",
43
46
  "preact": "^10.27.2",
44
47
  "preact-custom-element": "^4.6.0",
45
48
  "react": "^19.2.0",
package/src/index.js CHANGED
@@ -3,5 +3,6 @@ import { generateComponentCSS, generateTailwindCSS, extractTailwindClasses } fro
3
3
  import { cleanComponentHTML } from './html-cleaner.js';
4
4
  import { bundleIsland, bundleComponentIslands } from './bundler.js';
5
5
  import { deduplicateCSS } from './css-deduplicator.js';
6
+ import { markdownToHtml, processMarkdownProps } from './markdown.js';
6
7
 
7
- export { build, generateComponentCSS, generateTailwindCSS, extractTailwindClasses, cleanComponentHTML, bundleIsland, bundleComponentIslands, deduplicateCSS };
8
+ export { build, generateComponentCSS, generateTailwindCSS, extractTailwindClasses, cleanComponentHTML, bundleIsland, bundleComponentIslands, deduplicateCSS, markdownToHtml, processMarkdownProps };
@@ -0,0 +1,90 @@
1
+ /**
2
+ * Markdown Parser Utility für @webmate-studio/builder
3
+ * Konvertiert Markdown zu sicherem HTML
4
+ */
5
+
6
+ import { marked } from 'marked';
7
+ import DOMPurify from 'dompurify';
8
+ import { JSDOM } from 'jsdom';
9
+
10
+ // DOMPurify für Server-Side Rendering konfigurieren
11
+ const window = new JSDOM('').window;
12
+ const purify = DOMPurify(window);
13
+
14
+ // Marked Konfiguration
15
+ marked.setOptions({
16
+ gfm: true, // GitHub Flavored Markdown
17
+ breaks: true, // Konvertiere \n zu <br>
18
+ headerIds: true, // IDs für Headings
19
+ mangle: false, // Email-Adressen nicht verschleiern
20
+ });
21
+
22
+ /**
23
+ * Konvertiert Markdown zu sicherem HTML
24
+ *
25
+ * @param {string} markdown - Markdown-String
26
+ * @param {object} options - Optionale Konfiguration
27
+ * @param {boolean} options.sanitize - HTML sanitizen (default: true)
28
+ * @returns {string} - Sicherer HTML-String
29
+ */
30
+ export function markdownToHtml(markdown, options = {}) {
31
+ if (!markdown || typeof markdown !== 'string') {
32
+ return '';
33
+ }
34
+
35
+ // Markdown zu HTML
36
+ let html = marked.parse(markdown);
37
+
38
+ // XSS-Schutz mit DOMPurify
39
+ if (options.sanitize !== false) {
40
+ const config = {
41
+ ALLOWED_TAGS: [
42
+ 'p', 'br', 'strong', 'em', 'u', 's', 'del', 'ins',
43
+ 'h1', 'h2', 'h3', 'h4', 'h5', 'h6',
44
+ 'ul', 'ol', 'li',
45
+ 'blockquote', 'pre', 'code',
46
+ 'a', 'img',
47
+ 'table', 'thead', 'tbody', 'tr', 'th', 'td',
48
+ 'hr', 'abbr', 'cite', 'mark', 'small', 'sub', 'sup'
49
+ ],
50
+ ALLOWED_ATTR: [
51
+ 'href', 'title', 'alt', 'src',
52
+ 'target', 'rel',
53
+ 'class', 'id'
54
+ ],
55
+ ALLOW_DATA_ATTR: false
56
+ };
57
+
58
+ html = purify.sanitize(html, config);
59
+ }
60
+
61
+ return html;
62
+ }
63
+
64
+ /**
65
+ * Process markdown props: Convert markdown strings to HTML
66
+ *
67
+ * @param {Object} props - Component props
68
+ * @param {Object} propSchema - Prop schema with format info (from component.json)
69
+ * @returns {Object} Props with markdown converted to HTML
70
+ */
71
+ export function processMarkdownProps(props, propSchema = null) {
72
+ if (!props || typeof props !== 'object') return props;
73
+
74
+ const processed = { ...props };
75
+
76
+ for (const [key, value] of Object.entries(processed)) {
77
+ // Only process strings
78
+ if (typeof value !== 'string' || !value) continue;
79
+
80
+ // Check if this prop is markdown (via schema)
81
+ const isMarkdown = propSchema?.[key]?.format === 'markdown';
82
+
83
+ if (isMarkdown) {
84
+ // Convert markdown to HTML
85
+ processed[key] = markdownToHtml(value);
86
+ }
87
+ }
88
+
89
+ return processed;
90
+ }