@uniweb/content-reader 1.0.2 → 1.0.4

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/README.md CHANGED
@@ -139,7 +139,7 @@ Full support for aligned columns:
139
139
  ## Installation
140
140
 
141
141
  ```bash
142
- npm install @uniwebcms/content-reader
142
+ npm install @uniweb/content-reader
143
143
  ```
144
144
 
145
145
  ## Usage
@@ -147,7 +147,7 @@ npm install @uniwebcms/content-reader
147
147
  Basic usage:
148
148
 
149
149
  ```javascript
150
- const { markdownToProseMirror } = require("@uniwebcms/content-reader");
150
+ const { markdownToProseMirror } = require("@uniweb/content-reader");
151
151
 
152
152
  const markdown = `
153
153
  # Hello World
@@ -168,7 +168,7 @@ The library is designed to work seamlessly with TipTap editors:
168
168
 
169
169
  ```javascript
170
170
  import { Editor } from "@tiptap/core";
171
- import { markdownToProseMirror } from "@uniwebcms/content-reader";
171
+ import { markdownToProseMirror } from "@uniweb/content-reader";
172
172
 
173
173
  const editor = new Editor({
174
174
  content: markdownToProseMirror(markdown),
@@ -243,7 +243,7 @@ We welcome contributions! Please see our contributing guidelines for details.
243
243
  1. Clone the repository:
244
244
 
245
245
  ```bash
246
- git clone https://github.com/uniwebcms/content-reader.git
246
+ git clone https://github.com/uniweb/content-reader.git
247
247
  ```
248
248
 
249
249
  2. Install dependencies:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uniweb/content-reader",
3
- "version": "1.0.2",
3
+ "version": "1.0.4",
4
4
  "description": "Markdown to ProseMirror document structure converter",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
@@ -16,6 +16,7 @@
16
16
  "author": "Proximify Inc.",
17
17
  "license": "GPL-3.0-or-later",
18
18
  "dependencies": {
19
+ "js-yaml": "^4.1.0",
19
20
  "marked": "^11.1.0"
20
21
  },
21
22
  "devDependencies": {
@@ -3,22 +3,23 @@
3
3
  */
4
4
 
5
5
  import { marked } from "marked";
6
+ import yaml from "js-yaml";
6
7
  import { parseInline } from "./inline.js";
7
8
  import { parseList } from "./lists.js";
8
9
  import { parseTable } from "./tables.js";
9
10
 
10
11
  /**
11
- * Process code block info string (e.g., "javascript:example.js")
12
+ * Process code block info string (e.g., "json:tag-name")
12
13
  * @param {string} info - Code block info string
13
- * @returns {Object} Language and filename
14
+ * @returns {Object} Language and optional tag
14
15
  */
15
16
  function processCodeInfo(info) {
16
- if (!info) return { language: null, filename: null };
17
+ if (!info) return { language: null, tag: null };
17
18
 
18
19
  const parts = info.split(":");
19
20
  return {
20
21
  language: parts[0] || null,
21
- filename: parts[1] || null,
22
+ tag: parts[1] || null,
22
23
  };
23
24
  }
24
25
 
@@ -39,6 +40,37 @@ function cleanCodeText(text) {
39
40
  .trim();
40
41
  }
41
42
 
43
+ /**
44
+ * Parse code block content based on language
45
+ * Only parses tagged blocks with json/yaml language
46
+ * @param {string} text - Raw code block text
47
+ * @param {string} language - Code block language
48
+ * @returns {*} Parsed data or null if not parseable
49
+ */
50
+ function parseCodeBlockData(text, language) {
51
+ if (!text) return null;
52
+
53
+ const lang = (language || "").toLowerCase();
54
+
55
+ if (lang === "json") {
56
+ try {
57
+ return JSON.parse(text);
58
+ } catch {
59
+ return null;
60
+ }
61
+ }
62
+
63
+ if (lang === "yaml" || lang === "yml") {
64
+ try {
65
+ return yaml.load(text);
66
+ } catch {
67
+ return null;
68
+ }
69
+ }
70
+
71
+ return null;
72
+ }
73
+
42
74
  /**
43
75
  * Parse a paragraph's content by tokenizing with marked
44
76
  * @param {Object} token - Marked token for paragraph
@@ -142,16 +174,32 @@ function parseBlock(token, schema) {
142
174
  }
143
175
 
144
176
  if (token.type === "code") {
145
- const { language, filename } = processCodeInfo(token.lang);
177
+ const { language, tag } = processCodeInfo(token.lang);
178
+ const rawText = cleanCodeText(token.text);
179
+
180
+ // Tagged blocks become dataBlocks (structured data, not code for display)
181
+ if (tag) {
182
+ const parsedData = parseCodeBlockData(rawText, language);
183
+ if (parsedData !== null) {
184
+ // Successfully parsed - it's a dataBlock
185
+ return {
186
+ type: "dataBlock",
187
+ attrs: { tag, data: parsedData },
188
+ };
189
+ }
190
+ // Parsing failed - fall back to codeBlock with language for runtime fallback
191
+ return {
192
+ type: "codeBlock",
193
+ attrs: { language, tag },
194
+ content: [{ type: "text", text: rawText }],
195
+ };
196
+ }
197
+
198
+ // Untagged code block - for display with syntax highlighting
146
199
  return {
147
200
  type: "codeBlock",
148
- attrs: { language, filename },
149
- content: [
150
- {
151
- type: "text",
152
- text: cleanCodeText(token.text),
153
- },
154
- ],
201
+ attrs: { language },
202
+ content: [{ type: "text", text: rawText }],
155
203
  };
156
204
  }
157
205
 
@@ -12,7 +12,6 @@ describe("Code Parsing", () => {
12
12
  type: "codeBlock",
13
13
  attrs: {
14
14
  language: "javascript",
15
- filename: null,
16
15
  },
17
16
  content: [
18
17
  {
@@ -25,25 +24,19 @@ describe("Code Parsing", () => {
25
24
  });
26
25
  });
27
26
 
28
- test("parses code blocks with filenames", () => {
29
- const markdown = "```javascript:example.js\nconst x = 1;\n```";
27
+ test("parses tagged code blocks as dataBlocks", () => {
28
+ const markdown = "```json:nav-links\n[{\"label\": \"Home\"}]\n```";
30
29
  const result = markdownToProseMirror(markdown);
31
30
 
32
31
  expect(result).toEqual({
33
32
  type: "doc",
34
33
  content: [
35
34
  {
36
- type: "codeBlock",
35
+ type: "dataBlock", // Structured data, not code for display
37
36
  attrs: {
38
- language: "javascript",
39
- filename: "example.js",
37
+ tag: "nav-links",
38
+ data: [{ label: "Home" }],
40
39
  },
41
- content: [
42
- {
43
- type: "text",
44
- text: "const x = 1;",
45
- },
46
- ],
47
40
  },
48
41
  ],
49
42
  });
@@ -60,7 +53,6 @@ describe("Code Parsing", () => {
60
53
  type: "codeBlock",
61
54
  attrs: {
62
55
  language: null,
63
- filename: null,
64
56
  },
65
57
  content: [
66
58
  {
@@ -107,7 +99,6 @@ describe("Code Parsing", () => {
107
99
  type: "codeBlock",
108
100
  attrs: {
109
101
  language: null,
110
- filename: null,
111
102
  },
112
103
  content: [
113
104
  {