pro-editor-schema 1.1.8 → 1.2.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 +2 -0
- package/dist/index.js +84 -11
- package/dist/index.mjs +84 -11
- package/package.json +1 -1
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.js
CHANGED
|
@@ -2030,7 +2030,8 @@ var FOOTNOTE_SECTION_SCHEMA = createSchema({
|
|
|
2030
2030
|
});
|
|
2031
2031
|
|
|
2032
2032
|
// src/schema/elementSchemas/elements/heading.ts
|
|
2033
|
-
var
|
|
2033
|
+
var HEADING_LEVEL = ["H1", "H2", "H3", "H4", "H5", "H6"];
|
|
2034
|
+
var HEADING_ROLES = [...HEADING_LEVEL, "vignette_group"];
|
|
2034
2035
|
var HEADING_SCHEMA = createSchema({
|
|
2035
2036
|
code: "heading",
|
|
2036
2037
|
kind: "element",
|
|
@@ -2655,23 +2656,22 @@ var retrieveTextIgnoringNodesWithSelector = (element, selector = ".del") => {
|
|
|
2655
2656
|
return clonedElement.textContent || "";
|
|
2656
2657
|
};
|
|
2657
2658
|
|
|
2659
|
+
// src/validation/utils/isDeletedElement.ts
|
|
2660
|
+
var isDeletedElement = (element) => {
|
|
2661
|
+
return !!element.closest(".del");
|
|
2662
|
+
};
|
|
2663
|
+
|
|
2658
2664
|
// src/validation/utils/getElementsSelector.ts
|
|
2659
2665
|
var getElementsSelector = ({
|
|
2660
2666
|
element,
|
|
2661
2667
|
selector,
|
|
2662
2668
|
filterDeletedNodes
|
|
2663
2669
|
}) => {
|
|
2664
|
-
const elements = element.querySelectorAll(selector);
|
|
2670
|
+
const elements = Array.from(element.querySelectorAll(selector));
|
|
2665
2671
|
if (filterDeletedNodes) {
|
|
2666
|
-
return
|
|
2667
|
-
const hasDeletedParent = element2.closest(".del") !== null;
|
|
2668
|
-
if (hasDeletedParent) {
|
|
2669
|
-
return false;
|
|
2670
|
-
}
|
|
2671
|
-
return true;
|
|
2672
|
-
});
|
|
2672
|
+
return elements.filter((element2) => !isDeletedElement(element2));
|
|
2673
2673
|
}
|
|
2674
|
-
return
|
|
2674
|
+
return elements;
|
|
2675
2675
|
};
|
|
2676
2676
|
|
|
2677
2677
|
// src/validation/validateLinkend.ts
|
|
@@ -3010,7 +3010,7 @@ var validateReferenceCited = (referenceElement, linkElements) => {
|
|
|
3010
3010
|
// src/validation/validateWeblink.ts
|
|
3011
3011
|
var import_mark = __toESM(require("mark.js"));
|
|
3012
3012
|
var EDGE_PUNCTUATION = `:;.,\\-\u2013\u2014\u2012_(){}[\\]!'"+=\xAB\xBB\u2039\u203A\u201C\u201D\u2018\u2019<>`;
|
|
3013
|
-
var WEB_URI_PATTERN = `(?:(?:https?):\\/\\/|www\\.)(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\\.)+[a-zA-Z]{2,}(?::\\d{1,5})?(?:\\/[^\\s]*[^\\s${EDGE_PUNCTUATION}])?`;
|
|
3013
|
+
var WEB_URI_PATTERN = `(?:(?:https?):\\/\\/|www\\.)(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\\.)+[a-zA-Z]{2,}(?::\\d{1,5})?(?:\\/(?:[^\\s]*[^\\s${EDGE_PUNCTUATION}])?)?`;
|
|
3014
3014
|
var WEB_URI_IN_TEXT_REGEX = new RegExp(WEB_URI_PATTERN, "gi");
|
|
3015
3015
|
var POSSIBLE_WEBLINK_EXCLUDE_SELECTORS = [
|
|
3016
3016
|
"tag",
|
|
@@ -3056,6 +3056,76 @@ var validatePossibleWeblinks = (root) => {
|
|
|
3056
3056
|
return errors;
|
|
3057
3057
|
};
|
|
3058
3058
|
|
|
3059
|
+
// src/validation/utils/getParentElement.ts
|
|
3060
|
+
var getParentElement = ({
|
|
3061
|
+
element,
|
|
3062
|
+
schemaCode,
|
|
3063
|
+
filterDeletedNodes
|
|
3064
|
+
}) => {
|
|
3065
|
+
let current = element.parentElement;
|
|
3066
|
+
while (current) {
|
|
3067
|
+
const isValidParent = findSchemaByElement(current)?.code === schemaCode;
|
|
3068
|
+
const isFilterDeleted = filterDeletedNodes && isDeletedElement(current);
|
|
3069
|
+
if (isValidParent || isFilterDeleted) {
|
|
3070
|
+
return current;
|
|
3071
|
+
}
|
|
3072
|
+
current = current.parentElement;
|
|
3073
|
+
}
|
|
3074
|
+
return void 0;
|
|
3075
|
+
};
|
|
3076
|
+
|
|
3077
|
+
// src/validation/validateHeadingHierarchy.ts
|
|
3078
|
+
var getHierarchyLevel = (element) => {
|
|
3079
|
+
const role = element.getAttribute("role");
|
|
3080
|
+
if (!role) return void 0;
|
|
3081
|
+
const validHeadingLevel = HEADING_LEVEL.indexOf(role) + 1;
|
|
3082
|
+
if (!validHeadingLevel) return void 0;
|
|
3083
|
+
return validHeadingLevel;
|
|
3084
|
+
};
|
|
3085
|
+
var validateHeadingHierarchy = (element) => {
|
|
3086
|
+
const errors = [];
|
|
3087
|
+
if (isDeletedElement(element)) {
|
|
3088
|
+
return errors;
|
|
3089
|
+
}
|
|
3090
|
+
const level = getHierarchyLevel(element);
|
|
3091
|
+
if (level === void 0) {
|
|
3092
|
+
return errors;
|
|
3093
|
+
}
|
|
3094
|
+
const parentHeading = getParentElement({
|
|
3095
|
+
element,
|
|
3096
|
+
schemaCode: HEADING_SCHEMA.code,
|
|
3097
|
+
filterDeletedNodes: true
|
|
3098
|
+
});
|
|
3099
|
+
if (!parentHeading) {
|
|
3100
|
+
if (level !== 1) {
|
|
3101
|
+
addValidationIssue(errors, {
|
|
3102
|
+
store: getStore(element),
|
|
3103
|
+
title: "Missing heading H1",
|
|
3104
|
+
kind: "missing",
|
|
3105
|
+
description: `H${level} is not under an H1. Please check the heading hierarchy.`,
|
|
3106
|
+
level: "warning"
|
|
3107
|
+
});
|
|
3108
|
+
}
|
|
3109
|
+
return errors;
|
|
3110
|
+
}
|
|
3111
|
+
const parentLevel = getHierarchyLevel(parentHeading);
|
|
3112
|
+
if (parentLevel === void 0) {
|
|
3113
|
+
return errors;
|
|
3114
|
+
}
|
|
3115
|
+
const expectedLevel = parentLevel + 1;
|
|
3116
|
+
if (level === expectedLevel) {
|
|
3117
|
+
return errors;
|
|
3118
|
+
}
|
|
3119
|
+
addValidationIssue(errors, {
|
|
3120
|
+
store: getStore(element),
|
|
3121
|
+
title: "Invalid heading hierarchy",
|
|
3122
|
+
kind: "forbidden",
|
|
3123
|
+
description: `H${level} cannot follow H${parentLevel} directly. Please check the heading hierarchy.`,
|
|
3124
|
+
level: "warning"
|
|
3125
|
+
});
|
|
3126
|
+
return errors;
|
|
3127
|
+
};
|
|
3128
|
+
|
|
3059
3129
|
// src/validation/validateXml.ts
|
|
3060
3130
|
var validateElement = (element, root, elementsToLink, linkElements, schemasToValidateAgainst) => {
|
|
3061
3131
|
if (isIgnoredElement(element)) {
|
|
@@ -3076,6 +3146,9 @@ var validateElement = (element, root, elementsToLink, linkElements, schemasToVal
|
|
|
3076
3146
|
if (schema.tag === FOOTNOTE_SCHEMA.tag) {
|
|
3077
3147
|
errors.push(...validateFootnoteCue(element, linkElements));
|
|
3078
3148
|
}
|
|
3149
|
+
if (schema.code === HEADING_SCHEMA.code) {
|
|
3150
|
+
errors.push(...validateHeadingHierarchy(element));
|
|
3151
|
+
}
|
|
3079
3152
|
if (isIgnoredValidation(schema.code)) {
|
|
3080
3153
|
return errors;
|
|
3081
3154
|
}
|
package/dist/index.mjs
CHANGED
|
@@ -1950,7 +1950,8 @@ var FOOTNOTE_SECTION_SCHEMA = createSchema({
|
|
|
1950
1950
|
});
|
|
1951
1951
|
|
|
1952
1952
|
// src/schema/elementSchemas/elements/heading.ts
|
|
1953
|
-
var
|
|
1953
|
+
var HEADING_LEVEL = ["H1", "H2", "H3", "H4", "H5", "H6"];
|
|
1954
|
+
var HEADING_ROLES = [...HEADING_LEVEL, "vignette_group"];
|
|
1954
1955
|
var HEADING_SCHEMA = createSchema({
|
|
1955
1956
|
code: "heading",
|
|
1956
1957
|
kind: "element",
|
|
@@ -2575,23 +2576,22 @@ var retrieveTextIgnoringNodesWithSelector = (element, selector = ".del") => {
|
|
|
2575
2576
|
return clonedElement.textContent || "";
|
|
2576
2577
|
};
|
|
2577
2578
|
|
|
2579
|
+
// src/validation/utils/isDeletedElement.ts
|
|
2580
|
+
var isDeletedElement = (element) => {
|
|
2581
|
+
return !!element.closest(".del");
|
|
2582
|
+
};
|
|
2583
|
+
|
|
2578
2584
|
// src/validation/utils/getElementsSelector.ts
|
|
2579
2585
|
var getElementsSelector = ({
|
|
2580
2586
|
element,
|
|
2581
2587
|
selector,
|
|
2582
2588
|
filterDeletedNodes
|
|
2583
2589
|
}) => {
|
|
2584
|
-
const elements = element.querySelectorAll(selector);
|
|
2590
|
+
const elements = Array.from(element.querySelectorAll(selector));
|
|
2585
2591
|
if (filterDeletedNodes) {
|
|
2586
|
-
return
|
|
2587
|
-
const hasDeletedParent = element2.closest(".del") !== null;
|
|
2588
|
-
if (hasDeletedParent) {
|
|
2589
|
-
return false;
|
|
2590
|
-
}
|
|
2591
|
-
return true;
|
|
2592
|
-
});
|
|
2592
|
+
return elements.filter((element2) => !isDeletedElement(element2));
|
|
2593
2593
|
}
|
|
2594
|
-
return
|
|
2594
|
+
return elements;
|
|
2595
2595
|
};
|
|
2596
2596
|
|
|
2597
2597
|
// src/validation/validateLinkend.ts
|
|
@@ -2930,7 +2930,7 @@ var validateReferenceCited = (referenceElement, linkElements) => {
|
|
|
2930
2930
|
// src/validation/validateWeblink.ts
|
|
2931
2931
|
import Mark from "mark.js";
|
|
2932
2932
|
var EDGE_PUNCTUATION = `:;.,\\-\u2013\u2014\u2012_(){}[\\]!'"+=\xAB\xBB\u2039\u203A\u201C\u201D\u2018\u2019<>`;
|
|
2933
|
-
var WEB_URI_PATTERN = `(?:(?:https?):\\/\\/|www\\.)(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\\.)+[a-zA-Z]{2,}(?::\\d{1,5})?(?:\\/[^\\s]*[^\\s${EDGE_PUNCTUATION}])?`;
|
|
2933
|
+
var WEB_URI_PATTERN = `(?:(?:https?):\\/\\/|www\\.)(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\\.)+[a-zA-Z]{2,}(?::\\d{1,5})?(?:\\/(?:[^\\s]*[^\\s${EDGE_PUNCTUATION}])?)?`;
|
|
2934
2934
|
var WEB_URI_IN_TEXT_REGEX = new RegExp(WEB_URI_PATTERN, "gi");
|
|
2935
2935
|
var POSSIBLE_WEBLINK_EXCLUDE_SELECTORS = [
|
|
2936
2936
|
"tag",
|
|
@@ -2976,6 +2976,76 @@ var validatePossibleWeblinks = (root) => {
|
|
|
2976
2976
|
return errors;
|
|
2977
2977
|
};
|
|
2978
2978
|
|
|
2979
|
+
// src/validation/utils/getParentElement.ts
|
|
2980
|
+
var getParentElement = ({
|
|
2981
|
+
element,
|
|
2982
|
+
schemaCode,
|
|
2983
|
+
filterDeletedNodes
|
|
2984
|
+
}) => {
|
|
2985
|
+
let current = element.parentElement;
|
|
2986
|
+
while (current) {
|
|
2987
|
+
const isValidParent = findSchemaByElement(current)?.code === schemaCode;
|
|
2988
|
+
const isFilterDeleted = filterDeletedNodes && isDeletedElement(current);
|
|
2989
|
+
if (isValidParent || isFilterDeleted) {
|
|
2990
|
+
return current;
|
|
2991
|
+
}
|
|
2992
|
+
current = current.parentElement;
|
|
2993
|
+
}
|
|
2994
|
+
return void 0;
|
|
2995
|
+
};
|
|
2996
|
+
|
|
2997
|
+
// src/validation/validateHeadingHierarchy.ts
|
|
2998
|
+
var getHierarchyLevel = (element) => {
|
|
2999
|
+
const role = element.getAttribute("role");
|
|
3000
|
+
if (!role) return void 0;
|
|
3001
|
+
const validHeadingLevel = HEADING_LEVEL.indexOf(role) + 1;
|
|
3002
|
+
if (!validHeadingLevel) return void 0;
|
|
3003
|
+
return validHeadingLevel;
|
|
3004
|
+
};
|
|
3005
|
+
var validateHeadingHierarchy = (element) => {
|
|
3006
|
+
const errors = [];
|
|
3007
|
+
if (isDeletedElement(element)) {
|
|
3008
|
+
return errors;
|
|
3009
|
+
}
|
|
3010
|
+
const level = getHierarchyLevel(element);
|
|
3011
|
+
if (level === void 0) {
|
|
3012
|
+
return errors;
|
|
3013
|
+
}
|
|
3014
|
+
const parentHeading = getParentElement({
|
|
3015
|
+
element,
|
|
3016
|
+
schemaCode: HEADING_SCHEMA.code,
|
|
3017
|
+
filterDeletedNodes: true
|
|
3018
|
+
});
|
|
3019
|
+
if (!parentHeading) {
|
|
3020
|
+
if (level !== 1) {
|
|
3021
|
+
addValidationIssue(errors, {
|
|
3022
|
+
store: getStore(element),
|
|
3023
|
+
title: "Missing heading H1",
|
|
3024
|
+
kind: "missing",
|
|
3025
|
+
description: `H${level} is not under an H1. Please check the heading hierarchy.`,
|
|
3026
|
+
level: "warning"
|
|
3027
|
+
});
|
|
3028
|
+
}
|
|
3029
|
+
return errors;
|
|
3030
|
+
}
|
|
3031
|
+
const parentLevel = getHierarchyLevel(parentHeading);
|
|
3032
|
+
if (parentLevel === void 0) {
|
|
3033
|
+
return errors;
|
|
3034
|
+
}
|
|
3035
|
+
const expectedLevel = parentLevel + 1;
|
|
3036
|
+
if (level === expectedLevel) {
|
|
3037
|
+
return errors;
|
|
3038
|
+
}
|
|
3039
|
+
addValidationIssue(errors, {
|
|
3040
|
+
store: getStore(element),
|
|
3041
|
+
title: "Invalid heading hierarchy",
|
|
3042
|
+
kind: "forbidden",
|
|
3043
|
+
description: `H${level} cannot follow H${parentLevel} directly. Please check the heading hierarchy.`,
|
|
3044
|
+
level: "warning"
|
|
3045
|
+
});
|
|
3046
|
+
return errors;
|
|
3047
|
+
};
|
|
3048
|
+
|
|
2979
3049
|
// src/validation/validateXml.ts
|
|
2980
3050
|
var validateElement = (element, root, elementsToLink, linkElements, schemasToValidateAgainst) => {
|
|
2981
3051
|
if (isIgnoredElement(element)) {
|
|
@@ -2996,6 +3066,9 @@ var validateElement = (element, root, elementsToLink, linkElements, schemasToVal
|
|
|
2996
3066
|
if (schema.tag === FOOTNOTE_SCHEMA.tag) {
|
|
2997
3067
|
errors.push(...validateFootnoteCue(element, linkElements));
|
|
2998
3068
|
}
|
|
3069
|
+
if (schema.code === HEADING_SCHEMA.code) {
|
|
3070
|
+
errors.push(...validateHeadingHierarchy(element));
|
|
3071
|
+
}
|
|
2999
3072
|
if (isIgnoredValidation(schema.code)) {
|
|
3000
3073
|
return errors;
|
|
3001
3074
|
}
|