pro-editor-schema 1.3.0 → 1.4.0
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 +102 -53
- package/dist/index.d.mts +66 -28
- package/dist/index.d.ts +66 -28
- package/dist/index.js +376 -235
- package/dist/index.mjs +367 -231
- package/package.json +15 -3
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// src/schema/
|
|
1
|
+
// src/schema/helpers/createSchema.ts
|
|
2
2
|
var createSchema = (params) => {
|
|
3
3
|
return params;
|
|
4
4
|
};
|
|
@@ -40,10 +40,13 @@ var TRACK_CHANGES_ATTRS = [
|
|
|
40
40
|
];
|
|
41
41
|
var ELE_ID_ATTRIBUTE = "ele-id";
|
|
42
42
|
var STORE_ATTRIBUTE = "store";
|
|
43
|
+
var XMLID_ATTRIBUTE = "xmlid";
|
|
44
|
+
var LINKEND_ATTRIBUTE = "linkend";
|
|
43
45
|
var ID_ATTRS = [STORE_ATTRIBUTE, ELE_ID_ATTRIBUTE];
|
|
44
46
|
|
|
45
47
|
// src/schema/shared/allowedAtomsChildren.ts
|
|
46
48
|
var ATOM_CODES_ALLOWED_CHILDREN = [
|
|
49
|
+
{ code: "mark", required: false },
|
|
47
50
|
{ code: "indexterm", required: false },
|
|
48
51
|
{ code: "b", required: false },
|
|
49
52
|
{ code: "i", required: false },
|
|
@@ -87,6 +90,7 @@ var QUATERNARY_TAG = "QUATERNARY";
|
|
|
87
90
|
var BOOKMARK_TAG = "BOOKMARK";
|
|
88
91
|
var SEE_TAG = "SEE";
|
|
89
92
|
var REFERENCE_MARK_TAG = "REFERENCE";
|
|
93
|
+
var MARK_TAG = "MARK";
|
|
90
94
|
|
|
91
95
|
// src/schema/elementSchemas/atoms/b.ts
|
|
92
96
|
var B_SCHEMA = createSchema({
|
|
@@ -528,6 +532,23 @@ var ABBR_SCHEMA = createSchema({
|
|
|
528
532
|
allowedChildrenCodes: [...ATOM_CODES_ALLOWED_CHILDREN]
|
|
529
533
|
});
|
|
530
534
|
|
|
535
|
+
// src/schema/elementSchemas/atoms/mark.ts
|
|
536
|
+
var MARK_SCHEMA = createSchema({
|
|
537
|
+
code: "mark",
|
|
538
|
+
kind: "atom",
|
|
539
|
+
tag: MARK_TAG,
|
|
540
|
+
requiredAttributes: ["id"],
|
|
541
|
+
optionalAttributes: [
|
|
542
|
+
"data-markjs",
|
|
543
|
+
{
|
|
544
|
+
name: "data-replaceable",
|
|
545
|
+
values: ["true", "false"],
|
|
546
|
+
defaultValue: "true"
|
|
547
|
+
}
|
|
548
|
+
],
|
|
549
|
+
allowedChildrenCodes: [...ATOM_CODES_ALLOWED_CHILDREN]
|
|
550
|
+
});
|
|
551
|
+
|
|
531
552
|
// src/schema/elementSchemas/atoms/index.ts
|
|
532
553
|
var ATOM_SCHEMAS = {
|
|
533
554
|
indexterm: INDEXTERM_SCHEMA,
|
|
@@ -555,7 +576,8 @@ var ATOM_SCHEMAS = {
|
|
|
555
576
|
comment: COMMENT_SCHEMA,
|
|
556
577
|
query: QUERY_SCHEMA,
|
|
557
578
|
reply: REPLY_SCHEMA,
|
|
558
|
-
abbreviation: ABBR_SCHEMA
|
|
579
|
+
abbreviation: ABBR_SCHEMA,
|
|
580
|
+
mark: MARK_SCHEMA
|
|
559
581
|
};
|
|
560
582
|
|
|
561
583
|
// src/schema/elementSchemas/elements/elementsTags.ts
|
|
@@ -622,7 +644,7 @@ var EPIGRAPH_TAG = "EPIGRAPH";
|
|
|
622
644
|
var INFO_TAG = "INFO1";
|
|
623
645
|
var POEM_TAG = "POEM";
|
|
624
646
|
var BIBLIOMIXED_TAG = "BIBLIOMIXED";
|
|
625
|
-
var REFERENCE_BIBLIOGRAPHY_TAG = "
|
|
647
|
+
var REFERENCE_BIBLIOGRAPHY_TAG = "BIBLIOGRAPHY";
|
|
626
648
|
var BIBLIODIV_TAG = "BIBLIODIV";
|
|
627
649
|
var MATHPHRASE_TAG = "MATHPHRASE";
|
|
628
650
|
var MATH_TAG = "MATH";
|
|
@@ -1981,7 +2003,7 @@ var FOOTNOTE_SECTION_SCHEMA = createSchema({
|
|
|
1981
2003
|
});
|
|
1982
2004
|
|
|
1983
2005
|
// src/schema/elementSchemas/elements/heading.ts
|
|
1984
|
-
var HEADING_LEVEL = ["H1", "H2", "H3", "H4", "H5", "H6"];
|
|
2006
|
+
var HEADING_LEVEL = ["H0", "H1", "H2", "H3", "H4", "H5", "H6"];
|
|
1985
2007
|
var HEADING_ROLES = [...HEADING_LEVEL, "vignette_group"];
|
|
1986
2008
|
var HEADING_SCHEMA = createSchema({
|
|
1987
2009
|
code: "heading",
|
|
@@ -2052,6 +2074,7 @@ var POEM_SCHEMA = createSchema({
|
|
|
2052
2074
|
optionalAttributes: [...TRACK_CHANGES_ATTRS, "role", "trackmsg"],
|
|
2053
2075
|
defaultChildCode: "line",
|
|
2054
2076
|
allowedChildrenCodes: [
|
|
2077
|
+
{ code: "title1", required: false },
|
|
2055
2078
|
{ code: "line", required: false },
|
|
2056
2079
|
{ code: "linegroup", required: false },
|
|
2057
2080
|
{ code: "source1", required: false }
|
|
@@ -2347,55 +2370,10 @@ var SCHEMAS = {
|
|
|
2347
2370
|
...INLINE_ELEMENT_SCHEMAS
|
|
2348
2371
|
};
|
|
2349
2372
|
|
|
2350
|
-
// src/schema/
|
|
2351
|
-
var IGNORED_ELEMENT_SELECTORS = [
|
|
2352
|
-
"span.rhlabel",
|
|
2353
|
-
"span.printlabel",
|
|
2354
|
-
"span.refIcon",
|
|
2355
|
-
"span.missLink",
|
|
2356
|
-
"span.ref-drag",
|
|
2357
|
-
"span#dummySpan"
|
|
2358
|
-
];
|
|
2359
|
-
var IGNORED_VALIDATION_ELEMENT_SELECTORS = [
|
|
2360
|
-
"referenceBibliomixed"
|
|
2361
|
-
];
|
|
2362
|
-
|
|
2363
|
-
// src/schema/shared/ignoredAttributes.ts
|
|
2364
|
-
var IGNORED_ATTRIBUTES = [
|
|
2365
|
-
// Styling & layout
|
|
2366
|
-
"class",
|
|
2367
|
-
"style",
|
|
2368
|
-
// Editor state
|
|
2369
|
-
"contenteditable",
|
|
2370
|
-
"draggable",
|
|
2371
|
-
"data-prevpos",
|
|
2372
|
-
"tabindex",
|
|
2373
|
-
// Browser behaviour
|
|
2374
|
-
"spellcheck",
|
|
2375
|
-
"translate",
|
|
2376
|
-
"lang",
|
|
2377
|
-
"dir",
|
|
2378
|
-
"hidden",
|
|
2379
|
-
"data-gramm"
|
|
2380
|
-
];
|
|
2381
|
-
var IGNORED_ATTRIBUTES_STARTS_WITH = ["er-", "er_", "drop", "drag"];
|
|
2382
|
-
|
|
2383
|
-
// src/schema/utils/utils.ts
|
|
2384
|
-
var isTrackChangesSchema = (schema) => schema.code === "insertion" || schema.code === "deletion" || schema.code === "lineGroupRemoval";
|
|
2385
|
-
var isIgnoredAttribute = (attribute) => IGNORED_ATTRIBUTES.includes(attribute) || IGNORED_ATTRIBUTES_STARTS_WITH.some(
|
|
2386
|
-
(startsWith) => attribute.startsWith(startsWith)
|
|
2387
|
-
);
|
|
2388
|
-
var isIgnoredElement = (element) => IGNORED_ELEMENT_SELECTORS.some((selector) => element.matches(selector));
|
|
2389
|
-
var isIgnoredValidation = (code) => IGNORED_VALIDATION_ELEMENT_SELECTORS.includes(code);
|
|
2390
|
-
var findSchemaByCode = (code) => SCHEMAS[code];
|
|
2391
|
-
var findSchemaByElement = (element) => {
|
|
2392
|
-
const schema = Object.values(SCHEMAS).find(
|
|
2393
|
-
(schema2) => schema2.tag == element.tagName && (!schema2.matchesElement || schema2.matchesElement(element))
|
|
2394
|
-
);
|
|
2395
|
-
return schema;
|
|
2396
|
-
};
|
|
2397
|
-
var isAttributeRestricted = (attr) => typeof attr !== "string";
|
|
2373
|
+
// src/schema/helpers/getAttributeName.ts
|
|
2398
2374
|
var getAttributeName = (attribute) => typeof attribute === "string" ? attribute.toLowerCase() : attribute.name.toLowerCase();
|
|
2375
|
+
|
|
2376
|
+
// src/schema/helpers/findAttributeDefinitionByName.ts
|
|
2399
2377
|
var findAttributeDefinitionByName = (definitions, name) => {
|
|
2400
2378
|
for (const def of definitions) {
|
|
2401
2379
|
if (getAttributeName(def) === name.toLowerCase()) {
|
|
@@ -2405,47 +2383,29 @@ var findAttributeDefinitionByName = (definitions, name) => {
|
|
|
2405
2383
|
return void 0;
|
|
2406
2384
|
};
|
|
2407
2385
|
|
|
2408
|
-
// src/schema/
|
|
2409
|
-
var
|
|
2410
|
-
schemaCode,
|
|
2411
|
-
attributes
|
|
2412
|
-
}) => {
|
|
2413
|
-
const schema = findSchemaByCode(schemaCode);
|
|
2414
|
-
const element = document.createElement(schema.tag.toLowerCase());
|
|
2415
|
-
for (const [name, value] of Object.entries(attributes)) {
|
|
2416
|
-
if (!value) continue;
|
|
2417
|
-
element.setAttribute(name, String(value));
|
|
2418
|
-
}
|
|
2419
|
-
return element;
|
|
2420
|
-
};
|
|
2386
|
+
// src/schema/helpers/findSchemaByCode.ts
|
|
2387
|
+
var findSchemaByCode = (code) => SCHEMAS[code];
|
|
2421
2388
|
|
|
2422
|
-
// src/schema/
|
|
2423
|
-
var
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
}
|
|
2430
|
-
return element;
|
|
2431
|
-
};
|
|
2432
|
-
var queryAllElementsBySchema = (content, schemaCode) => {
|
|
2433
|
-
const schema = findSchemaByCode(schemaCode);
|
|
2434
|
-
const elements = content.querySelectorAll(
|
|
2435
|
-
schema.tag.toLowerCase()
|
|
2389
|
+
// src/schema/helpers/matchesSchemaTag.ts
|
|
2390
|
+
var matchesSchemaTag = (element, tag) => element.tagName.toUpperCase() === tag.toUpperCase();
|
|
2391
|
+
|
|
2392
|
+
// src/schema/helpers/findSchemaByElement.ts
|
|
2393
|
+
var findSchemaByElement = (element) => {
|
|
2394
|
+
const schema = Object.values(SCHEMAS).find(
|
|
2395
|
+
(schema2) => matchesSchemaTag(element, schema2.tag) && (!schema2.matchesElement || schema2.matchesElement(element))
|
|
2436
2396
|
);
|
|
2437
|
-
|
|
2438
|
-
for (const element of elements) {
|
|
2439
|
-
if (schema.matchesElement && !schema.matchesElement(element)) {
|
|
2440
|
-
continue;
|
|
2441
|
-
}
|
|
2442
|
-
matchingElements.push(element);
|
|
2443
|
-
}
|
|
2444
|
-
return matchingElements;
|
|
2397
|
+
return schema;
|
|
2445
2398
|
};
|
|
2446
2399
|
|
|
2400
|
+
// src/schema/helpers/isAttributeRestricted.ts
|
|
2401
|
+
var isAttributeRestricted = (attr) => typeof attr !== "string";
|
|
2402
|
+
|
|
2403
|
+
// src/schema/helpers/isTrackChangesSchema.ts
|
|
2404
|
+
var isTrackChangesSchema = (schema) => schema.code === "insertion" || schema.code === "deletion" || schema.code === "lineGroupRemoval";
|
|
2405
|
+
|
|
2447
2406
|
// src/schema/shared/labelElements.ts
|
|
2448
2407
|
var ElementLabel = {
|
|
2408
|
+
mark: "Mark",
|
|
2449
2409
|
referenceBibliomixed: "Reference Bibliomixed",
|
|
2450
2410
|
referenceBibliography: "Reference Bibliography",
|
|
2451
2411
|
bibliodiv: "Bibliodiv",
|
|
@@ -2580,40 +2540,54 @@ var DEPENDENT_FORBIDDEN_ELEMENTS = [
|
|
|
2580
2540
|
}
|
|
2581
2541
|
];
|
|
2582
2542
|
|
|
2583
|
-
// src/
|
|
2584
|
-
var
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
|
|
2588
|
-
|
|
2589
|
-
|
|
2590
|
-
|
|
2591
|
-
|
|
2592
|
-
var
|
|
2593
|
-
id: generateValidationIssueId(),
|
|
2594
|
-
...issue
|
|
2595
|
-
});
|
|
2596
|
-
var addValidationIssue = (errors, issue) => {
|
|
2597
|
-
errors.push(createValidationIssue(issue));
|
|
2598
|
-
};
|
|
2543
|
+
// src/helpers/isIgnoredElement.ts
|
|
2544
|
+
var IGNORED_ELEMENT_SELECTORS = [
|
|
2545
|
+
"span.rhlabel",
|
|
2546
|
+
"span.printlabel",
|
|
2547
|
+
"span.refIcon",
|
|
2548
|
+
"span.missLink",
|
|
2549
|
+
"span.ref-drag",
|
|
2550
|
+
"span#dummySpan"
|
|
2551
|
+
];
|
|
2552
|
+
var isIgnoredElement = (element) => IGNORED_ELEMENT_SELECTORS.some((selector) => element.matches(selector));
|
|
2599
2553
|
|
|
2600
|
-
// src/validation/
|
|
2601
|
-
var
|
|
2602
|
-
|
|
2603
|
-
|
|
2554
|
+
// src/validation/helpers/isIgnoredValidation.ts
|
|
2555
|
+
var IGNORED_VALIDATION_ELEMENT_SELECTORS = [
|
|
2556
|
+
"referenceBibliomixed"
|
|
2557
|
+
];
|
|
2558
|
+
var isIgnoredValidation = (code) => IGNORED_VALIDATION_ELEMENT_SELECTORS.includes(code);
|
|
2604
2559
|
|
|
2605
|
-
// src/
|
|
2606
|
-
var
|
|
2607
|
-
|
|
2608
|
-
|
|
2609
|
-
|
|
2560
|
+
// src/helpers/closestElementBySchema.ts
|
|
2561
|
+
var closestElementBySchema = ({
|
|
2562
|
+
element,
|
|
2563
|
+
code,
|
|
2564
|
+
ignoreDeletedElements = false
|
|
2565
|
+
}) => {
|
|
2566
|
+
const schema = findSchemaByCode(code);
|
|
2567
|
+
if (!schema) return;
|
|
2568
|
+
const closestElement = element.closest(
|
|
2569
|
+
schema.tag.toLowerCase()
|
|
2570
|
+
);
|
|
2571
|
+
if (!closestElement) return;
|
|
2572
|
+
if (schema.matchesElement && !schema.matchesElement(closestElement)) {
|
|
2573
|
+
return;
|
|
2610
2574
|
}
|
|
2611
|
-
|
|
2575
|
+
if (ignoreDeletedElements && isDeletedElement(closestElement)) {
|
|
2576
|
+
return closestElementBySchema({
|
|
2577
|
+
element: closestElement,
|
|
2578
|
+
code,
|
|
2579
|
+
ignoreDeletedElements
|
|
2580
|
+
});
|
|
2581
|
+
}
|
|
2582
|
+
return closestElement;
|
|
2612
2583
|
};
|
|
2613
2584
|
|
|
2614
|
-
// src/
|
|
2585
|
+
// src/helpers/isDeletedElement.ts
|
|
2615
2586
|
var isDeletedElement = (element) => {
|
|
2616
|
-
return !!
|
|
2587
|
+
return !!closestElementBySchema({
|
|
2588
|
+
element,
|
|
2589
|
+
code: "deletion"
|
|
2590
|
+
});
|
|
2617
2591
|
};
|
|
2618
2592
|
|
|
2619
2593
|
// src/validation/utils/getElementsSelector.ts
|
|
@@ -2629,63 +2603,35 @@ var getElementsSelector = ({
|
|
|
2629
2603
|
return elements;
|
|
2630
2604
|
};
|
|
2631
2605
|
|
|
2632
|
-
// src/validation/
|
|
2633
|
-
var
|
|
2634
|
-
|
|
2635
|
-
|
|
2636
|
-
|
|
2637
|
-
TABLE_LINK_ROLE,
|
|
2638
|
-
FIGURE_LINK_ROLE,
|
|
2639
|
-
EQUATION_LINK_ROLE,
|
|
2640
|
-
FOOTNOTE_LINK_ROLE,
|
|
2641
|
-
REFERENCE_LINK_ROLE
|
|
2642
|
-
];
|
|
2643
|
-
var LINK_BLOCKER_ROLES = [
|
|
2644
|
-
TABLE_LINK_ROLE,
|
|
2645
|
-
FIGURE_LINK_ROLE,
|
|
2646
|
-
EQUATION_LINK_ROLE,
|
|
2647
|
-
FOOTNOTE_LINK_ROLE
|
|
2648
|
-
];
|
|
2649
|
-
var validateLinkend = (linkElement, elementsToLink) => {
|
|
2650
|
-
const linkend = linkElement.getAttribute("linkend");
|
|
2651
|
-
if (!linkend) {
|
|
2652
|
-
return [];
|
|
2653
|
-
}
|
|
2654
|
-
const isLinkFootnoteCue = linkElement.tagName.toUpperCase() === FOOTNOTE_LINK_SCHEMA.tag;
|
|
2655
|
-
if (isLinkFootnoteCue) {
|
|
2656
|
-
if (findElementLinkedTo(linkend, elementsToLink)) {
|
|
2657
|
-
return [];
|
|
2658
|
-
}
|
|
2659
|
-
return [
|
|
2660
|
-
createValidationIssue({
|
|
2661
|
-
store: getStore(linkElement),
|
|
2662
|
-
title: "Unlinked footnote cue",
|
|
2663
|
-
kind: "unlinked",
|
|
2664
|
-
description: "This footnote cue is not referenced to any footnote in this chapter. Please link it again manually.",
|
|
2665
|
-
level: "blocker"
|
|
2666
|
-
})
|
|
2667
|
-
];
|
|
2668
|
-
}
|
|
2669
|
-
const role = linkElement.getAttribute("role");
|
|
2670
|
-
if (!role) {
|
|
2671
|
-
return [];
|
|
2672
|
-
}
|
|
2673
|
-
if (!LINK_TO_CROSS_CHECK.includes(role)) {
|
|
2674
|
-
return [];
|
|
2606
|
+
// src/validation/utils/retrieveTextIgnoringNodesWithSelector.ts
|
|
2607
|
+
var retrieveTextIgnoringNodesWithSelector = (element, selector = ".del") => {
|
|
2608
|
+
const clonedElement = element.cloneNode(true);
|
|
2609
|
+
for (const delElement of clonedElement.querySelectorAll(selector)) {
|
|
2610
|
+
delElement.remove();
|
|
2675
2611
|
}
|
|
2676
|
-
|
|
2677
|
-
|
|
2612
|
+
return clonedElement.textContent || "";
|
|
2613
|
+
};
|
|
2614
|
+
|
|
2615
|
+
// src/helpers/getStore.ts
|
|
2616
|
+
var getStore = (element) => {
|
|
2617
|
+
return element.getAttribute(STORE_ATTRIBUTE) || "";
|
|
2618
|
+
};
|
|
2619
|
+
|
|
2620
|
+
// src/validation/helpers/generateValidationIssueId.ts
|
|
2621
|
+
var generateValidationIssueId = () => {
|
|
2622
|
+
if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
|
|
2623
|
+
return crypto.randomUUID();
|
|
2678
2624
|
}
|
|
2679
|
-
|
|
2680
|
-
|
|
2681
|
-
|
|
2682
|
-
|
|
2683
|
-
|
|
2684
|
-
|
|
2685
|
-
|
|
2686
|
-
|
|
2687
|
-
|
|
2688
|
-
|
|
2625
|
+
return `${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
2626
|
+
};
|
|
2627
|
+
|
|
2628
|
+
// src/validation/helpers/addValidationIssue.ts
|
|
2629
|
+
var createValidationIssue = (issue) => ({
|
|
2630
|
+
id: generateValidationIssueId(),
|
|
2631
|
+
...issue
|
|
2632
|
+
});
|
|
2633
|
+
var addValidationIssue = (errors, issue) => {
|
|
2634
|
+
errors.push(createValidationIssue(issue));
|
|
2689
2635
|
};
|
|
2690
2636
|
|
|
2691
2637
|
// src/validation/validateFootnotes.ts
|
|
@@ -2698,15 +2644,11 @@ var extractFootnoteNumber = (footnote) => {
|
|
|
2698
2644
|
}
|
|
2699
2645
|
return footnoteNumber;
|
|
2700
2646
|
};
|
|
2701
|
-
var
|
|
2647
|
+
var validateFootnoteNumber = (footnoteElement) => {
|
|
2702
2648
|
const errors = [];
|
|
2703
|
-
const linkend = footnoteElement.getAttribute("xmlid") || "";
|
|
2704
2649
|
const footnoteNumber = footnoteElement.querySelector(
|
|
2705
2650
|
FOOTNOTE_NUMBER_SCHEMA.tag
|
|
2706
2651
|
);
|
|
2707
|
-
if (findElementLinkedTo(linkend, linkElements)) {
|
|
2708
|
-
return errors;
|
|
2709
|
-
}
|
|
2710
2652
|
if (!footnoteNumber) {
|
|
2711
2653
|
addValidationIssue(errors, {
|
|
2712
2654
|
store: getStore(footnoteElement),
|
|
@@ -2716,14 +2658,6 @@ var validateFootnoteCue = (footnoteElement, linkElements) => {
|
|
|
2716
2658
|
level: "blocker"
|
|
2717
2659
|
});
|
|
2718
2660
|
}
|
|
2719
|
-
const label = extractFootnoteNumber(footnoteNumber);
|
|
2720
|
-
addValidationIssue(errors, {
|
|
2721
|
-
store: getStore(footnoteElement),
|
|
2722
|
-
title: "Unreferenced footnote",
|
|
2723
|
-
kind: "unlinked",
|
|
2724
|
-
description: `The footnote ${label} is not referenced to any footnote cue in this chapter. Please reference it in the chapter.`,
|
|
2725
|
-
level: "blocker"
|
|
2726
|
-
});
|
|
2727
2661
|
return errors;
|
|
2728
2662
|
};
|
|
2729
2663
|
var validateConsecutiveFootnotes = (root) => {
|
|
@@ -2808,6 +2742,92 @@ var validateConsecutiveFootnoteCues = (root) => {
|
|
|
2808
2742
|
return errors;
|
|
2809
2743
|
};
|
|
2810
2744
|
|
|
2745
|
+
// src/validation/validateLinkend.ts
|
|
2746
|
+
var findElementLinkedTo = (linkend, elementsToLink) => {
|
|
2747
|
+
return elementsToLink.includes(linkend);
|
|
2748
|
+
};
|
|
2749
|
+
var LINK_TO_CROSS_CHECK = [
|
|
2750
|
+
TABLE_LINK_ROLE,
|
|
2751
|
+
FIGURE_LINK_ROLE,
|
|
2752
|
+
EQUATION_LINK_ROLE,
|
|
2753
|
+
FOOTNOTE_LINK_ROLE,
|
|
2754
|
+
REFERENCE_LINK_ROLE
|
|
2755
|
+
];
|
|
2756
|
+
var LINK_BLOCKER_ROLES = [
|
|
2757
|
+
TABLE_LINK_ROLE,
|
|
2758
|
+
FIGURE_LINK_ROLE,
|
|
2759
|
+
EQUATION_LINK_ROLE,
|
|
2760
|
+
FOOTNOTE_LINK_ROLE
|
|
2761
|
+
];
|
|
2762
|
+
var validateLinkend = (linkElement, elementsToLink) => {
|
|
2763
|
+
const linkend = linkElement.getAttribute("linkend");
|
|
2764
|
+
if (!linkend) {
|
|
2765
|
+
return [];
|
|
2766
|
+
}
|
|
2767
|
+
if (findElementLinkedTo(linkend, elementsToLink)) {
|
|
2768
|
+
return [];
|
|
2769
|
+
}
|
|
2770
|
+
const isLinkFootnoteCue = matchesSchemaTag(
|
|
2771
|
+
linkElement,
|
|
2772
|
+
FOOTNOTE_LINK_SCHEMA.tag
|
|
2773
|
+
);
|
|
2774
|
+
if (isLinkFootnoteCue) {
|
|
2775
|
+
return [
|
|
2776
|
+
createValidationIssue({
|
|
2777
|
+
store: getStore(linkElement),
|
|
2778
|
+
title: "Unlinked footnote cue",
|
|
2779
|
+
kind: "unlinked",
|
|
2780
|
+
description: "This footnote cue is not referenced to any footnote in this chapter. Please link it again manually.",
|
|
2781
|
+
level: "blocker"
|
|
2782
|
+
})
|
|
2783
|
+
];
|
|
2784
|
+
}
|
|
2785
|
+
const isLink = matchesSchemaTag(linkElement, LINK_SCHEMA.tag);
|
|
2786
|
+
if (!isLink) {
|
|
2787
|
+
return [];
|
|
2788
|
+
}
|
|
2789
|
+
const role = linkElement.getAttribute("role");
|
|
2790
|
+
if (!role) {
|
|
2791
|
+
return [];
|
|
2792
|
+
}
|
|
2793
|
+
if (!LINK_TO_CROSS_CHECK.includes(role)) {
|
|
2794
|
+
return [];
|
|
2795
|
+
}
|
|
2796
|
+
const isBlocker = LINK_BLOCKER_ROLES.includes(role.toLowerCase());
|
|
2797
|
+
return [
|
|
2798
|
+
createValidationIssue({
|
|
2799
|
+
store: getStore(linkElement),
|
|
2800
|
+
title: "Unlinked element",
|
|
2801
|
+
kind: "unlinked",
|
|
2802
|
+
description: "This link is not referenced to any element in the current chapter or any other chapter. Please link it again manually.",
|
|
2803
|
+
level: isBlocker ? "blocker" : "warning"
|
|
2804
|
+
})
|
|
2805
|
+
];
|
|
2806
|
+
};
|
|
2807
|
+
|
|
2808
|
+
// src/helpers/isIgnoredAttribute.ts
|
|
2809
|
+
var IGNORED_ATTRIBUTES = [
|
|
2810
|
+
// Styling & layout
|
|
2811
|
+
"class",
|
|
2812
|
+
"style",
|
|
2813
|
+
// Editor state
|
|
2814
|
+
"contenteditable",
|
|
2815
|
+
"draggable",
|
|
2816
|
+
"data-prevpos",
|
|
2817
|
+
"tabindex",
|
|
2818
|
+
// Browser behaviour
|
|
2819
|
+
"spellcheck",
|
|
2820
|
+
"translate",
|
|
2821
|
+
"lang",
|
|
2822
|
+
"dir",
|
|
2823
|
+
"hidden",
|
|
2824
|
+
"data-gramm"
|
|
2825
|
+
];
|
|
2826
|
+
var IGNORED_ATTRIBUTES_STARTS_WITH = ["er-", "er_", "drop", "drag"];
|
|
2827
|
+
var isIgnoredAttribute = (attribute) => IGNORED_ATTRIBUTES.includes(attribute) || IGNORED_ATTRIBUTES_STARTS_WITH.some(
|
|
2828
|
+
(startsWith) => attribute.startsWith(startsWith)
|
|
2829
|
+
);
|
|
2830
|
+
|
|
2811
2831
|
// src/validation/validateAttributes.ts
|
|
2812
2832
|
var validateAttributes = (element, schema) => {
|
|
2813
2833
|
const errors = [];
|
|
@@ -2851,7 +2871,7 @@ var validateAttributes = (element, schema) => {
|
|
|
2851
2871
|
// src/validation/validateChildren.ts
|
|
2852
2872
|
var validateElementAgainstSchema = (element, schema) => {
|
|
2853
2873
|
const errors = [];
|
|
2854
|
-
if (element
|
|
2874
|
+
if (!matchesSchemaTag(element, schema.tag)) {
|
|
2855
2875
|
addValidationIssue(errors, {
|
|
2856
2876
|
store: getStore(element),
|
|
2857
2877
|
title: `Expected ${schema.tag}, got ${element.tagName}`,
|
|
@@ -2952,27 +2972,79 @@ var getExtraInstruction = (schema, childSchema) => {
|
|
|
2952
2972
|
return "";
|
|
2953
2973
|
};
|
|
2954
2974
|
|
|
2955
|
-
// src/validation/
|
|
2975
|
+
// src/validation/validateElementToLinkTo.ts
|
|
2956
2976
|
var findElementLinkedTo2 = (xmlid, linkElements) => {
|
|
2957
2977
|
return linkElements.includes(xmlid);
|
|
2958
2978
|
};
|
|
2959
|
-
var
|
|
2960
|
-
|
|
2979
|
+
var isFootnote = (element) => {
|
|
2980
|
+
return matchesSchemaTag(element, FOOTNOTE_SCHEMA.tag);
|
|
2981
|
+
};
|
|
2982
|
+
var isReference = (element) => {
|
|
2983
|
+
return matchesSchemaTag(element, BIBLIOMIXED_SCHEMA.tag) || !!closestElementBySchema({
|
|
2984
|
+
element,
|
|
2985
|
+
code: "referenceBibliography"
|
|
2986
|
+
});
|
|
2987
|
+
};
|
|
2988
|
+
var isTable = (element) => {
|
|
2989
|
+
return matchesSchemaTag(element, TABLE_SCHEMA.tag);
|
|
2990
|
+
};
|
|
2991
|
+
var isFigure = (element) => {
|
|
2992
|
+
return matchesSchemaTag(element, FIGURE_SCHEMA.tag);
|
|
2993
|
+
};
|
|
2994
|
+
var validateElementToLinkTo = (element, linkElements) => {
|
|
2995
|
+
const xmlid = element.getAttribute("xmlid");
|
|
2961
2996
|
if (!xmlid) {
|
|
2962
2997
|
return [];
|
|
2963
2998
|
}
|
|
2964
2999
|
if (findElementLinkedTo2(xmlid, linkElements)) {
|
|
2965
3000
|
return [];
|
|
2966
3001
|
}
|
|
2967
|
-
|
|
2968
|
-
|
|
2969
|
-
|
|
2970
|
-
|
|
2971
|
-
|
|
2972
|
-
|
|
2973
|
-
|
|
2974
|
-
|
|
2975
|
-
|
|
3002
|
+
if (isFootnote(element)) {
|
|
3003
|
+
const label = extractFootnoteNumber(element);
|
|
3004
|
+
return [
|
|
3005
|
+
createValidationIssue({
|
|
3006
|
+
store: getStore(element),
|
|
3007
|
+
title: "Uncited footnote",
|
|
3008
|
+
kind: "uncited",
|
|
3009
|
+
description: `The footnote ${label} is not cited to any footnote cue in this chapter. Please reference it in the chapter.`,
|
|
3010
|
+
level: "blocker"
|
|
3011
|
+
})
|
|
3012
|
+
];
|
|
3013
|
+
}
|
|
3014
|
+
if (isReference(element)) {
|
|
3015
|
+
return [
|
|
3016
|
+
createValidationIssue({
|
|
3017
|
+
store: getStore(element),
|
|
3018
|
+
title: "Uncited reference",
|
|
3019
|
+
kind: "uncited",
|
|
3020
|
+
description: "This reference is not cited in this chapter or any other chapter. Please add a link to this reference or delete it.",
|
|
3021
|
+
level: "warning"
|
|
3022
|
+
})
|
|
3023
|
+
];
|
|
3024
|
+
}
|
|
3025
|
+
if (isTable(element)) {
|
|
3026
|
+
return [
|
|
3027
|
+
createValidationIssue({
|
|
3028
|
+
store: getStore(element),
|
|
3029
|
+
title: "Uncited table",
|
|
3030
|
+
kind: "uncited",
|
|
3031
|
+
description: "This table is not cited in this chapter or any other chapter. Please add a link to this table or delete it.",
|
|
3032
|
+
level: "warning"
|
|
3033
|
+
})
|
|
3034
|
+
];
|
|
3035
|
+
}
|
|
3036
|
+
if (isFigure(element)) {
|
|
3037
|
+
return [
|
|
3038
|
+
createValidationIssue({
|
|
3039
|
+
store: getStore(element),
|
|
3040
|
+
title: "Uncited figure",
|
|
3041
|
+
kind: "uncited",
|
|
3042
|
+
description: "This figure is not cited in this chapter or any other chapter. Please add a link to this figure or delete it.",
|
|
3043
|
+
level: "warning"
|
|
3044
|
+
})
|
|
3045
|
+
];
|
|
3046
|
+
}
|
|
3047
|
+
return [];
|
|
2976
3048
|
};
|
|
2977
3049
|
|
|
2978
3050
|
// src/validation/validateWeblink.ts
|
|
@@ -3024,30 +3096,12 @@ var validatePossibleWeblinks = (root) => {
|
|
|
3024
3096
|
return errors;
|
|
3025
3097
|
};
|
|
3026
3098
|
|
|
3027
|
-
// src/validation/utils/getParentElement.ts
|
|
3028
|
-
var getParentElement = ({
|
|
3029
|
-
element,
|
|
3030
|
-
schemaCode,
|
|
3031
|
-
filterDeletedNodes
|
|
3032
|
-
}) => {
|
|
3033
|
-
let current = element.parentElement;
|
|
3034
|
-
while (current) {
|
|
3035
|
-
const isValidParent = findSchemaByElement(current)?.code === schemaCode;
|
|
3036
|
-
const isFilterDeleted = filterDeletedNodes && isDeletedElement(current);
|
|
3037
|
-
if (isValidParent || isFilterDeleted) {
|
|
3038
|
-
return current;
|
|
3039
|
-
}
|
|
3040
|
-
current = current.parentElement;
|
|
3041
|
-
}
|
|
3042
|
-
return void 0;
|
|
3043
|
-
};
|
|
3044
|
-
|
|
3045
3099
|
// src/validation/validateHeadingHierarchy.ts
|
|
3046
3100
|
var getHierarchyLevel = (element) => {
|
|
3047
3101
|
const role = element.getAttribute("role");
|
|
3048
3102
|
if (!role) return void 0;
|
|
3049
|
-
const validHeadingLevel = HEADING_LEVEL.indexOf(role)
|
|
3050
|
-
if (
|
|
3103
|
+
const validHeadingLevel = HEADING_LEVEL.indexOf(role);
|
|
3104
|
+
if (validHeadingLevel === -1) return void 0;
|
|
3051
3105
|
return validHeadingLevel;
|
|
3052
3106
|
};
|
|
3053
3107
|
var validateHeadingHierarchy = (element) => {
|
|
@@ -3059,13 +3113,16 @@ var validateHeadingHierarchy = (element) => {
|
|
|
3059
3113
|
if (level === void 0) {
|
|
3060
3114
|
return errors;
|
|
3061
3115
|
}
|
|
3062
|
-
|
|
3063
|
-
|
|
3064
|
-
|
|
3065
|
-
|
|
3116
|
+
if (!element.parentElement) {
|
|
3117
|
+
return errors;
|
|
3118
|
+
}
|
|
3119
|
+
const parentHeading = closestElementBySchema({
|
|
3120
|
+
element: element.parentElement,
|
|
3121
|
+
code: HEADING_SCHEMA.code,
|
|
3122
|
+
ignoreDeletedElements: true
|
|
3066
3123
|
});
|
|
3067
3124
|
if (!parentHeading) {
|
|
3068
|
-
if (level
|
|
3125
|
+
if (level > 1) {
|
|
3069
3126
|
addValidationIssue(errors, {
|
|
3070
3127
|
store: getStore(element),
|
|
3071
3128
|
title: "Missing heading H1",
|
|
@@ -3095,7 +3152,7 @@ var validateHeadingHierarchy = (element) => {
|
|
|
3095
3152
|
};
|
|
3096
3153
|
|
|
3097
3154
|
// src/validation/validateOlink.ts
|
|
3098
|
-
var ORCID_PATTERN = /^\d{4}-\d{4}-\d{4}-\d{
|
|
3155
|
+
var ORCID_PATTERN = /^\d{4}-\d{4}-\d{4}-\d{3}[\dX]$/;
|
|
3099
3156
|
var validateOlink = (element) => {
|
|
3100
3157
|
const errors = [];
|
|
3101
3158
|
if (isDeletedElement(element)) {
|
|
@@ -3128,14 +3185,8 @@ var validateElement = (element, root, elementsToLink, linkElements, schemasToVal
|
|
|
3128
3185
|
if (schemasToValidateAgainst.includes(schema.code)) {
|
|
3129
3186
|
errors.push(...validateElementAgainstSchema(element, schema));
|
|
3130
3187
|
}
|
|
3131
|
-
if (schema.tag === LINK_SCHEMA.tag || schema.tag === FOOTNOTE_LINK_SCHEMA.tag) {
|
|
3132
|
-
errors.push(...validateLinkend(element, elementsToLink));
|
|
3133
|
-
}
|
|
3134
|
-
if (schema.tag === BIBLIOMIXED_SCHEMA.tag) {
|
|
3135
|
-
errors.push(...validateReferenceCited(element, linkElements));
|
|
3136
|
-
}
|
|
3137
3188
|
if (schema.tag === FOOTNOTE_SCHEMA.tag) {
|
|
3138
|
-
errors.push(...
|
|
3189
|
+
errors.push(...validateFootnoteNumber(element));
|
|
3139
3190
|
}
|
|
3140
3191
|
if (schema.code === HEADING_SCHEMA.code) {
|
|
3141
3192
|
errors.push(...validateHeadingHierarchy(element));
|
|
@@ -3143,6 +3194,8 @@ var validateElement = (element, root, elementsToLink, linkElements, schemasToVal
|
|
|
3143
3194
|
if (schema.code === OLINK_SCHEMA.code) {
|
|
3144
3195
|
errors.push(...validateOlink(element));
|
|
3145
3196
|
}
|
|
3197
|
+
errors.push(...validateLinkend(element, elementsToLink));
|
|
3198
|
+
errors.push(...validateElementToLinkTo(element, linkElements));
|
|
3146
3199
|
if (isIgnoredValidation(schema.code)) {
|
|
3147
3200
|
return errors;
|
|
3148
3201
|
}
|
|
@@ -3178,6 +3231,84 @@ var validateXml = (xml, elementsToLink, linkElements, schemasToValidateAgainst)
|
|
|
3178
3231
|
}
|
|
3179
3232
|
return errors;
|
|
3180
3233
|
};
|
|
3234
|
+
|
|
3235
|
+
// src/helpers/getElementLinks.ts
|
|
3236
|
+
var getElementLinks = (contentChaptersToValidate) => {
|
|
3237
|
+
const elementsToLink = [];
|
|
3238
|
+
const linkedElements = [];
|
|
3239
|
+
for (const chapter of contentChaptersToValidate) {
|
|
3240
|
+
const parser = new DOMParser();
|
|
3241
|
+
const content = parser.parseFromString(chapter, "text/html");
|
|
3242
|
+
const elementsXMLID = content.querySelectorAll(`[${XMLID_ATTRIBUTE}]`);
|
|
3243
|
+
for (const elementWithXMLID of elementsXMLID) {
|
|
3244
|
+
const linkValue = elementWithXMLID.getAttribute(XMLID_ATTRIBUTE);
|
|
3245
|
+
if (!linkValue) continue;
|
|
3246
|
+
elementsToLink.push(linkValue);
|
|
3247
|
+
}
|
|
3248
|
+
const elementsLinkend = content.querySelectorAll(`[${LINKEND_ATTRIBUTE}]`);
|
|
3249
|
+
for (const elementWithLinkend of elementsLinkend) {
|
|
3250
|
+
const linkendValue = elementWithLinkend.getAttribute(LINKEND_ATTRIBUTE);
|
|
3251
|
+
if (!linkendValue) continue;
|
|
3252
|
+
linkedElements.push(linkendValue);
|
|
3253
|
+
}
|
|
3254
|
+
}
|
|
3255
|
+
return { elementsToLink, linkedElements };
|
|
3256
|
+
};
|
|
3257
|
+
|
|
3258
|
+
// src/helpers/createElement.ts
|
|
3259
|
+
var createElement = ({
|
|
3260
|
+
schemaCode,
|
|
3261
|
+
attributes
|
|
3262
|
+
}) => {
|
|
3263
|
+
const schema = findSchemaByCode(schemaCode);
|
|
3264
|
+
const element = document.createElement(schema.tag.toLowerCase());
|
|
3265
|
+
for (const [name, value] of Object.entries(attributes)) {
|
|
3266
|
+
if (!value) continue;
|
|
3267
|
+
element.setAttribute(name, String(value));
|
|
3268
|
+
}
|
|
3269
|
+
return element;
|
|
3270
|
+
};
|
|
3271
|
+
|
|
3272
|
+
// src/helpers/queryElementBySchema.ts
|
|
3273
|
+
var queryElementBySchema = (content, schemaCode) => {
|
|
3274
|
+
const schema = findSchemaByCode(schemaCode);
|
|
3275
|
+
const element = content.querySelector(schema.tag.toLowerCase());
|
|
3276
|
+
if (!element) return void 0;
|
|
3277
|
+
if (schema.matchesElement && !schema.matchesElement(element)) {
|
|
3278
|
+
return void 0;
|
|
3279
|
+
}
|
|
3280
|
+
return element;
|
|
3281
|
+
};
|
|
3282
|
+
var queryAllElementsBySchema = (content, schemaCode) => {
|
|
3283
|
+
const schema = findSchemaByCode(schemaCode);
|
|
3284
|
+
const elements = content.querySelectorAll(
|
|
3285
|
+
schema.tag.toLowerCase()
|
|
3286
|
+
);
|
|
3287
|
+
const matchingElements = [];
|
|
3288
|
+
for (const element of elements) {
|
|
3289
|
+
if (schema.matchesElement && !schema.matchesElement(element)) {
|
|
3290
|
+
continue;
|
|
3291
|
+
}
|
|
3292
|
+
matchingElements.push(element);
|
|
3293
|
+
}
|
|
3294
|
+
return matchingElements;
|
|
3295
|
+
};
|
|
3296
|
+
|
|
3297
|
+
// src/helpers/getAdjacentElement.ts
|
|
3298
|
+
var getAdjacentElement = ({
|
|
3299
|
+
element,
|
|
3300
|
+
direction,
|
|
3301
|
+
code
|
|
3302
|
+
}) => {
|
|
3303
|
+
let current = element;
|
|
3304
|
+
while (current) {
|
|
3305
|
+
const sibling = direction === "next" ? current.nextElementSibling : current.previousElementSibling;
|
|
3306
|
+
if (sibling instanceof HTMLElement) {
|
|
3307
|
+
return closestElementBySchema({ element: sibling, code }) || queryElementBySchema(sibling, code);
|
|
3308
|
+
}
|
|
3309
|
+
current = current.parentElement;
|
|
3310
|
+
}
|
|
3311
|
+
};
|
|
3181
3312
|
export {
|
|
3182
3313
|
ALIGNMENT_ATTRIBUTE,
|
|
3183
3314
|
ATOM_SCHEMAS,
|
|
@@ -3190,7 +3321,6 @@ export {
|
|
|
3190
3321
|
IGNORED_ATTRIBUTES,
|
|
3191
3322
|
IGNORED_ATTRIBUTES_STARTS_WITH,
|
|
3192
3323
|
IGNORED_ELEMENT_SELECTORS,
|
|
3193
|
-
IGNORED_VALIDATION_ELEMENT_SELECTORS,
|
|
3194
3324
|
INDENT_TYPE_ATTRIBUTE,
|
|
3195
3325
|
INLINE_ELEMENT_SCHEMAS,
|
|
3196
3326
|
LAYOUT_ATTRIBUTES,
|
|
@@ -3199,6 +3329,7 @@ export {
|
|
|
3199
3329
|
LAYOUT_TABLE_PLACEMENT_ATTRIBUTE,
|
|
3200
3330
|
LAYOUT_USER_ATTRIBUTE,
|
|
3201
3331
|
LEFT_INDENT_ATTRIBUTE,
|
|
3332
|
+
LINKEND_ATTRIBUTE,
|
|
3202
3333
|
RIGHT_INDENT_ATTRIBUTE,
|
|
3203
3334
|
SCHEMAS,
|
|
3204
3335
|
SPACE_ABOVE_ATTRIBUTE,
|
|
@@ -3211,15 +3342,20 @@ export {
|
|
|
3211
3342
|
TRACK_CHANGES_ATTR_DATA_TIME,
|
|
3212
3343
|
TRACK_CHANGES_ATTR_DATA_USERID,
|
|
3213
3344
|
TRACK_CHANGES_ATTR_DATA_USERNAME,
|
|
3345
|
+
XMLID_ATTRIBUTE,
|
|
3346
|
+
closestElementBySchema,
|
|
3214
3347
|
createElement,
|
|
3215
3348
|
findAttributeDefinitionByName,
|
|
3216
3349
|
findSchemaByCode,
|
|
3217
3350
|
findSchemaByElement,
|
|
3351
|
+
getAdjacentElement,
|
|
3218
3352
|
getAttributeName,
|
|
3353
|
+
getElementLinks,
|
|
3354
|
+
getStore,
|
|
3219
3355
|
isAttributeRestricted,
|
|
3356
|
+
isDeletedElement,
|
|
3220
3357
|
isIgnoredAttribute,
|
|
3221
3358
|
isIgnoredElement,
|
|
3222
|
-
isIgnoredValidation,
|
|
3223
3359
|
isTrackChangesSchema,
|
|
3224
3360
|
queryAllElementsBySchema,
|
|
3225
3361
|
queryElementBySchema,
|