pro-editor-schema 0.2.21 → 0.2.24

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.
Files changed (3) hide show
  1. package/dist/index.js +133 -83
  2. package/dist/index.mjs +133 -83
  3. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -244,7 +244,13 @@ var INSERTION_SCHEMA = createSchema({
244
244
  tag: SPAN_TAG,
245
245
  matchesElement: (element) => element.classList.contains("ins"),
246
246
  requiredAttributes: [...TRACK_CHANGES_ATTRS, ...ID_ATTRS],
247
- optionalAttributes: [],
247
+ optionalAttributes: [
248
+ {
249
+ name: "role",
250
+ values: ["web-link", "figure-note-link", "figsource"],
251
+ defaultValue: ""
252
+ }
253
+ ],
248
254
  allowedChildrenCodes: [
249
255
  ...ATOM_CODES_ALLOWED_CHILDREN,
250
256
  ...INLINE_ELEMENT_CODES_ALLOWED_CHILDREN
@@ -2334,8 +2340,8 @@ var URI_SCHEMA = createSchema({
2334
2340
  code: "uri",
2335
2341
  kind: "inline",
2336
2342
  tag: URI_TAG,
2337
- requiredAttributes: [...ID_ATTRS],
2338
- optionalAttributes: ["linkend"],
2343
+ requiredAttributes: [],
2344
+ optionalAttributes: ["xlinkhref"],
2339
2345
  allowedChildrenCodes: [...ATOM_CODES_ALLOWED_CHILDREN]
2340
2346
  });
2341
2347
 
@@ -2601,6 +2607,84 @@ var retrieveTextIgnoringNodesWithSelector = (element, selector = ".del") => {
2601
2607
  return clonedElement.textContent || "";
2602
2608
  };
2603
2609
 
2610
+ // src/validation/utils/getElementsSelector.ts
2611
+ var getElementsSelector = ({
2612
+ element,
2613
+ selector,
2614
+ filterDeletedNodes
2615
+ }) => {
2616
+ const elements = element.querySelectorAll(selector);
2617
+ if (filterDeletedNodes) {
2618
+ return Array.from(elements).filter((element2) => {
2619
+ const hasDeletedParent = element2.closest(".del") !== null;
2620
+ if (hasDeletedParent) {
2621
+ return false;
2622
+ }
2623
+ return true;
2624
+ });
2625
+ }
2626
+ return Array.from(elements);
2627
+ };
2628
+
2629
+ // src/validation/validateLinkend.ts
2630
+ var findElementLinkedTo = (linkend, elementsToLink) => {
2631
+ return elementsToLink.includes(linkend);
2632
+ };
2633
+ var LINK_TO_CROSS_CHECK = [
2634
+ TABLE_LINK_ROLE,
2635
+ FIGURE_LINK_ROLE,
2636
+ EQUATION_LINK_ROLE,
2637
+ FOOTNOTE_LINK_ROLE,
2638
+ REFERENCE_LINK_ROLE
2639
+ ];
2640
+ var LINK_BLOCKER_ROLES = [
2641
+ TABLE_LINK_ROLE,
2642
+ FIGURE_LINK_ROLE,
2643
+ EQUATION_LINK_ROLE,
2644
+ FOOTNOTE_LINK_ROLE
2645
+ ];
2646
+ var validateLinkend = (linkElement, elementsToLink) => {
2647
+ const linkend = linkElement.getAttribute("linkend");
2648
+ if (!linkend) {
2649
+ return [];
2650
+ }
2651
+ const isLinkFootnoteCue = linkElement.tagName.toUpperCase() === FOOTNOTE_LINK_SCHEMA.tag;
2652
+ if (isLinkFootnoteCue) {
2653
+ if (findElementLinkedTo(linkend, elementsToLink)) {
2654
+ return [];
2655
+ }
2656
+ return [
2657
+ createValidationIssue({
2658
+ store: getStore(linkElement),
2659
+ title: "Unlinked footnote cue",
2660
+ kind: "unlinked",
2661
+ description: "This footnote cue is not referenced to any footnote in this chapter. Please link it again manually.",
2662
+ level: "blocker"
2663
+ })
2664
+ ];
2665
+ }
2666
+ const role = linkElement.getAttribute("role");
2667
+ if (!role) {
2668
+ return [];
2669
+ }
2670
+ if (!LINK_TO_CROSS_CHECK.includes(role)) {
2671
+ return [];
2672
+ }
2673
+ if (findElementLinkedTo(linkend, elementsToLink)) {
2674
+ return [];
2675
+ }
2676
+ const isBlocker = LINK_BLOCKER_ROLES.includes(role.toLowerCase());
2677
+ return [
2678
+ createValidationIssue({
2679
+ store: getStore(linkElement),
2680
+ title: "Unlinked element",
2681
+ kind: "unlinked",
2682
+ description: "This link is not referenced to any element in the current chapter or any other chapter. Please link it again manually.",
2683
+ level: isBlocker ? "blocker" : "warning"
2684
+ })
2685
+ ];
2686
+ };
2687
+
2604
2688
  // src/validation/validateFootnotes.ts
2605
2689
  var extractFootnoteNumber = (footnote) => {
2606
2690
  if (!footnote) return "no label";
@@ -2611,16 +2695,13 @@ var extractFootnoteNumber = (footnote) => {
2611
2695
  }
2612
2696
  return footnoteNumber;
2613
2697
  };
2614
- var validateFootnoteCue = (footnoteElement, root) => {
2698
+ var validateFootnoteCue = (footnoteElement, linkElements) => {
2615
2699
  const errors = [];
2616
2700
  const linkend = footnoteElement.getAttribute("xmlid") || "";
2617
2701
  const footnoteNumber = footnoteElement.querySelector(
2618
2702
  FOOTNOTE_NUMBER_SCHEMA.tag
2619
2703
  );
2620
- const footnoteLink = root.querySelector(
2621
- `${FOOTNOTE_LINK_SCHEMA.tag}[linkend='${CSS.escape(linkend)}']`
2622
- );
2623
- if (footnoteLink) {
2704
+ if (findElementLinkedTo(linkend, linkElements)) {
2624
2705
  return errors;
2625
2706
  }
2626
2707
  if (!footnoteNumber) {
@@ -2642,8 +2723,12 @@ var validateFootnoteCue = (footnoteElement, root) => {
2642
2723
  });
2643
2724
  return errors;
2644
2725
  };
2645
- var validateConsecutiveFootnotes = (root) => {
2646
- const footnotes = Array.from(root.querySelectorAll(FOOTNOTE_SCHEMA.tag));
2726
+ var validateConsecutiveFootnotes = (element) => {
2727
+ const footnotes = getElementsSelector({
2728
+ element,
2729
+ selector: FOOTNOTE_SCHEMA.tag,
2730
+ filterDeletedNodes: true
2731
+ });
2647
2732
  if (footnotes.length === 0) {
2648
2733
  return [];
2649
2734
  }
@@ -2671,10 +2756,12 @@ var validateConsecutiveFootnotes = (root) => {
2671
2756
  }
2672
2757
  return [];
2673
2758
  };
2674
- var validateConsecutiveFootnoteCues = (root) => {
2675
- const footnoteLinks = Array.from(
2676
- root.querySelectorAll(FOOTNOTE_LINK_SCHEMA.tag)
2677
- );
2759
+ var validateConsecutiveFootnoteCues = (element) => {
2760
+ const footnoteLinks = getElementsSelector({
2761
+ element,
2762
+ selector: FOOTNOTE_LINK_SCHEMA.tag,
2763
+ filterDeletedNodes: true
2764
+ });
2678
2765
  if (footnoteLinks.length === 0) {
2679
2766
  return [];
2680
2767
  }
@@ -2697,56 +2784,6 @@ var validateConsecutiveFootnoteCues = (root) => {
2697
2784
  return [];
2698
2785
  };
2699
2786
 
2700
- // src/validation/validateLinkend.ts
2701
- var findElementLinkedTo = (linkend, elementsToLink) => {
2702
- return elementsToLink.includes(linkend);
2703
- };
2704
- var LINK_BLOCKER_ROLES = [
2705
- TABLE_LINK_ROLE,
2706
- FIGURE_LINK_ROLE,
2707
- EQUATION_LINK_ROLE,
2708
- FOOTNOTE_LINK_ROLE,
2709
- CHAPTER_LINK_ROLE
2710
- ];
2711
- var validateLinkend = (linkElement, elementsToLink) => {
2712
- const linkend = linkElement.getAttribute("linkend");
2713
- if (!linkend) {
2714
- return [];
2715
- }
2716
- const isLinkFootnoteCue = linkElement.tagName.toUpperCase() === FOOTNOTE_LINK_SCHEMA.tag;
2717
- if (isLinkFootnoteCue) {
2718
- if (findElementLinkedTo(linkend, elementsToLink)) {
2719
- return [];
2720
- }
2721
- return [
2722
- createValidationIssue({
2723
- store: getStore(linkElement),
2724
- title: "Unlinked footnote cue",
2725
- kind: "unlinked",
2726
- description: "This footnote cue is not referenced to any footnote in this chapter. Please link it again manually.",
2727
- level: "blocker"
2728
- })
2729
- ];
2730
- }
2731
- const role = linkElement.getAttribute("role");
2732
- if (!role) {
2733
- return [];
2734
- }
2735
- if (findElementLinkedTo(linkend, elementsToLink)) {
2736
- return [];
2737
- }
2738
- const isBlocker = LINK_BLOCKER_ROLES.includes(role.toLowerCase());
2739
- return [
2740
- createValidationIssue({
2741
- store: getStore(linkElement),
2742
- title: "Unlinked element",
2743
- kind: "unlinked",
2744
- description: "This link is not referenced to any element in the current chapter or any other chapter. Please link it again manually.",
2745
- level: isBlocker ? "blocker" : "warning"
2746
- })
2747
- ];
2748
- };
2749
-
2750
2787
  // src/validation/validateAttributes.ts
2751
2788
  var validateAttributes = (element, schema) => {
2752
2789
  const errors = [];
@@ -2878,21 +2915,6 @@ var validateChildren = (element, schema) => {
2878
2915
  return errors;
2879
2916
  };
2880
2917
 
2881
- // src/validation/utils/getLinkableRoles.ts
2882
- var getLinkableRoles = () => {
2883
- const linkRoleDefinition = findAttributeDefinitionByName(
2884
- LINK_SCHEMA.requiredAttributes,
2885
- "role"
2886
- );
2887
- if (!linkRoleDefinition) {
2888
- return [];
2889
- }
2890
- if (isAttributeRestricted(linkRoleDefinition)) {
2891
- return linkRoleDefinition.values;
2892
- }
2893
- return [];
2894
- };
2895
-
2896
2918
  // src/validation/validateReferences.ts
2897
2919
  var findElementLinkedTo2 = (xmlid, linkElements) => {
2898
2920
  return linkElements.includes(xmlid);
@@ -2916,6 +2938,33 @@ var validateReferenceCited = (referenceElement, linkElements) => {
2916
2938
  ];
2917
2939
  };
2918
2940
 
2941
+ // src/validation/validateUri.ts
2942
+ var WEB_URI_REGEX = /^(?:(?:https?):\/\/)?(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}(?::\d{1,5})?(?:\/[^\s]*)?$/i;
2943
+ var isValidUri = (uri) => {
2944
+ if (!uri || /\s/.test(uri)) {
2945
+ return false;
2946
+ }
2947
+ if (/^[a-z][a-z0-9+.-]*:/i.test(uri) && !/^https?:\/\//i.test(uri)) {
2948
+ return false;
2949
+ }
2950
+ return WEB_URI_REGEX.test(uri);
2951
+ };
2952
+ var validateUri = (uriElement) => {
2953
+ const url = uriElement.textContent.trim();
2954
+ if (isValidUri(url)) {
2955
+ return [];
2956
+ }
2957
+ return [
2958
+ createValidationIssue({
2959
+ store: getStore(uriElement),
2960
+ title: "URL cannot be reached",
2961
+ kind: "unlinked",
2962
+ description: "URL cannot be reached. Please check and adjust.",
2963
+ level: "warning"
2964
+ })
2965
+ ];
2966
+ };
2967
+
2919
2968
  // src/validation/validateXml.ts
2920
2969
  var validateElement = (element, root, elementsToLink, linkElements, schemasToValidateAgainst) => {
2921
2970
  if (isIgnoredElement(element)) {
@@ -2927,16 +2976,17 @@ var validateElement = (element, root, elementsToLink, linkElements, schemasToVal
2927
2976
  if (schemasToValidateAgainst.includes(schema.code)) {
2928
2977
  errors.push(...validateElementAgainstSchema(element, schema));
2929
2978
  }
2930
- const role = element.getAttribute("role");
2931
- const linkableRoles = getLinkableRoles();
2932
- if (schema.tag === LINK_SCHEMA.tag && role && linkableRoles.includes(role) || schema.tag === FOOTNOTE_LINK_SCHEMA.tag) {
2979
+ if (schema.tag === LINK_SCHEMA.tag || schema.tag === FOOTNOTE_LINK_SCHEMA.tag) {
2933
2980
  errors.push(...validateLinkend(element, elementsToLink));
2934
2981
  }
2935
2982
  if (schema.tag === BIBLIOMIXED_SCHEMA.tag) {
2936
2983
  errors.push(...validateReferenceCited(element, linkElements));
2937
2984
  }
2938
2985
  if (schema.tag === FOOTNOTE_SCHEMA.tag) {
2939
- errors.push(...validateFootnoteCue(element, root));
2986
+ errors.push(...validateFootnoteCue(element, linkElements));
2987
+ }
2988
+ if (schema.tag === URI_SCHEMA.tag) {
2989
+ errors.push(...validateUri(element));
2940
2990
  }
2941
2991
  if (isIgnoredValidation(schema.code)) {
2942
2992
  return errors;
package/dist/index.mjs CHANGED
@@ -176,7 +176,13 @@ var INSERTION_SCHEMA = createSchema({
176
176
  tag: SPAN_TAG,
177
177
  matchesElement: (element) => element.classList.contains("ins"),
178
178
  requiredAttributes: [...TRACK_CHANGES_ATTRS, ...ID_ATTRS],
179
- optionalAttributes: [],
179
+ optionalAttributes: [
180
+ {
181
+ name: "role",
182
+ values: ["web-link", "figure-note-link", "figsource"],
183
+ defaultValue: ""
184
+ }
185
+ ],
180
186
  allowedChildrenCodes: [
181
187
  ...ATOM_CODES_ALLOWED_CHILDREN,
182
188
  ...INLINE_ELEMENT_CODES_ALLOWED_CHILDREN
@@ -2266,8 +2272,8 @@ var URI_SCHEMA = createSchema({
2266
2272
  code: "uri",
2267
2273
  kind: "inline",
2268
2274
  tag: URI_TAG,
2269
- requiredAttributes: [...ID_ATTRS],
2270
- optionalAttributes: ["linkend"],
2275
+ requiredAttributes: [],
2276
+ optionalAttributes: ["xlinkhref"],
2271
2277
  allowedChildrenCodes: [...ATOM_CODES_ALLOWED_CHILDREN]
2272
2278
  });
2273
2279
 
@@ -2533,6 +2539,84 @@ var retrieveTextIgnoringNodesWithSelector = (element, selector = ".del") => {
2533
2539
  return clonedElement.textContent || "";
2534
2540
  };
2535
2541
 
2542
+ // src/validation/utils/getElementsSelector.ts
2543
+ var getElementsSelector = ({
2544
+ element,
2545
+ selector,
2546
+ filterDeletedNodes
2547
+ }) => {
2548
+ const elements = element.querySelectorAll(selector);
2549
+ if (filterDeletedNodes) {
2550
+ return Array.from(elements).filter((element2) => {
2551
+ const hasDeletedParent = element2.closest(".del") !== null;
2552
+ if (hasDeletedParent) {
2553
+ return false;
2554
+ }
2555
+ return true;
2556
+ });
2557
+ }
2558
+ return Array.from(elements);
2559
+ };
2560
+
2561
+ // src/validation/validateLinkend.ts
2562
+ var findElementLinkedTo = (linkend, elementsToLink) => {
2563
+ return elementsToLink.includes(linkend);
2564
+ };
2565
+ var LINK_TO_CROSS_CHECK = [
2566
+ TABLE_LINK_ROLE,
2567
+ FIGURE_LINK_ROLE,
2568
+ EQUATION_LINK_ROLE,
2569
+ FOOTNOTE_LINK_ROLE,
2570
+ REFERENCE_LINK_ROLE
2571
+ ];
2572
+ var LINK_BLOCKER_ROLES = [
2573
+ TABLE_LINK_ROLE,
2574
+ FIGURE_LINK_ROLE,
2575
+ EQUATION_LINK_ROLE,
2576
+ FOOTNOTE_LINK_ROLE
2577
+ ];
2578
+ var validateLinkend = (linkElement, elementsToLink) => {
2579
+ const linkend = linkElement.getAttribute("linkend");
2580
+ if (!linkend) {
2581
+ return [];
2582
+ }
2583
+ const isLinkFootnoteCue = linkElement.tagName.toUpperCase() === FOOTNOTE_LINK_SCHEMA.tag;
2584
+ if (isLinkFootnoteCue) {
2585
+ if (findElementLinkedTo(linkend, elementsToLink)) {
2586
+ return [];
2587
+ }
2588
+ return [
2589
+ createValidationIssue({
2590
+ store: getStore(linkElement),
2591
+ title: "Unlinked footnote cue",
2592
+ kind: "unlinked",
2593
+ description: "This footnote cue is not referenced to any footnote in this chapter. Please link it again manually.",
2594
+ level: "blocker"
2595
+ })
2596
+ ];
2597
+ }
2598
+ const role = linkElement.getAttribute("role");
2599
+ if (!role) {
2600
+ return [];
2601
+ }
2602
+ if (!LINK_TO_CROSS_CHECK.includes(role)) {
2603
+ return [];
2604
+ }
2605
+ if (findElementLinkedTo(linkend, elementsToLink)) {
2606
+ return [];
2607
+ }
2608
+ const isBlocker = LINK_BLOCKER_ROLES.includes(role.toLowerCase());
2609
+ return [
2610
+ createValidationIssue({
2611
+ store: getStore(linkElement),
2612
+ title: "Unlinked element",
2613
+ kind: "unlinked",
2614
+ description: "This link is not referenced to any element in the current chapter or any other chapter. Please link it again manually.",
2615
+ level: isBlocker ? "blocker" : "warning"
2616
+ })
2617
+ ];
2618
+ };
2619
+
2536
2620
  // src/validation/validateFootnotes.ts
2537
2621
  var extractFootnoteNumber = (footnote) => {
2538
2622
  if (!footnote) return "no label";
@@ -2543,16 +2627,13 @@ var extractFootnoteNumber = (footnote) => {
2543
2627
  }
2544
2628
  return footnoteNumber;
2545
2629
  };
2546
- var validateFootnoteCue = (footnoteElement, root) => {
2630
+ var validateFootnoteCue = (footnoteElement, linkElements) => {
2547
2631
  const errors = [];
2548
2632
  const linkend = footnoteElement.getAttribute("xmlid") || "";
2549
2633
  const footnoteNumber = footnoteElement.querySelector(
2550
2634
  FOOTNOTE_NUMBER_SCHEMA.tag
2551
2635
  );
2552
- const footnoteLink = root.querySelector(
2553
- `${FOOTNOTE_LINK_SCHEMA.tag}[linkend='${CSS.escape(linkend)}']`
2554
- );
2555
- if (footnoteLink) {
2636
+ if (findElementLinkedTo(linkend, linkElements)) {
2556
2637
  return errors;
2557
2638
  }
2558
2639
  if (!footnoteNumber) {
@@ -2574,8 +2655,12 @@ var validateFootnoteCue = (footnoteElement, root) => {
2574
2655
  });
2575
2656
  return errors;
2576
2657
  };
2577
- var validateConsecutiveFootnotes = (root) => {
2578
- const footnotes = Array.from(root.querySelectorAll(FOOTNOTE_SCHEMA.tag));
2658
+ var validateConsecutiveFootnotes = (element) => {
2659
+ const footnotes = getElementsSelector({
2660
+ element,
2661
+ selector: FOOTNOTE_SCHEMA.tag,
2662
+ filterDeletedNodes: true
2663
+ });
2579
2664
  if (footnotes.length === 0) {
2580
2665
  return [];
2581
2666
  }
@@ -2603,10 +2688,12 @@ var validateConsecutiveFootnotes = (root) => {
2603
2688
  }
2604
2689
  return [];
2605
2690
  };
2606
- var validateConsecutiveFootnoteCues = (root) => {
2607
- const footnoteLinks = Array.from(
2608
- root.querySelectorAll(FOOTNOTE_LINK_SCHEMA.tag)
2609
- );
2691
+ var validateConsecutiveFootnoteCues = (element) => {
2692
+ const footnoteLinks = getElementsSelector({
2693
+ element,
2694
+ selector: FOOTNOTE_LINK_SCHEMA.tag,
2695
+ filterDeletedNodes: true
2696
+ });
2610
2697
  if (footnoteLinks.length === 0) {
2611
2698
  return [];
2612
2699
  }
@@ -2629,56 +2716,6 @@ var validateConsecutiveFootnoteCues = (root) => {
2629
2716
  return [];
2630
2717
  };
2631
2718
 
2632
- // src/validation/validateLinkend.ts
2633
- var findElementLinkedTo = (linkend, elementsToLink) => {
2634
- return elementsToLink.includes(linkend);
2635
- };
2636
- var LINK_BLOCKER_ROLES = [
2637
- TABLE_LINK_ROLE,
2638
- FIGURE_LINK_ROLE,
2639
- EQUATION_LINK_ROLE,
2640
- FOOTNOTE_LINK_ROLE,
2641
- CHAPTER_LINK_ROLE
2642
- ];
2643
- var validateLinkend = (linkElement, elementsToLink) => {
2644
- const linkend = linkElement.getAttribute("linkend");
2645
- if (!linkend) {
2646
- return [];
2647
- }
2648
- const isLinkFootnoteCue = linkElement.tagName.toUpperCase() === FOOTNOTE_LINK_SCHEMA.tag;
2649
- if (isLinkFootnoteCue) {
2650
- if (findElementLinkedTo(linkend, elementsToLink)) {
2651
- return [];
2652
- }
2653
- return [
2654
- createValidationIssue({
2655
- store: getStore(linkElement),
2656
- title: "Unlinked footnote cue",
2657
- kind: "unlinked",
2658
- description: "This footnote cue is not referenced to any footnote in this chapter. Please link it again manually.",
2659
- level: "blocker"
2660
- })
2661
- ];
2662
- }
2663
- const role = linkElement.getAttribute("role");
2664
- if (!role) {
2665
- return [];
2666
- }
2667
- if (findElementLinkedTo(linkend, elementsToLink)) {
2668
- return [];
2669
- }
2670
- const isBlocker = LINK_BLOCKER_ROLES.includes(role.toLowerCase());
2671
- return [
2672
- createValidationIssue({
2673
- store: getStore(linkElement),
2674
- title: "Unlinked element",
2675
- kind: "unlinked",
2676
- description: "This link is not referenced to any element in the current chapter or any other chapter. Please link it again manually.",
2677
- level: isBlocker ? "blocker" : "warning"
2678
- })
2679
- ];
2680
- };
2681
-
2682
2719
  // src/validation/validateAttributes.ts
2683
2720
  var validateAttributes = (element, schema) => {
2684
2721
  const errors = [];
@@ -2810,21 +2847,6 @@ var validateChildren = (element, schema) => {
2810
2847
  return errors;
2811
2848
  };
2812
2849
 
2813
- // src/validation/utils/getLinkableRoles.ts
2814
- var getLinkableRoles = () => {
2815
- const linkRoleDefinition = findAttributeDefinitionByName(
2816
- LINK_SCHEMA.requiredAttributes,
2817
- "role"
2818
- );
2819
- if (!linkRoleDefinition) {
2820
- return [];
2821
- }
2822
- if (isAttributeRestricted(linkRoleDefinition)) {
2823
- return linkRoleDefinition.values;
2824
- }
2825
- return [];
2826
- };
2827
-
2828
2850
  // src/validation/validateReferences.ts
2829
2851
  var findElementLinkedTo2 = (xmlid, linkElements) => {
2830
2852
  return linkElements.includes(xmlid);
@@ -2848,6 +2870,33 @@ var validateReferenceCited = (referenceElement, linkElements) => {
2848
2870
  ];
2849
2871
  };
2850
2872
 
2873
+ // src/validation/validateUri.ts
2874
+ var WEB_URI_REGEX = /^(?:(?:https?):\/\/)?(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}(?::\d{1,5})?(?:\/[^\s]*)?$/i;
2875
+ var isValidUri = (uri) => {
2876
+ if (!uri || /\s/.test(uri)) {
2877
+ return false;
2878
+ }
2879
+ if (/^[a-z][a-z0-9+.-]*:/i.test(uri) && !/^https?:\/\//i.test(uri)) {
2880
+ return false;
2881
+ }
2882
+ return WEB_URI_REGEX.test(uri);
2883
+ };
2884
+ var validateUri = (uriElement) => {
2885
+ const url = uriElement.textContent.trim();
2886
+ if (isValidUri(url)) {
2887
+ return [];
2888
+ }
2889
+ return [
2890
+ createValidationIssue({
2891
+ store: getStore(uriElement),
2892
+ title: "URL cannot be reached",
2893
+ kind: "unlinked",
2894
+ description: "URL cannot be reached. Please check and adjust.",
2895
+ level: "warning"
2896
+ })
2897
+ ];
2898
+ };
2899
+
2851
2900
  // src/validation/validateXml.ts
2852
2901
  var validateElement = (element, root, elementsToLink, linkElements, schemasToValidateAgainst) => {
2853
2902
  if (isIgnoredElement(element)) {
@@ -2859,16 +2908,17 @@ var validateElement = (element, root, elementsToLink, linkElements, schemasToVal
2859
2908
  if (schemasToValidateAgainst.includes(schema.code)) {
2860
2909
  errors.push(...validateElementAgainstSchema(element, schema));
2861
2910
  }
2862
- const role = element.getAttribute("role");
2863
- const linkableRoles = getLinkableRoles();
2864
- if (schema.tag === LINK_SCHEMA.tag && role && linkableRoles.includes(role) || schema.tag === FOOTNOTE_LINK_SCHEMA.tag) {
2911
+ if (schema.tag === LINK_SCHEMA.tag || schema.tag === FOOTNOTE_LINK_SCHEMA.tag) {
2865
2912
  errors.push(...validateLinkend(element, elementsToLink));
2866
2913
  }
2867
2914
  if (schema.tag === BIBLIOMIXED_SCHEMA.tag) {
2868
2915
  errors.push(...validateReferenceCited(element, linkElements));
2869
2916
  }
2870
2917
  if (schema.tag === FOOTNOTE_SCHEMA.tag) {
2871
- errors.push(...validateFootnoteCue(element, root));
2918
+ errors.push(...validateFootnoteCue(element, linkElements));
2919
+ }
2920
+ if (schema.tag === URI_SCHEMA.tag) {
2921
+ errors.push(...validateUri(element));
2872
2922
  }
2873
2923
  if (isIgnoredValidation(schema.code)) {
2874
2924
  return errors;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pro-editor-schema",
3
- "version": "0.2.21",
3
+ "version": "0.2.24",
4
4
  "description": "Pro Editor XML schemas",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",