@uniweb/semantic-parser 1.12.0 → 1.12.1
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/processors/sequence.js +63 -19
package/package.json
CHANGED
|
@@ -161,7 +161,7 @@ function createSequenceElement(node, options = {}) {
|
|
|
161
161
|
};
|
|
162
162
|
|
|
163
163
|
case "codeBlock": {
|
|
164
|
-
const codeText =
|
|
164
|
+
const codeText = codeTextOf(content);
|
|
165
165
|
// Tagged code blocks are semantically data blocks, not code — the
|
|
166
166
|
// tag is what routes them to `data[tag]`, so the routing holds even
|
|
167
167
|
// though the payload here is raw text.
|
|
@@ -374,22 +374,43 @@ function sameLink(a, b) {
|
|
|
374
374
|
/**
|
|
375
375
|
* Wrap already-styled inline content in an anchor.
|
|
376
376
|
*/
|
|
377
|
+
/**
|
|
378
|
+
* A code block's code, as written — the characters a reader sees, not HTML.
|
|
379
|
+
*
|
|
380
|
+
* Every consumer draws it as text: kit's `Code` (and the highlighter, which
|
|
381
|
+
* escapes as it colors), press's `CodeBlock`, a foundation's `{snippet.code}`.
|
|
382
|
+
* ⛔ Until 2026-10-19 it went through `getTextContent`, which escapes text for
|
|
383
|
+
* the HTML strings a paragraph carries, so a `<` arrived as `<`, was escaped
|
|
384
|
+
* again where it was drawn, and a page showed `<p>` for `<p>`.
|
|
385
|
+
*/
|
|
386
|
+
function codeTextOf(content) {
|
|
387
|
+
return (content || [])
|
|
388
|
+
.map((node) => (node?.type === "text" ? node.text || "" : node?.type === "hardBreak" ? "\n" : ""))
|
|
389
|
+
.join("");
|
|
390
|
+
}
|
|
391
|
+
|
|
377
392
|
function wrapLink(inner, linkMark) {
|
|
378
|
-
return anchor(linkMark.attrs.href, linkMark.attrs.target, inner);
|
|
393
|
+
return anchor(linkMark.attrs.href, linkMark.attrs.target, inner, linkMark.attrs.role);
|
|
379
394
|
}
|
|
380
395
|
|
|
381
396
|
/**
|
|
382
397
|
* An anchor around already-escaped inner HTML. A link whose URL may not be
|
|
383
398
|
* followed (`javascript:`, `data:`, any scheme `isSafeLink` refuses) is not
|
|
384
399
|
* drawn as a link: its label stays, as text.
|
|
400
|
+
*
|
|
401
|
+
* Its `role` — `button` for a `[Go](/x){button}`, or an authored hint such as
|
|
402
|
+
* `nav` — rides as `data-role`, a style name or nothing, so a stylesheet can
|
|
403
|
+
* tell a button from a link. ⛔ Until 2026-10-19 the role was dropped here, and
|
|
404
|
+
* a button reached the page as a plain link.
|
|
385
405
|
*/
|
|
386
|
-
function anchor(href, target, inner) {
|
|
406
|
+
function anchor(href, target, inner, role) {
|
|
387
407
|
if (typeof href !== "string" || !isSafeLink(href)) return inner;
|
|
388
408
|
const t = isLinkTarget(target) ? target : "_self";
|
|
389
409
|
const extension = href.split(".").pop()?.toLowerCase();
|
|
390
410
|
const isFileLink = FILE_LINK_EXTENSIONS.includes(extension);
|
|
411
|
+
const roleAttr = isStyleName(role) ? ` data-role="${escapeAttr(role)}"` : "";
|
|
391
412
|
|
|
392
|
-
return `<a href="${escapeAttr(href)}" target="${t}"${isFileLink ? " download" : ""}>${inner}</a>`;
|
|
413
|
+
return `<a href="${escapeAttr(href)}" target="${t}"${isFileLink ? " download" : ""}${roleAttr}>${inner}</a>`;
|
|
393
414
|
}
|
|
394
415
|
|
|
395
416
|
function getTextContent(content, options = {}) {
|
|
@@ -453,8 +474,8 @@ function renderInlineNode(curr, iconOrdinals, pictureOrdinals) {
|
|
|
453
474
|
if (type === "text") {
|
|
454
475
|
let styledText = escapeText(text || "");
|
|
455
476
|
|
|
456
|
-
// Apply marks in order: span, code, bold, italic — the link
|
|
457
|
-
// applied per group by getTextContent. This ensures proper nesting.
|
|
477
|
+
// Apply marks in order: span, code, bold, italic, strike — the link
|
|
478
|
+
// is applied per group by getTextContent. This ensures proper nesting.
|
|
458
479
|
//
|
|
459
480
|
// ⛔ Until 2026-10-18 the editor's `textStyle` (a theme color) and
|
|
460
481
|
// `highlight` marks were applied first. The editor saves both as
|
|
@@ -513,6 +534,12 @@ function renderInlineNode(curr, iconOrdinals, pictureOrdinals) {
|
|
|
513
534
|
styledText = `<em>${styledText}</em>`;
|
|
514
535
|
}
|
|
515
536
|
|
|
537
|
+
// strike — `~~text~~`. ⛔ Until 2026-10-19 nothing applied the
|
|
538
|
+
// mark, so struck text reached the page as ordinary text.
|
|
539
|
+
if (marks.some((mark) => mark.type === "strike")) {
|
|
540
|
+
styledText = `<s>${styledText}</s>`;
|
|
541
|
+
}
|
|
542
|
+
|
|
516
543
|
// The link mark is deliberately NOT applied here — it is the
|
|
517
544
|
// outermost wrapper and may span several nodes, so
|
|
518
545
|
// getTextContent applies it once per group.
|
|
@@ -1043,18 +1070,35 @@ function isOnlyLinks(item) {
|
|
|
1043
1070
|
|
|
1044
1071
|
if (!allLinks) return false;
|
|
1045
1072
|
|
|
1046
|
-
//
|
|
1073
|
+
// One link per anchor, as `getTextContent` draws them: consecutive runs that
|
|
1074
|
+
// carry the same link are ONE link whose label has several runs
|
|
1075
|
+
// (`[**Go** now](/go)`), and anything between two links — the space a line
|
|
1076
|
+
// break becomes, an icon — keeps them apart. ⛔ Until 2026-10-19 every run
|
|
1077
|
+
// was a link of its own, so a button labelled in two styles became two
|
|
1078
|
+
// buttons, "Go" and " now".
|
|
1047
1079
|
// Icons in this paragraph go to body.icons separately (no association)
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
}
|
|
1056
|
-
|
|
1057
|
-
|
|
1080
|
+
const groups = [];
|
|
1081
|
+
let current = null;
|
|
1082
|
+
for (const c of content) {
|
|
1083
|
+
const mark = c.type === "text" ? linkMarkOf(c.marks) : null;
|
|
1084
|
+
if (mark && current && sameLink(current.mark, mark)) {
|
|
1085
|
+
current.label += c.text || "";
|
|
1086
|
+
} else if (mark) {
|
|
1087
|
+
current = { mark, label: c.text || "" };
|
|
1088
|
+
groups.push(current);
|
|
1089
|
+
} else {
|
|
1090
|
+
current = null;
|
|
1091
|
+
}
|
|
1092
|
+
}
|
|
1093
|
+
|
|
1094
|
+
// Extract links with all their attributes
|
|
1095
|
+
return groups.map(({ mark, label }) => ({
|
|
1096
|
+
type: "link",
|
|
1097
|
+
attrs: {
|
|
1098
|
+
...mark?.attrs, // Preserve all link attributes (role, target, etc.)
|
|
1099
|
+
label,
|
|
1100
|
+
},
|
|
1101
|
+
}));
|
|
1058
1102
|
}
|
|
1059
1103
|
|
|
1060
1104
|
// method to check if given item has multiple content parts and each of them has the same link attrs with different inline style (plain, em, strong, u)
|
|
@@ -1085,7 +1129,7 @@ function isStyledLink(item, options = {}) {
|
|
|
1085
1129
|
)
|
|
1086
1130
|
return false;
|
|
1087
1131
|
|
|
1088
|
-
const { href, target } = firstLinkMark.attrs;
|
|
1132
|
+
const { href, target, role } = firstLinkMark.attrs;
|
|
1089
1133
|
|
|
1090
1134
|
const cleanedContent = content.map((c) => {
|
|
1091
1135
|
// remove link marks from content items
|
|
@@ -1104,7 +1148,7 @@ function isStyledLink(item, options = {}) {
|
|
|
1104
1148
|
return {
|
|
1105
1149
|
type: "paragraph",
|
|
1106
1150
|
children: processInlineElements(item.content, options),
|
|
1107
|
-
text: anchor(href, target, textContent),
|
|
1151
|
+
text: anchor(href, target, textContent, role),
|
|
1108
1152
|
attrs: item.attrs,
|
|
1109
1153
|
};
|
|
1110
1154
|
}
|