@uniweb/content-reader 1.1.2 → 1.1.3
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 +1 -1
- package/src/parser/block.js +4 -1
- package/src/parser/inline.js +14 -0
- package/tests/parser.test.js +84 -0
package/package.json
CHANGED
package/src/parser/block.js
CHANGED
|
@@ -111,7 +111,10 @@ function parseBlock(token, schema) {
|
|
|
111
111
|
let currentParagraph = null;
|
|
112
112
|
|
|
113
113
|
content.forEach((element) => {
|
|
114
|
-
if (
|
|
114
|
+
if (
|
|
115
|
+
(element.type === "image" && element.attrs?.role !== "icon") ||
|
|
116
|
+
element.type === "inline_child_ref"
|
|
117
|
+
) {
|
|
115
118
|
// Extract non-icon images to root level so they become
|
|
116
119
|
// block-level elements. Icons stay inline so the semantic
|
|
117
120
|
// parser can associate them with adjacent links.
|
package/src/parser/inline.js
CHANGED
|
@@ -148,6 +148,20 @@ function parseInline(token, schema, removeNewLine = false) {
|
|
|
148
148
|
}
|
|
149
149
|
|
|
150
150
|
if (token.type === "image") {
|
|
151
|
+
// Check for @ component reference: {key=value}
|
|
152
|
+
if (token.href.startsWith('@') && token.href.length > 1) {
|
|
153
|
+
const component = token.href.slice(1)
|
|
154
|
+
const { role: _role, ...otherAttrs } = token.attrs || {}
|
|
155
|
+
return [{
|
|
156
|
+
type: "inline_child_ref",
|
|
157
|
+
attrs: {
|
|
158
|
+
component,
|
|
159
|
+
alt: text || null,
|
|
160
|
+
...otherAttrs,
|
|
161
|
+
},
|
|
162
|
+
}]
|
|
163
|
+
}
|
|
164
|
+
|
|
151
165
|
let role, src, iconLibrary, iconName;
|
|
152
166
|
|
|
153
167
|
// Supported icon families - friendly names and direct react-icons codes
|
package/tests/parser.test.js
CHANGED
|
@@ -699,3 +699,87 @@ describe("Bracketed Spans", () => {
|
|
|
699
699
|
expect(content[2].marks[0].attrs.class).toBe("muted");
|
|
700
700
|
});
|
|
701
701
|
});
|
|
702
|
+
|
|
703
|
+
describe("Component References (@)", () => {
|
|
704
|
+
test("parses bare @ComponentName", () => {
|
|
705
|
+
const markdown = "";
|
|
706
|
+
const result = markdownToProseMirror(markdown);
|
|
707
|
+
|
|
708
|
+
expect(result).toEqual({
|
|
709
|
+
type: "doc",
|
|
710
|
+
content: [
|
|
711
|
+
{
|
|
712
|
+
type: "inline_child_ref",
|
|
713
|
+
attrs: {
|
|
714
|
+
component: "Hero",
|
|
715
|
+
alt: null,
|
|
716
|
+
},
|
|
717
|
+
},
|
|
718
|
+
],
|
|
719
|
+
});
|
|
720
|
+
});
|
|
721
|
+
|
|
722
|
+
test("parses @ComponentName with alt text and params", () => {
|
|
723
|
+
const markdown = "{variant=compact size=lg}";
|
|
724
|
+
const result = markdownToProseMirror(markdown);
|
|
725
|
+
|
|
726
|
+
expect(result).toEqual({
|
|
727
|
+
type: "doc",
|
|
728
|
+
content: [
|
|
729
|
+
{
|
|
730
|
+
type: "inline_child_ref",
|
|
731
|
+
attrs: {
|
|
732
|
+
component: "NetworkDiagram",
|
|
733
|
+
alt: "Architecture diagram",
|
|
734
|
+
variant: "compact",
|
|
735
|
+
size: "lg",
|
|
736
|
+
},
|
|
737
|
+
},
|
|
738
|
+
],
|
|
739
|
+
});
|
|
740
|
+
});
|
|
741
|
+
|
|
742
|
+
test("bare @ is treated as regular image", () => {
|
|
743
|
+
const markdown = "";
|
|
744
|
+
const result = markdownToProseMirror(markdown);
|
|
745
|
+
|
|
746
|
+
// Bare @ doesn't match component ref (length check), falls through to image
|
|
747
|
+
expect(result.content[0].type).toBe("image");
|
|
748
|
+
});
|
|
749
|
+
|
|
750
|
+
test("@ ref is lifted to block level (not inline in paragraph)", () => {
|
|
751
|
+
const markdown = "Some text before  and after";
|
|
752
|
+
const result = markdownToProseMirror(markdown);
|
|
753
|
+
|
|
754
|
+
// inline_child_ref should be extracted from paragraph like images
|
|
755
|
+
const types = result.content.map((n) => n.type);
|
|
756
|
+
expect(types).toContain("inline_child_ref");
|
|
757
|
+
expect(types).toContain("paragraph");
|
|
758
|
+
});
|
|
759
|
+
|
|
760
|
+
test("icon syntax is not affected by @ detection", () => {
|
|
761
|
+
const markdown = "";
|
|
762
|
+
const result = markdownToProseMirror(markdown);
|
|
763
|
+
|
|
764
|
+
// Icons still work as before
|
|
765
|
+
expect(result.content[0].type).toBe("paragraph");
|
|
766
|
+
expect(result.content[0].content[0].attrs.role).toBe("icon");
|
|
767
|
+
expect(result.content[0].content[0].attrs.library).toBe("lu");
|
|
768
|
+
expect(result.content[0].content[0].attrs.name).toBe("house");
|
|
769
|
+
});
|
|
770
|
+
|
|
771
|
+
test("multiple @ refs in same section", () => {
|
|
772
|
+
const markdown = "\n\n";
|
|
773
|
+
const result = markdownToProseMirror(markdown);
|
|
774
|
+
|
|
775
|
+
expect(result.content).toHaveLength(2);
|
|
776
|
+
expect(result.content[0]).toEqual({
|
|
777
|
+
type: "inline_child_ref",
|
|
778
|
+
attrs: { component: "Widget", alt: null },
|
|
779
|
+
});
|
|
780
|
+
expect(result.content[1]).toEqual({
|
|
781
|
+
type: "inline_child_ref",
|
|
782
|
+
attrs: { component: "Chart", alt: null },
|
|
783
|
+
});
|
|
784
|
+
});
|
|
785
|
+
});
|