pro-editor-schema 1.1.9 → 1.2.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/README.md CHANGED
@@ -197,12 +197,14 @@ const errors = validateXml(rootElement, elementsToLink, linkElements, [
197
197
 
198
198
  - Consecutive footnote number checks
199
199
  - Consecutive footnote cue checks
200
+ - Possible weblink checks
200
201
 
201
202
  It also runs per-element checks for:
202
203
 
203
204
  - Link targets (`linkend`) on linkable elements
204
205
  - Uncited bibliographic references
205
206
  - Unreferenced footnotes
207
+ - Heading hierarchy
206
208
 
207
209
  Schema-based attribute and child validation only runs for codes listed in `schemasToValidateAgainst`.
208
210
 
package/dist/index.d.mts CHANGED
@@ -86,21 +86,9 @@ declare const SCHEMAS: {
86
86
  email: Schema<readonly ["store", "ele-id"], readonly []>;
87
87
  org: Schema<readonly ["store", "ele-id"], readonly []>;
88
88
  degrees: Schema<readonly ["store", "ele-id"], readonly []>;
89
- dialogue: Schema<readonly ["store", "ele-id"], readonly ["data-username", "data-userid", "data-time", "data-date", {
90
- readonly name: "role";
91
- readonly values: readonly ["add-element"];
92
- readonly defaultValue: "add-element";
93
- }]>;
94
- line: Schema<readonly ["store", "ele-id"], readonly [{
95
- readonly name: "role";
96
- readonly values: readonly ["add-element"];
97
- readonly defaultValue: "add-element";
98
- }]>;
99
- speaker: Schema<readonly ["store", "ele-id"], readonly [{
100
- readonly name: "role";
101
- readonly values: readonly ["add-element"];
102
- readonly defaultValue: "add-element";
103
- }]>;
89
+ dialogue: Schema<readonly ["store", "ele-id"], readonly ["data-username", "data-userid", "data-time", "data-date", "role", "trackmsg"]>;
90
+ line: Schema<readonly ["store", "ele-id"], readonly ["role"]>;
91
+ speaker: Schema<readonly ["store", "ele-id"], readonly ["role"]>;
104
92
  equation: Schema<readonly ["store", "ele-id"], readonly ["data-username", "data-userid", "data-time", "data-date", {
105
93
  readonly name: "eqn-data";
106
94
  readonly values: readonly ["new", "updated"];
@@ -251,7 +239,7 @@ declare const SCHEMAS: {
251
239
  readonly values: readonly ["add-element", "change-element"];
252
240
  readonly defaultValue: "add-element";
253
241
  }]>;
254
- poem: Schema<readonly ["store", "ele-id"], readonly ["data-username", "data-userid", "data-time", "data-date", "role"]>;
242
+ poem: Schema<readonly ["store", "ele-id"], readonly ["data-username", "data-userid", "data-time", "data-date", "role", "trackmsg"]>;
255
243
  blockquote: Schema<readonly ["store", "ele-id"], readonly ["data-username", "data-userid", "data-time", "data-date", "xmlid", "data-tagname", "element-change-description", {
256
244
  readonly name: "role";
257
245
  readonly values: readonly ["add-element", "extract_group", "change-element"];
@@ -441,21 +429,9 @@ declare const ELEMENT_SCHEMAS: {
441
429
  email: Schema<readonly ["store", "ele-id"], readonly []>;
442
430
  org: Schema<readonly ["store", "ele-id"], readonly []>;
443
431
  degrees: Schema<readonly ["store", "ele-id"], readonly []>;
444
- dialogue: Schema<readonly ["store", "ele-id"], readonly ["data-username", "data-userid", "data-time", "data-date", {
445
- readonly name: "role";
446
- readonly values: readonly ["add-element"];
447
- readonly defaultValue: "add-element";
448
- }]>;
449
- line: Schema<readonly ["store", "ele-id"], readonly [{
450
- readonly name: "role";
451
- readonly values: readonly ["add-element"];
452
- readonly defaultValue: "add-element";
453
- }]>;
454
- speaker: Schema<readonly ["store", "ele-id"], readonly [{
455
- readonly name: "role";
456
- readonly values: readonly ["add-element"];
457
- readonly defaultValue: "add-element";
458
- }]>;
432
+ dialogue: Schema<readonly ["store", "ele-id"], readonly ["data-username", "data-userid", "data-time", "data-date", "role", "trackmsg"]>;
433
+ line: Schema<readonly ["store", "ele-id"], readonly ["role"]>;
434
+ speaker: Schema<readonly ["store", "ele-id"], readonly ["role"]>;
459
435
  equation: Schema<readonly ["store", "ele-id"], readonly ["data-username", "data-userid", "data-time", "data-date", {
460
436
  readonly name: "eqn-data";
461
437
  readonly values: readonly ["new", "updated"];
@@ -606,7 +582,7 @@ declare const ELEMENT_SCHEMAS: {
606
582
  readonly values: readonly ["add-element", "change-element"];
607
583
  readonly defaultValue: "add-element";
608
584
  }]>;
609
- poem: Schema<readonly ["store", "ele-id"], readonly ["data-username", "data-userid", "data-time", "data-date", "role"]>;
585
+ poem: Schema<readonly ["store", "ele-id"], readonly ["data-username", "data-userid", "data-time", "data-date", "role", "trackmsg"]>;
610
586
  blockquote: Schema<readonly ["store", "ele-id"], readonly ["data-username", "data-userid", "data-time", "data-date", "xmlid", "data-tagname", "element-change-description", {
611
587
  readonly name: "role";
612
588
  readonly values: readonly ["add-element", "extract_group", "change-element"];
package/dist/index.d.ts CHANGED
@@ -86,21 +86,9 @@ declare const SCHEMAS: {
86
86
  email: Schema<readonly ["store", "ele-id"], readonly []>;
87
87
  org: Schema<readonly ["store", "ele-id"], readonly []>;
88
88
  degrees: Schema<readonly ["store", "ele-id"], readonly []>;
89
- dialogue: Schema<readonly ["store", "ele-id"], readonly ["data-username", "data-userid", "data-time", "data-date", {
90
- readonly name: "role";
91
- readonly values: readonly ["add-element"];
92
- readonly defaultValue: "add-element";
93
- }]>;
94
- line: Schema<readonly ["store", "ele-id"], readonly [{
95
- readonly name: "role";
96
- readonly values: readonly ["add-element"];
97
- readonly defaultValue: "add-element";
98
- }]>;
99
- speaker: Schema<readonly ["store", "ele-id"], readonly [{
100
- readonly name: "role";
101
- readonly values: readonly ["add-element"];
102
- readonly defaultValue: "add-element";
103
- }]>;
89
+ dialogue: Schema<readonly ["store", "ele-id"], readonly ["data-username", "data-userid", "data-time", "data-date", "role", "trackmsg"]>;
90
+ line: Schema<readonly ["store", "ele-id"], readonly ["role"]>;
91
+ speaker: Schema<readonly ["store", "ele-id"], readonly ["role"]>;
104
92
  equation: Schema<readonly ["store", "ele-id"], readonly ["data-username", "data-userid", "data-time", "data-date", {
105
93
  readonly name: "eqn-data";
106
94
  readonly values: readonly ["new", "updated"];
@@ -251,7 +239,7 @@ declare const SCHEMAS: {
251
239
  readonly values: readonly ["add-element", "change-element"];
252
240
  readonly defaultValue: "add-element";
253
241
  }]>;
254
- poem: Schema<readonly ["store", "ele-id"], readonly ["data-username", "data-userid", "data-time", "data-date", "role"]>;
242
+ poem: Schema<readonly ["store", "ele-id"], readonly ["data-username", "data-userid", "data-time", "data-date", "role", "trackmsg"]>;
255
243
  blockquote: Schema<readonly ["store", "ele-id"], readonly ["data-username", "data-userid", "data-time", "data-date", "xmlid", "data-tagname", "element-change-description", {
256
244
  readonly name: "role";
257
245
  readonly values: readonly ["add-element", "extract_group", "change-element"];
@@ -441,21 +429,9 @@ declare const ELEMENT_SCHEMAS: {
441
429
  email: Schema<readonly ["store", "ele-id"], readonly []>;
442
430
  org: Schema<readonly ["store", "ele-id"], readonly []>;
443
431
  degrees: Schema<readonly ["store", "ele-id"], readonly []>;
444
- dialogue: Schema<readonly ["store", "ele-id"], readonly ["data-username", "data-userid", "data-time", "data-date", {
445
- readonly name: "role";
446
- readonly values: readonly ["add-element"];
447
- readonly defaultValue: "add-element";
448
- }]>;
449
- line: Schema<readonly ["store", "ele-id"], readonly [{
450
- readonly name: "role";
451
- readonly values: readonly ["add-element"];
452
- readonly defaultValue: "add-element";
453
- }]>;
454
- speaker: Schema<readonly ["store", "ele-id"], readonly [{
455
- readonly name: "role";
456
- readonly values: readonly ["add-element"];
457
- readonly defaultValue: "add-element";
458
- }]>;
432
+ dialogue: Schema<readonly ["store", "ele-id"], readonly ["data-username", "data-userid", "data-time", "data-date", "role", "trackmsg"]>;
433
+ line: Schema<readonly ["store", "ele-id"], readonly ["role"]>;
434
+ speaker: Schema<readonly ["store", "ele-id"], readonly ["role"]>;
459
435
  equation: Schema<readonly ["store", "ele-id"], readonly ["data-username", "data-userid", "data-time", "data-date", {
460
436
  readonly name: "eqn-data";
461
437
  readonly values: readonly ["new", "updated"];
@@ -606,7 +582,7 @@ declare const ELEMENT_SCHEMAS: {
606
582
  readonly values: readonly ["add-element", "change-element"];
607
583
  readonly defaultValue: "add-element";
608
584
  }]>;
609
- poem: Schema<readonly ["store", "ele-id"], readonly ["data-username", "data-userid", "data-time", "data-date", "role"]>;
585
+ poem: Schema<readonly ["store", "ele-id"], readonly ["data-username", "data-userid", "data-time", "data-date", "role", "trackmsg"]>;
610
586
  blockquote: Schema<readonly ["store", "ele-id"], readonly ["data-username", "data-userid", "data-time", "data-date", "xmlid", "data-tagname", "element-change-description", {
611
587
  readonly name: "role";
612
588
  readonly values: readonly ["add-element", "extract_group", "change-element"];
package/dist/index.js CHANGED
@@ -839,13 +839,7 @@ var LINE_SCHEMA = createSchema({
839
839
  kind: "element",
840
840
  tag: LINE_TAG,
841
841
  requiredAttributes: [...ID_ATTRS],
842
- optionalAttributes: [
843
- {
844
- name: "role",
845
- values: ["add-element"],
846
- defaultValue: "add-element"
847
- }
848
- ],
842
+ optionalAttributes: ["role"],
849
843
  allowedChildrenCodes: [
850
844
  ...ATOM_CODES_ALLOWED_CHILDREN,
851
845
  ...INLINE_ELEMENT_CODES_ALLOWED_CHILDREN
@@ -858,13 +852,7 @@ var SPEAKER_SCHEMA = createSchema({
858
852
  kind: "element",
859
853
  tag: SPEAKER_TAG,
860
854
  requiredAttributes: [...ID_ATTRS],
861
- optionalAttributes: [
862
- {
863
- name: "role",
864
- values: ["add-element"],
865
- defaultValue: "add-element"
866
- }
867
- ],
855
+ optionalAttributes: ["role"],
868
856
  allowedChildrenCodes: [...ATOM_CODES_ALLOWED_CHILDREN]
869
857
  });
870
858
 
@@ -874,16 +862,10 @@ var DIALOGUE_SCHEMA = createSchema({
874
862
  kind: "element",
875
863
  tag: DIALOGUE_TAG,
876
864
  requiredAttributes: [...ID_ATTRS],
877
- optionalAttributes: [
878
- ...TRACK_CHANGES_ATTRS,
879
- {
880
- name: "role",
881
- values: ["add-element"],
882
- defaultValue: "add-element"
883
- }
884
- ],
865
+ optionalAttributes: [...TRACK_CHANGES_ATTRS, "role", "trackmsg"],
866
+ defaultChildCode: "line",
885
867
  allowedChildrenCodes: [
886
- { code: "line", required: false },
868
+ { code: "line", required: true },
887
869
  { code: "speaker", required: true }
888
870
  ]
889
871
  });
@@ -2030,7 +2012,8 @@ var FOOTNOTE_SECTION_SCHEMA = createSchema({
2030
2012
  });
2031
2013
 
2032
2014
  // src/schema/elementSchemas/elements/heading.ts
2033
- var HEADING_ROLES = ["H1", "H2", "H3", "H4", "H5", "H6", "vignette_group"];
2015
+ var HEADING_LEVEL = ["H1", "H2", "H3", "H4", "H5", "H6"];
2016
+ var HEADING_ROLES = [...HEADING_LEVEL, "vignette_group"];
2034
2017
  var HEADING_SCHEMA = createSchema({
2035
2018
  code: "heading",
2036
2019
  kind: "element",
@@ -2097,7 +2080,7 @@ var POEM_SCHEMA = createSchema({
2097
2080
  kind: "element",
2098
2081
  tag: POEM_TAG,
2099
2082
  requiredAttributes: [...ID_ATTRS],
2100
- optionalAttributes: [...TRACK_CHANGES_ATTRS, "role"],
2083
+ optionalAttributes: [...TRACK_CHANGES_ATTRS, "role", "trackmsg"],
2101
2084
  defaultChildCode: "line",
2102
2085
  allowedChildrenCodes: [
2103
2086
  { code: "line", required: true },
@@ -2655,23 +2638,22 @@ var retrieveTextIgnoringNodesWithSelector = (element, selector = ".del") => {
2655
2638
  return clonedElement.textContent || "";
2656
2639
  };
2657
2640
 
2641
+ // src/validation/utils/isDeletedElement.ts
2642
+ var isDeletedElement = (element) => {
2643
+ return !!element.closest(".del");
2644
+ };
2645
+
2658
2646
  // src/validation/utils/getElementsSelector.ts
2659
2647
  var getElementsSelector = ({
2660
2648
  element,
2661
2649
  selector,
2662
2650
  filterDeletedNodes
2663
2651
  }) => {
2664
- const elements = element.querySelectorAll(selector);
2652
+ const elements = Array.from(element.querySelectorAll(selector));
2665
2653
  if (filterDeletedNodes) {
2666
- return Array.from(elements).filter((element2) => {
2667
- const hasDeletedParent = element2.closest(".del") !== null;
2668
- if (hasDeletedParent) {
2669
- return false;
2670
- }
2671
- return true;
2672
- });
2654
+ return elements.filter((element2) => !isDeletedElement(element2));
2673
2655
  }
2674
- return Array.from(elements);
2656
+ return elements;
2675
2657
  };
2676
2658
 
2677
2659
  // src/validation/validateLinkend.ts
@@ -3056,6 +3038,97 @@ var validatePossibleWeblinks = (root) => {
3056
3038
  return errors;
3057
3039
  };
3058
3040
 
3041
+ // src/validation/utils/getParentElement.ts
3042
+ var getParentElement = ({
3043
+ element,
3044
+ schemaCode,
3045
+ filterDeletedNodes
3046
+ }) => {
3047
+ let current = element.parentElement;
3048
+ while (current) {
3049
+ const isValidParent = findSchemaByElement(current)?.code === schemaCode;
3050
+ const isFilterDeleted = filterDeletedNodes && isDeletedElement(current);
3051
+ if (isValidParent || isFilterDeleted) {
3052
+ return current;
3053
+ }
3054
+ current = current.parentElement;
3055
+ }
3056
+ return void 0;
3057
+ };
3058
+
3059
+ // src/validation/validateHeadingHierarchy.ts
3060
+ var getHierarchyLevel = (element) => {
3061
+ const role = element.getAttribute("role");
3062
+ if (!role) return void 0;
3063
+ const validHeadingLevel = HEADING_LEVEL.indexOf(role) + 1;
3064
+ if (!validHeadingLevel) return void 0;
3065
+ return validHeadingLevel;
3066
+ };
3067
+ var validateHeadingHierarchy = (element) => {
3068
+ const errors = [];
3069
+ if (isDeletedElement(element)) {
3070
+ return errors;
3071
+ }
3072
+ const level = getHierarchyLevel(element);
3073
+ if (level === void 0) {
3074
+ return errors;
3075
+ }
3076
+ const parentHeading = getParentElement({
3077
+ element,
3078
+ schemaCode: HEADING_SCHEMA.code,
3079
+ filterDeletedNodes: true
3080
+ });
3081
+ if (!parentHeading) {
3082
+ if (level !== 1) {
3083
+ addValidationIssue(errors, {
3084
+ store: getStore(element),
3085
+ title: "Missing heading H1",
3086
+ kind: "missing",
3087
+ description: `H${level} is not under an H1. Please check the heading hierarchy.`,
3088
+ level: "warning"
3089
+ });
3090
+ }
3091
+ return errors;
3092
+ }
3093
+ const parentLevel = getHierarchyLevel(parentHeading);
3094
+ if (parentLevel === void 0) {
3095
+ return errors;
3096
+ }
3097
+ const expectedLevel = parentLevel + 1;
3098
+ if (level === expectedLevel) {
3099
+ return errors;
3100
+ }
3101
+ addValidationIssue(errors, {
3102
+ store: getStore(element),
3103
+ title: "Invalid heading hierarchy",
3104
+ kind: "forbidden",
3105
+ description: `H${level} cannot follow H${parentLevel} directly. Please check the heading hierarchy.`,
3106
+ level: "warning"
3107
+ });
3108
+ return errors;
3109
+ };
3110
+
3111
+ // src/validation/validateOlink.ts
3112
+ var ORCID_PATTERN = /^\d{4}-\d{4}-\d{4}-\d{4}$/;
3113
+ var validateOlink = (element) => {
3114
+ const errors = [];
3115
+ if (isDeletedElement(element)) {
3116
+ return errors;
3117
+ }
3118
+ const text = retrieveTextIgnoringNodesWithSelector(element).trim();
3119
+ if (ORCID_PATTERN.test(text)) {
3120
+ return errors;
3121
+ }
3122
+ addValidationIssue(errors, {
3123
+ store: getStore(element.parentElement ?? element),
3124
+ title: "Invalid ORCID",
3125
+ kind: "forbidden",
3126
+ description: "The ORCiD is not the correct format. Please check it and adjust.",
3127
+ level: "warning"
3128
+ });
3129
+ return errors;
3130
+ };
3131
+
3059
3132
  // src/validation/validateXml.ts
3060
3133
  var validateElement = (element, root, elementsToLink, linkElements, schemasToValidateAgainst) => {
3061
3134
  if (isIgnoredElement(element)) {
@@ -3076,6 +3149,12 @@ var validateElement = (element, root, elementsToLink, linkElements, schemasToVal
3076
3149
  if (schema.tag === FOOTNOTE_SCHEMA.tag) {
3077
3150
  errors.push(...validateFootnoteCue(element, linkElements));
3078
3151
  }
3152
+ if (schema.code === HEADING_SCHEMA.code) {
3153
+ errors.push(...validateHeadingHierarchy(element));
3154
+ }
3155
+ if (schema.code === OLINK_SCHEMA.code) {
3156
+ errors.push(...validateOlink(element));
3157
+ }
3079
3158
  if (isIgnoredValidation(schema.code)) {
3080
3159
  return errors;
3081
3160
  }
package/dist/index.mjs CHANGED
@@ -759,13 +759,7 @@ var LINE_SCHEMA = createSchema({
759
759
  kind: "element",
760
760
  tag: LINE_TAG,
761
761
  requiredAttributes: [...ID_ATTRS],
762
- optionalAttributes: [
763
- {
764
- name: "role",
765
- values: ["add-element"],
766
- defaultValue: "add-element"
767
- }
768
- ],
762
+ optionalAttributes: ["role"],
769
763
  allowedChildrenCodes: [
770
764
  ...ATOM_CODES_ALLOWED_CHILDREN,
771
765
  ...INLINE_ELEMENT_CODES_ALLOWED_CHILDREN
@@ -778,13 +772,7 @@ var SPEAKER_SCHEMA = createSchema({
778
772
  kind: "element",
779
773
  tag: SPEAKER_TAG,
780
774
  requiredAttributes: [...ID_ATTRS],
781
- optionalAttributes: [
782
- {
783
- name: "role",
784
- values: ["add-element"],
785
- defaultValue: "add-element"
786
- }
787
- ],
775
+ optionalAttributes: ["role"],
788
776
  allowedChildrenCodes: [...ATOM_CODES_ALLOWED_CHILDREN]
789
777
  });
790
778
 
@@ -794,16 +782,10 @@ var DIALOGUE_SCHEMA = createSchema({
794
782
  kind: "element",
795
783
  tag: DIALOGUE_TAG,
796
784
  requiredAttributes: [...ID_ATTRS],
797
- optionalAttributes: [
798
- ...TRACK_CHANGES_ATTRS,
799
- {
800
- name: "role",
801
- values: ["add-element"],
802
- defaultValue: "add-element"
803
- }
804
- ],
785
+ optionalAttributes: [...TRACK_CHANGES_ATTRS, "role", "trackmsg"],
786
+ defaultChildCode: "line",
805
787
  allowedChildrenCodes: [
806
- { code: "line", required: false },
788
+ { code: "line", required: true },
807
789
  { code: "speaker", required: true }
808
790
  ]
809
791
  });
@@ -1950,7 +1932,8 @@ var FOOTNOTE_SECTION_SCHEMA = createSchema({
1950
1932
  });
1951
1933
 
1952
1934
  // src/schema/elementSchemas/elements/heading.ts
1953
- var HEADING_ROLES = ["H1", "H2", "H3", "H4", "H5", "H6", "vignette_group"];
1935
+ var HEADING_LEVEL = ["H1", "H2", "H3", "H4", "H5", "H6"];
1936
+ var HEADING_ROLES = [...HEADING_LEVEL, "vignette_group"];
1954
1937
  var HEADING_SCHEMA = createSchema({
1955
1938
  code: "heading",
1956
1939
  kind: "element",
@@ -2017,7 +2000,7 @@ var POEM_SCHEMA = createSchema({
2017
2000
  kind: "element",
2018
2001
  tag: POEM_TAG,
2019
2002
  requiredAttributes: [...ID_ATTRS],
2020
- optionalAttributes: [...TRACK_CHANGES_ATTRS, "role"],
2003
+ optionalAttributes: [...TRACK_CHANGES_ATTRS, "role", "trackmsg"],
2021
2004
  defaultChildCode: "line",
2022
2005
  allowedChildrenCodes: [
2023
2006
  { code: "line", required: true },
@@ -2575,23 +2558,22 @@ var retrieveTextIgnoringNodesWithSelector = (element, selector = ".del") => {
2575
2558
  return clonedElement.textContent || "";
2576
2559
  };
2577
2560
 
2561
+ // src/validation/utils/isDeletedElement.ts
2562
+ var isDeletedElement = (element) => {
2563
+ return !!element.closest(".del");
2564
+ };
2565
+
2578
2566
  // src/validation/utils/getElementsSelector.ts
2579
2567
  var getElementsSelector = ({
2580
2568
  element,
2581
2569
  selector,
2582
2570
  filterDeletedNodes
2583
2571
  }) => {
2584
- const elements = element.querySelectorAll(selector);
2572
+ const elements = Array.from(element.querySelectorAll(selector));
2585
2573
  if (filterDeletedNodes) {
2586
- return Array.from(elements).filter((element2) => {
2587
- const hasDeletedParent = element2.closest(".del") !== null;
2588
- if (hasDeletedParent) {
2589
- return false;
2590
- }
2591
- return true;
2592
- });
2574
+ return elements.filter((element2) => !isDeletedElement(element2));
2593
2575
  }
2594
- return Array.from(elements);
2576
+ return elements;
2595
2577
  };
2596
2578
 
2597
2579
  // src/validation/validateLinkend.ts
@@ -2976,6 +2958,97 @@ var validatePossibleWeblinks = (root) => {
2976
2958
  return errors;
2977
2959
  };
2978
2960
 
2961
+ // src/validation/utils/getParentElement.ts
2962
+ var getParentElement = ({
2963
+ element,
2964
+ schemaCode,
2965
+ filterDeletedNodes
2966
+ }) => {
2967
+ let current = element.parentElement;
2968
+ while (current) {
2969
+ const isValidParent = findSchemaByElement(current)?.code === schemaCode;
2970
+ const isFilterDeleted = filterDeletedNodes && isDeletedElement(current);
2971
+ if (isValidParent || isFilterDeleted) {
2972
+ return current;
2973
+ }
2974
+ current = current.parentElement;
2975
+ }
2976
+ return void 0;
2977
+ };
2978
+
2979
+ // src/validation/validateHeadingHierarchy.ts
2980
+ var getHierarchyLevel = (element) => {
2981
+ const role = element.getAttribute("role");
2982
+ if (!role) return void 0;
2983
+ const validHeadingLevel = HEADING_LEVEL.indexOf(role) + 1;
2984
+ if (!validHeadingLevel) return void 0;
2985
+ return validHeadingLevel;
2986
+ };
2987
+ var validateHeadingHierarchy = (element) => {
2988
+ const errors = [];
2989
+ if (isDeletedElement(element)) {
2990
+ return errors;
2991
+ }
2992
+ const level = getHierarchyLevel(element);
2993
+ if (level === void 0) {
2994
+ return errors;
2995
+ }
2996
+ const parentHeading = getParentElement({
2997
+ element,
2998
+ schemaCode: HEADING_SCHEMA.code,
2999
+ filterDeletedNodes: true
3000
+ });
3001
+ if (!parentHeading) {
3002
+ if (level !== 1) {
3003
+ addValidationIssue(errors, {
3004
+ store: getStore(element),
3005
+ title: "Missing heading H1",
3006
+ kind: "missing",
3007
+ description: `H${level} is not under an H1. Please check the heading hierarchy.`,
3008
+ level: "warning"
3009
+ });
3010
+ }
3011
+ return errors;
3012
+ }
3013
+ const parentLevel = getHierarchyLevel(parentHeading);
3014
+ if (parentLevel === void 0) {
3015
+ return errors;
3016
+ }
3017
+ const expectedLevel = parentLevel + 1;
3018
+ if (level === expectedLevel) {
3019
+ return errors;
3020
+ }
3021
+ addValidationIssue(errors, {
3022
+ store: getStore(element),
3023
+ title: "Invalid heading hierarchy",
3024
+ kind: "forbidden",
3025
+ description: `H${level} cannot follow H${parentLevel} directly. Please check the heading hierarchy.`,
3026
+ level: "warning"
3027
+ });
3028
+ return errors;
3029
+ };
3030
+
3031
+ // src/validation/validateOlink.ts
3032
+ var ORCID_PATTERN = /^\d{4}-\d{4}-\d{4}-\d{4}$/;
3033
+ var validateOlink = (element) => {
3034
+ const errors = [];
3035
+ if (isDeletedElement(element)) {
3036
+ return errors;
3037
+ }
3038
+ const text = retrieveTextIgnoringNodesWithSelector(element).trim();
3039
+ if (ORCID_PATTERN.test(text)) {
3040
+ return errors;
3041
+ }
3042
+ addValidationIssue(errors, {
3043
+ store: getStore(element.parentElement ?? element),
3044
+ title: "Invalid ORCID",
3045
+ kind: "forbidden",
3046
+ description: "The ORCiD is not the correct format. Please check it and adjust.",
3047
+ level: "warning"
3048
+ });
3049
+ return errors;
3050
+ };
3051
+
2979
3052
  // src/validation/validateXml.ts
2980
3053
  var validateElement = (element, root, elementsToLink, linkElements, schemasToValidateAgainst) => {
2981
3054
  if (isIgnoredElement(element)) {
@@ -2996,6 +3069,12 @@ var validateElement = (element, root, elementsToLink, linkElements, schemasToVal
2996
3069
  if (schema.tag === FOOTNOTE_SCHEMA.tag) {
2997
3070
  errors.push(...validateFootnoteCue(element, linkElements));
2998
3071
  }
3072
+ if (schema.code === HEADING_SCHEMA.code) {
3073
+ errors.push(...validateHeadingHierarchy(element));
3074
+ }
3075
+ if (schema.code === OLINK_SCHEMA.code) {
3076
+ errors.push(...validateOlink(element));
3077
+ }
2999
3078
  if (isIgnoredValidation(schema.code)) {
3000
3079
  return errors;
3001
3080
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pro-editor-schema",
3
- "version": "1.1.9",
3
+ "version": "1.2.1",
4
4
  "description": "Pro Editor XML schemas",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",