pro-editor-schema 1.5.5-7 → 1.5.5-8
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 +23 -1
- package/dist/index.d.mts +24 -5
- package/dist/index.d.ts +24 -5
- package/dist/index.js +180 -67
- package/dist/index.mjs +177 -66
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -182,7 +182,7 @@ From `src/index.ts`, consumers can import:
|
|
|
182
182
|
- **Schema helpers:** `findSchemaByCode`, `findSchemaByElement`, `findAttributeDefinitionByName`, `getAttributeName`, `isAttributeRestricted`, `isTrackChangesSchema`
|
|
183
183
|
- **DOM helpers:** `createElement`, `closestElementBySchema`, `queryElementBySchema`, `queryAllElementsBySchema`, `getElementLinks`, `getStore`, `isDeletedElement`
|
|
184
184
|
- **Ignored nodes:** `isIgnoredAttribute`, `isIgnoredElement`, `IGNORED_ATTRIBUTES`, `IGNORED_ELEMENT_SELECTORS`
|
|
185
|
-
- **Validation:** `validateXml`
|
|
185
|
+
- **Validation:** `validateXml`, `validateXmlAsync`
|
|
186
186
|
- **Shared constants:** `ElementLabel`, global attribute constants, dependents forbidden elements
|
|
187
187
|
|
|
188
188
|
## Usage examples
|
|
@@ -256,6 +256,28 @@ It also runs per-element checks for:
|
|
|
256
256
|
|
|
257
257
|
Schema-based attribute and child validation only runs for codes listed in `schemasToValidateAgainst`.
|
|
258
258
|
|
|
259
|
+
### Validate a large document without freezing the page
|
|
260
|
+
|
|
261
|
+
```ts
|
|
262
|
+
import { validateXmlAsync } from "pro-editor-schema";
|
|
263
|
+
|
|
264
|
+
const controller = new AbortController();
|
|
265
|
+
const errors = await validateXmlAsync(
|
|
266
|
+
rootElement.cloneNode(true) as Element,
|
|
267
|
+
elementsToLink,
|
|
268
|
+
linkElements,
|
|
269
|
+
["para", "heading"],
|
|
270
|
+
{ signal: controller.signal },
|
|
271
|
+
);
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
`validateXmlAsync` returns the same issues as `validateXml`, in the same order, but works in short slices and hands the main thread back between them (`scheduler.yield()` where available, otherwise `setTimeout`).
|
|
275
|
+
|
|
276
|
+
- `signal` — aborting it rejects the promise with the signal's reason, for example when a newer edit makes the run outdated.
|
|
277
|
+
- `timeBudgetMs` — how long to work before yielding. Defaults to 8 ms.
|
|
278
|
+
|
|
279
|
+
Pass a copy of the document if it can change while validation runs.
|
|
280
|
+
|
|
259
281
|
Listing `referenceBibliomixed` checks each bibliography entry against the schema of its reference type instead (see [Reference schemas](#reference-schemas)).
|
|
260
282
|
|
|
261
283
|
## How validation works
|
package/dist/index.d.mts
CHANGED
|
@@ -1002,7 +1002,7 @@ type ValidationError = {
|
|
|
1002
1002
|
|
|
1003
1003
|
/**
|
|
1004
1004
|
* Validates the XML document against the schema.
|
|
1005
|
-
|
|
1005
|
+
|
|
1006
1006
|
* @param xml - The XML document to validate.
|
|
1007
1007
|
* @param elementsToLink - The elements IDs that are linked to.
|
|
1008
1008
|
* @param linkElements - The elements IDs that are linked to.
|
|
@@ -1011,11 +1011,29 @@ type ValidationError = {
|
|
|
1011
1011
|
* @returns The validation errors.
|
|
1012
1012
|
*/
|
|
1013
1013
|
declare const validateXml: (xml: Element, elementsToLink: string[], linkElements: string[], schemasToValidateAgainst: SchemaCode[]) => ValidationError[];
|
|
1014
|
+
type ValidateXmlAsyncOptions = {
|
|
1015
|
+
/** Rejects with the signal's reason once aborted. */
|
|
1016
|
+
signal?: AbortSignal;
|
|
1017
|
+
/** How long to work before handing the main thread back. Defaults to 8 ms. */
|
|
1018
|
+
timeBudgetMs?: number;
|
|
1019
|
+
};
|
|
1020
|
+
/**
|
|
1021
|
+
* Same result as `validateXml`, but works in short slices and hands the main
|
|
1022
|
+
* thread back between them, so large documents do not freeze the page.
|
|
1023
|
+
*
|
|
1024
|
+
* Pass a copy of the document if it can change while validation runs.
|
|
1025
|
+
*/
|
|
1026
|
+
declare const validateXmlAsync: (xml: Element, elementsToLink: string[], linkElements: string[], schemasToValidateAgainst: SchemaCode[], { signal, timeBudgetMs }?: ValidateXmlAsyncOptions) => Promise<ValidationError[]>;
|
|
1027
|
+
|
|
1028
|
+
type LinkIds = readonly string[] | ReadonlySet<string>;
|
|
1014
1029
|
|
|
1015
|
-
declare const findElementLinkedTo: (linkend: string, elementsToLink:
|
|
1030
|
+
declare const findElementLinkedTo: (linkend: string, elementsToLink: LinkIds) => boolean;
|
|
1016
1031
|
declare const LINK_TO_CROSS_CHECK: string[];
|
|
1017
1032
|
declare const LINK_BLOCKER_ROLES: string[];
|
|
1018
|
-
declare const validateLinkend: (linkElement: Element, elementsToLink:
|
|
1033
|
+
declare const validateLinkend: (linkElement: Element, elementsToLink: LinkIds) => ValidationError[];
|
|
1034
|
+
|
|
1035
|
+
/** Work split into steps: each `yield` is a point where a caller may pause. */
|
|
1036
|
+
type Steps<T> = Generator<void, T, void>;
|
|
1019
1037
|
|
|
1020
1038
|
declare const POSSIBLE_WEBLINK_CLASS = "possible-weblink";
|
|
1021
1039
|
declare const POSSIBLE_WEBLINK_EXCLUDE_SELECTORS: string[];
|
|
@@ -1025,6 +1043,7 @@ type PossibleWeblink = {
|
|
|
1025
1043
|
};
|
|
1026
1044
|
declare const getPossibleWeblinks: (root: Element) => Map<string, PossibleWeblink>;
|
|
1027
1045
|
declare const markPossibleWeblinks: (editor: HTMLElement) => Map<string, PossibleWeblink>;
|
|
1046
|
+
declare function validatePossibleWeblinksSteps(root: Element): Steps<ValidationError[]>;
|
|
1028
1047
|
declare const validatePossibleWeblinks: (root: Element) => ValidationError[];
|
|
1029
1048
|
declare const clearWeblinkMatches: (editor: HTMLElement) => void;
|
|
1030
1049
|
|
|
@@ -1038,7 +1057,7 @@ declare const validateFootnoteNumber: (footnoteElement: Element) => ValidationEr
|
|
|
1038
1057
|
declare const validateConsecutiveFootnotes: (root: Element | Document) => ValidationError[];
|
|
1039
1058
|
declare const validateConsecutiveFootnoteCues: (root: Element | Document) => ValidationError[];
|
|
1040
1059
|
|
|
1041
|
-
declare const validateElementToLinkTo: (element: Element, linkElements:
|
|
1060
|
+
declare const validateElementToLinkTo: (element: Element, linkElements: LinkIds) => ValidationError[];
|
|
1042
1061
|
|
|
1043
1062
|
declare const validateElementAgainstSchema: (element: Element, schema: Schema) => ValidationError[];
|
|
1044
1063
|
declare const getEffectiveChildElements: (element: Element) => Element[];
|
|
@@ -1122,4 +1141,4 @@ declare const REFERENCE_PART_SELECTOR: string;
|
|
|
1122
1141
|
declare const getReferenceParts: (reference: Element) => HTMLElement[];
|
|
1123
1142
|
declare const getReferenceFieldElements: (reference: Element) => ReferenceFieldElement[];
|
|
1124
1143
|
|
|
1125
|
-
export { ALIGNMENT_ATTRIBUTE, ATOM_SCHEMAS, type AllowedChildren, type AtomSchemaCode, type AttributeDefinition, type BibliomsetRelation, DEPENDENT_FORBIDDEN_ELEMENTS, ELEMENT_SCHEMAS, ELE_ID_ATTRIBUTE, ElementLabel, type ElementSchemaCode, FIGURE_PLACEMENT_ATTRIBUTE, type FreeAttribute, ID_ATTRS, IGNORED_ATTRIBUTES, IGNORED_ATTRIBUTES_STARTS_WITH, IGNORED_ELEMENT_SELECTORS, INDENT_TYPE_ATTRIBUTE, INLINE_ELEMENT_SCHEMAS, type InlineSchemaCode, LAYOUT_ATTRIBUTES, LAYOUT_CELL_WIDTH_ATTRIBUTE, LAYOUT_TABLE_ORIENTATION_ATTRIBUTE, LAYOUT_TABLE_PLACEMENT_ATTRIBUTE, LAYOUT_USER_ATTRIBUTE, LEFT_INDENT_ATTRIBUTE, LINKEND_ATTRIBUTE, LINK_BLOCKER_ROLES, LINK_TO_CROSS_CHECK, POSSIBLE_WEBLINK_CLASS, POSSIBLE_WEBLINK_EXCLUDE_SELECTORS, REFERENCE_FIELD_SCHEMAS, REFERENCE_PART_SELECTOR, REFERENCE_TYPE_SCHEMAS, RIGHT_INDENT_ATTRIBUTE, type ReferenceElementReplacement, type ReferenceFieldCode, type ReferenceFieldElement, type ReferenceFieldSchema, type ReferenceMarkupIssue, type ReferenceMarkupRule, type ReferenceStructureIssue, type ReferenceTypeCode, type ReferenceTypeSchema, type RequiredReferenceField, type RestrictedAttribute, SCHEMAS, SPACE_ABOVE_ATTRIBUTE, SPACE_BELOW_ATTRIBUTE, SPECIAL_INDENT_ATTRIBUTE, STORE_ATTRIBUTE, STYLE_NAME_ATTRIBUTE, type Schema, type SchemaAttributes, type SchemaCode, type SchemaKind, type SchemasByCode, TRACK_CHANGES_ATTRS, TRACK_CHANGES_ATTR_DATA_DATE, TRACK_CHANGES_ATTR_DATA_TIME, TRACK_CHANGES_ATTR_DATA_USERID, TRACK_CHANGES_ATTR_DATA_USERNAME, VALIDATION_IGNORED_ATTRIBUTE, type ValidationError, type ValidationErrorKind, type ValidationErrorLevel, XMLID_ATTRIBUTE, clearWeblinkMatches, closestElementBySchema, createElement, extractFootnoteNumber, findAttributeDefinitionByName, findElementLinkedTo, findReferenceFieldByElement, findReferenceTypeSchemaByElement, findSchemaByCode, findSchemaByElement, getAdjacentElement, getAttributeName, getEffectiveChildElements, getElementLinks, getPossibleWeblinks, getReferenceFieldElements, getReferenceParts, getReferenceStructureIssueElements, getStore, isAttributeRestricted, isDeletedElement, isIgnoredAttribute, isIgnoredElement, isTrackChangesSchema, markPossibleWeblinks, queryAllElementsBySchema, queryElementBySchema, validateAttributes, validateConsecutiveFootnoteCues, validateConsecutiveFootnotes, validateElementAgainstSchema, validateElementToLinkTo, validateFootnoteNumber, validateHierarchy, validateLinkend, validateOlink, validatePossibleWeblinks, validateReferenceStructure, validateXml };
|
|
1144
|
+
export { ALIGNMENT_ATTRIBUTE, ATOM_SCHEMAS, type AllowedChildren, type AtomSchemaCode, type AttributeDefinition, type BibliomsetRelation, DEPENDENT_FORBIDDEN_ELEMENTS, ELEMENT_SCHEMAS, ELE_ID_ATTRIBUTE, ElementLabel, type ElementSchemaCode, FIGURE_PLACEMENT_ATTRIBUTE, type FreeAttribute, ID_ATTRS, IGNORED_ATTRIBUTES, IGNORED_ATTRIBUTES_STARTS_WITH, IGNORED_ELEMENT_SELECTORS, INDENT_TYPE_ATTRIBUTE, INLINE_ELEMENT_SCHEMAS, type InlineSchemaCode, LAYOUT_ATTRIBUTES, LAYOUT_CELL_WIDTH_ATTRIBUTE, LAYOUT_TABLE_ORIENTATION_ATTRIBUTE, LAYOUT_TABLE_PLACEMENT_ATTRIBUTE, LAYOUT_USER_ATTRIBUTE, LEFT_INDENT_ATTRIBUTE, LINKEND_ATTRIBUTE, LINK_BLOCKER_ROLES, LINK_TO_CROSS_CHECK, POSSIBLE_WEBLINK_CLASS, POSSIBLE_WEBLINK_EXCLUDE_SELECTORS, REFERENCE_FIELD_SCHEMAS, REFERENCE_PART_SELECTOR, REFERENCE_TYPE_SCHEMAS, RIGHT_INDENT_ATTRIBUTE, type ReferenceElementReplacement, type ReferenceFieldCode, type ReferenceFieldElement, type ReferenceFieldSchema, type ReferenceMarkupIssue, type ReferenceMarkupRule, type ReferenceStructureIssue, type ReferenceTypeCode, type ReferenceTypeSchema, type RequiredReferenceField, type RestrictedAttribute, SCHEMAS, SPACE_ABOVE_ATTRIBUTE, SPACE_BELOW_ATTRIBUTE, SPECIAL_INDENT_ATTRIBUTE, STORE_ATTRIBUTE, STYLE_NAME_ATTRIBUTE, type Schema, type SchemaAttributes, type SchemaCode, type SchemaKind, type SchemasByCode, TRACK_CHANGES_ATTRS, TRACK_CHANGES_ATTR_DATA_DATE, TRACK_CHANGES_ATTR_DATA_TIME, TRACK_CHANGES_ATTR_DATA_USERID, TRACK_CHANGES_ATTR_DATA_USERNAME, VALIDATION_IGNORED_ATTRIBUTE, type ValidateXmlAsyncOptions, type ValidationError, type ValidationErrorKind, type ValidationErrorLevel, XMLID_ATTRIBUTE, clearWeblinkMatches, closestElementBySchema, createElement, extractFootnoteNumber, findAttributeDefinitionByName, findElementLinkedTo, findReferenceFieldByElement, findReferenceTypeSchemaByElement, findSchemaByCode, findSchemaByElement, getAdjacentElement, getAttributeName, getEffectiveChildElements, getElementLinks, getPossibleWeblinks, getReferenceFieldElements, getReferenceParts, getReferenceStructureIssueElements, getStore, isAttributeRestricted, isDeletedElement, isIgnoredAttribute, isIgnoredElement, isTrackChangesSchema, markPossibleWeblinks, queryAllElementsBySchema, queryElementBySchema, validateAttributes, validateConsecutiveFootnoteCues, validateConsecutiveFootnotes, validateElementAgainstSchema, validateElementToLinkTo, validateFootnoteNumber, validateHierarchy, validateLinkend, validateOlink, validatePossibleWeblinks, validatePossibleWeblinksSteps, validateReferenceStructure, validateXml, validateXmlAsync };
|
package/dist/index.d.ts
CHANGED
|
@@ -1002,7 +1002,7 @@ type ValidationError = {
|
|
|
1002
1002
|
|
|
1003
1003
|
/**
|
|
1004
1004
|
* Validates the XML document against the schema.
|
|
1005
|
-
|
|
1005
|
+
|
|
1006
1006
|
* @param xml - The XML document to validate.
|
|
1007
1007
|
* @param elementsToLink - The elements IDs that are linked to.
|
|
1008
1008
|
* @param linkElements - The elements IDs that are linked to.
|
|
@@ -1011,11 +1011,29 @@ type ValidationError = {
|
|
|
1011
1011
|
* @returns The validation errors.
|
|
1012
1012
|
*/
|
|
1013
1013
|
declare const validateXml: (xml: Element, elementsToLink: string[], linkElements: string[], schemasToValidateAgainst: SchemaCode[]) => ValidationError[];
|
|
1014
|
+
type ValidateXmlAsyncOptions = {
|
|
1015
|
+
/** Rejects with the signal's reason once aborted. */
|
|
1016
|
+
signal?: AbortSignal;
|
|
1017
|
+
/** How long to work before handing the main thread back. Defaults to 8 ms. */
|
|
1018
|
+
timeBudgetMs?: number;
|
|
1019
|
+
};
|
|
1020
|
+
/**
|
|
1021
|
+
* Same result as `validateXml`, but works in short slices and hands the main
|
|
1022
|
+
* thread back between them, so large documents do not freeze the page.
|
|
1023
|
+
*
|
|
1024
|
+
* Pass a copy of the document if it can change while validation runs.
|
|
1025
|
+
*/
|
|
1026
|
+
declare const validateXmlAsync: (xml: Element, elementsToLink: string[], linkElements: string[], schemasToValidateAgainst: SchemaCode[], { signal, timeBudgetMs }?: ValidateXmlAsyncOptions) => Promise<ValidationError[]>;
|
|
1027
|
+
|
|
1028
|
+
type LinkIds = readonly string[] | ReadonlySet<string>;
|
|
1014
1029
|
|
|
1015
|
-
declare const findElementLinkedTo: (linkend: string, elementsToLink:
|
|
1030
|
+
declare const findElementLinkedTo: (linkend: string, elementsToLink: LinkIds) => boolean;
|
|
1016
1031
|
declare const LINK_TO_CROSS_CHECK: string[];
|
|
1017
1032
|
declare const LINK_BLOCKER_ROLES: string[];
|
|
1018
|
-
declare const validateLinkend: (linkElement: Element, elementsToLink:
|
|
1033
|
+
declare const validateLinkend: (linkElement: Element, elementsToLink: LinkIds) => ValidationError[];
|
|
1034
|
+
|
|
1035
|
+
/** Work split into steps: each `yield` is a point where a caller may pause. */
|
|
1036
|
+
type Steps<T> = Generator<void, T, void>;
|
|
1019
1037
|
|
|
1020
1038
|
declare const POSSIBLE_WEBLINK_CLASS = "possible-weblink";
|
|
1021
1039
|
declare const POSSIBLE_WEBLINK_EXCLUDE_SELECTORS: string[];
|
|
@@ -1025,6 +1043,7 @@ type PossibleWeblink = {
|
|
|
1025
1043
|
};
|
|
1026
1044
|
declare const getPossibleWeblinks: (root: Element) => Map<string, PossibleWeblink>;
|
|
1027
1045
|
declare const markPossibleWeblinks: (editor: HTMLElement) => Map<string, PossibleWeblink>;
|
|
1046
|
+
declare function validatePossibleWeblinksSteps(root: Element): Steps<ValidationError[]>;
|
|
1028
1047
|
declare const validatePossibleWeblinks: (root: Element) => ValidationError[];
|
|
1029
1048
|
declare const clearWeblinkMatches: (editor: HTMLElement) => void;
|
|
1030
1049
|
|
|
@@ -1038,7 +1057,7 @@ declare const validateFootnoteNumber: (footnoteElement: Element) => ValidationEr
|
|
|
1038
1057
|
declare const validateConsecutiveFootnotes: (root: Element | Document) => ValidationError[];
|
|
1039
1058
|
declare const validateConsecutiveFootnoteCues: (root: Element | Document) => ValidationError[];
|
|
1040
1059
|
|
|
1041
|
-
declare const validateElementToLinkTo: (element: Element, linkElements:
|
|
1060
|
+
declare const validateElementToLinkTo: (element: Element, linkElements: LinkIds) => ValidationError[];
|
|
1042
1061
|
|
|
1043
1062
|
declare const validateElementAgainstSchema: (element: Element, schema: Schema) => ValidationError[];
|
|
1044
1063
|
declare const getEffectiveChildElements: (element: Element) => Element[];
|
|
@@ -1122,4 +1141,4 @@ declare const REFERENCE_PART_SELECTOR: string;
|
|
|
1122
1141
|
declare const getReferenceParts: (reference: Element) => HTMLElement[];
|
|
1123
1142
|
declare const getReferenceFieldElements: (reference: Element) => ReferenceFieldElement[];
|
|
1124
1143
|
|
|
1125
|
-
export { ALIGNMENT_ATTRIBUTE, ATOM_SCHEMAS, type AllowedChildren, type AtomSchemaCode, type AttributeDefinition, type BibliomsetRelation, DEPENDENT_FORBIDDEN_ELEMENTS, ELEMENT_SCHEMAS, ELE_ID_ATTRIBUTE, ElementLabel, type ElementSchemaCode, FIGURE_PLACEMENT_ATTRIBUTE, type FreeAttribute, ID_ATTRS, IGNORED_ATTRIBUTES, IGNORED_ATTRIBUTES_STARTS_WITH, IGNORED_ELEMENT_SELECTORS, INDENT_TYPE_ATTRIBUTE, INLINE_ELEMENT_SCHEMAS, type InlineSchemaCode, LAYOUT_ATTRIBUTES, LAYOUT_CELL_WIDTH_ATTRIBUTE, LAYOUT_TABLE_ORIENTATION_ATTRIBUTE, LAYOUT_TABLE_PLACEMENT_ATTRIBUTE, LAYOUT_USER_ATTRIBUTE, LEFT_INDENT_ATTRIBUTE, LINKEND_ATTRIBUTE, LINK_BLOCKER_ROLES, LINK_TO_CROSS_CHECK, POSSIBLE_WEBLINK_CLASS, POSSIBLE_WEBLINK_EXCLUDE_SELECTORS, REFERENCE_FIELD_SCHEMAS, REFERENCE_PART_SELECTOR, REFERENCE_TYPE_SCHEMAS, RIGHT_INDENT_ATTRIBUTE, type ReferenceElementReplacement, type ReferenceFieldCode, type ReferenceFieldElement, type ReferenceFieldSchema, type ReferenceMarkupIssue, type ReferenceMarkupRule, type ReferenceStructureIssue, type ReferenceTypeCode, type ReferenceTypeSchema, type RequiredReferenceField, type RestrictedAttribute, SCHEMAS, SPACE_ABOVE_ATTRIBUTE, SPACE_BELOW_ATTRIBUTE, SPECIAL_INDENT_ATTRIBUTE, STORE_ATTRIBUTE, STYLE_NAME_ATTRIBUTE, type Schema, type SchemaAttributes, type SchemaCode, type SchemaKind, type SchemasByCode, TRACK_CHANGES_ATTRS, TRACK_CHANGES_ATTR_DATA_DATE, TRACK_CHANGES_ATTR_DATA_TIME, TRACK_CHANGES_ATTR_DATA_USERID, TRACK_CHANGES_ATTR_DATA_USERNAME, VALIDATION_IGNORED_ATTRIBUTE, type ValidationError, type ValidationErrorKind, type ValidationErrorLevel, XMLID_ATTRIBUTE, clearWeblinkMatches, closestElementBySchema, createElement, extractFootnoteNumber, findAttributeDefinitionByName, findElementLinkedTo, findReferenceFieldByElement, findReferenceTypeSchemaByElement, findSchemaByCode, findSchemaByElement, getAdjacentElement, getAttributeName, getEffectiveChildElements, getElementLinks, getPossibleWeblinks, getReferenceFieldElements, getReferenceParts, getReferenceStructureIssueElements, getStore, isAttributeRestricted, isDeletedElement, isIgnoredAttribute, isIgnoredElement, isTrackChangesSchema, markPossibleWeblinks, queryAllElementsBySchema, queryElementBySchema, validateAttributes, validateConsecutiveFootnoteCues, validateConsecutiveFootnotes, validateElementAgainstSchema, validateElementToLinkTo, validateFootnoteNumber, validateHierarchy, validateLinkend, validateOlink, validatePossibleWeblinks, validateReferenceStructure, validateXml };
|
|
1144
|
+
export { ALIGNMENT_ATTRIBUTE, ATOM_SCHEMAS, type AllowedChildren, type AtomSchemaCode, type AttributeDefinition, type BibliomsetRelation, DEPENDENT_FORBIDDEN_ELEMENTS, ELEMENT_SCHEMAS, ELE_ID_ATTRIBUTE, ElementLabel, type ElementSchemaCode, FIGURE_PLACEMENT_ATTRIBUTE, type FreeAttribute, ID_ATTRS, IGNORED_ATTRIBUTES, IGNORED_ATTRIBUTES_STARTS_WITH, IGNORED_ELEMENT_SELECTORS, INDENT_TYPE_ATTRIBUTE, INLINE_ELEMENT_SCHEMAS, type InlineSchemaCode, LAYOUT_ATTRIBUTES, LAYOUT_CELL_WIDTH_ATTRIBUTE, LAYOUT_TABLE_ORIENTATION_ATTRIBUTE, LAYOUT_TABLE_PLACEMENT_ATTRIBUTE, LAYOUT_USER_ATTRIBUTE, LEFT_INDENT_ATTRIBUTE, LINKEND_ATTRIBUTE, LINK_BLOCKER_ROLES, LINK_TO_CROSS_CHECK, POSSIBLE_WEBLINK_CLASS, POSSIBLE_WEBLINK_EXCLUDE_SELECTORS, REFERENCE_FIELD_SCHEMAS, REFERENCE_PART_SELECTOR, REFERENCE_TYPE_SCHEMAS, RIGHT_INDENT_ATTRIBUTE, type ReferenceElementReplacement, type ReferenceFieldCode, type ReferenceFieldElement, type ReferenceFieldSchema, type ReferenceMarkupIssue, type ReferenceMarkupRule, type ReferenceStructureIssue, type ReferenceTypeCode, type ReferenceTypeSchema, type RequiredReferenceField, type RestrictedAttribute, SCHEMAS, SPACE_ABOVE_ATTRIBUTE, SPACE_BELOW_ATTRIBUTE, SPECIAL_INDENT_ATTRIBUTE, STORE_ATTRIBUTE, STYLE_NAME_ATTRIBUTE, type Schema, type SchemaAttributes, type SchemaCode, type SchemaKind, type SchemasByCode, TRACK_CHANGES_ATTRS, TRACK_CHANGES_ATTR_DATA_DATE, TRACK_CHANGES_ATTR_DATA_TIME, TRACK_CHANGES_ATTR_DATA_USERID, TRACK_CHANGES_ATTR_DATA_USERNAME, VALIDATION_IGNORED_ATTRIBUTE, type ValidateXmlAsyncOptions, type ValidationError, type ValidationErrorKind, type ValidationErrorLevel, XMLID_ATTRIBUTE, clearWeblinkMatches, closestElementBySchema, createElement, extractFootnoteNumber, findAttributeDefinitionByName, findElementLinkedTo, findReferenceFieldByElement, findReferenceTypeSchemaByElement, findSchemaByCode, findSchemaByElement, getAdjacentElement, getAttributeName, getEffectiveChildElements, getElementLinks, getPossibleWeblinks, getReferenceFieldElements, getReferenceParts, getReferenceStructureIssueElements, getStore, isAttributeRestricted, isDeletedElement, isIgnoredAttribute, isIgnoredElement, isTrackChangesSchema, markPossibleWeblinks, queryAllElementsBySchema, queryElementBySchema, validateAttributes, validateConsecutiveFootnoteCues, validateConsecutiveFootnotes, validateElementAgainstSchema, validateElementToLinkTo, validateFootnoteNumber, validateHierarchy, validateLinkend, validateOlink, validatePossibleWeblinks, validatePossibleWeblinksSteps, validateReferenceStructure, validateXml, validateXmlAsync };
|
package/dist/index.js
CHANGED
|
@@ -108,8 +108,10 @@ __export(index_exports, {
|
|
|
108
108
|
validateLinkend: () => validateLinkend,
|
|
109
109
|
validateOlink: () => validateOlink,
|
|
110
110
|
validatePossibleWeblinks: () => validatePossibleWeblinks,
|
|
111
|
+
validatePossibleWeblinksSteps: () => validatePossibleWeblinksSteps,
|
|
111
112
|
validateReferenceStructure: () => validateReferenceStructure,
|
|
112
|
-
validateXml: () => validateXml
|
|
113
|
+
validateXml: () => validateXml,
|
|
114
|
+
validateXmlAsync: () => validateXmlAsync
|
|
113
115
|
});
|
|
114
116
|
module.exports = __toCommonJS(index_exports);
|
|
115
117
|
|
|
@@ -2845,12 +2847,19 @@ var findAttributeDefinitionByName = (definitions, name) => {
|
|
|
2845
2847
|
var findSchemaByCode = (code) => SCHEMAS[code];
|
|
2846
2848
|
|
|
2847
2849
|
// src/schema/helpers/findSchemaByElement.ts
|
|
2848
|
-
var
|
|
2849
|
-
|
|
2850
|
-
|
|
2851
|
-
);
|
|
2852
|
-
|
|
2850
|
+
var schemasByTag;
|
|
2851
|
+
var getSchemasByTag = () => {
|
|
2852
|
+
if (schemasByTag) return schemasByTag;
|
|
2853
|
+
schemasByTag = /* @__PURE__ */ new Map();
|
|
2854
|
+
for (const schema of Object.values(SCHEMAS)) {
|
|
2855
|
+
const tag = schema.tag.toUpperCase();
|
|
2856
|
+
const schemas = schemasByTag.get(tag);
|
|
2857
|
+
if (schemas) schemas.push(schema);
|
|
2858
|
+
else schemasByTag.set(tag, [schema]);
|
|
2859
|
+
}
|
|
2860
|
+
return schemasByTag;
|
|
2853
2861
|
};
|
|
2862
|
+
var findSchemaByElement = (element) => getSchemasByTag().get(element.tagName.toUpperCase())?.find((schema) => !schema.matchesElement || schema.matchesElement(element));
|
|
2854
2863
|
|
|
2855
2864
|
// src/schema/helpers/isAttributeRestricted.ts
|
|
2856
2865
|
var isAttributeRestricted = (attr) => typeof attr !== "string";
|
|
@@ -3394,7 +3403,8 @@ var IGNORED_ELEMENT_SELECTORS = [
|
|
|
3394
3403
|
"span.ref-drag",
|
|
3395
3404
|
"span#dummySpan"
|
|
3396
3405
|
];
|
|
3397
|
-
var
|
|
3406
|
+
var IGNORED_ELEMENT_SELECTOR = IGNORED_ELEMENT_SELECTORS.join(", ");
|
|
3407
|
+
var isIgnoredElement = (element) => element.tagName.toUpperCase() === "SPAN" && element.matches(IGNORED_ELEMENT_SELECTOR);
|
|
3398
3408
|
|
|
3399
3409
|
// src/validation/helpers/isIgnoredValidation.ts
|
|
3400
3410
|
var IGNORED_VALIDATION_ELEMENT_SELECTORS = [
|
|
@@ -3553,10 +3563,11 @@ var validateConsecutiveFootnoteCues = (root) => {
|
|
|
3553
3563
|
return errors;
|
|
3554
3564
|
};
|
|
3555
3565
|
|
|
3566
|
+
// src/validation/helpers/hasLinkId.ts
|
|
3567
|
+
var hasLinkId = (ids, id) => "has" in ids ? ids.has(id) : ids.includes(id);
|
|
3568
|
+
|
|
3556
3569
|
// src/validation/validateLinkend.ts
|
|
3557
|
-
var findElementLinkedTo = (linkend, elementsToLink) =>
|
|
3558
|
-
return elementsToLink.includes(linkend);
|
|
3559
|
-
};
|
|
3570
|
+
var findElementLinkedTo = (linkend, elementsToLink) => hasLinkId(elementsToLink, linkend);
|
|
3560
3571
|
var LINK_TO_CROSS_CHECK = [
|
|
3561
3572
|
TABLE_LINK_ROLE,
|
|
3562
3573
|
FIGURE_LINK_ROLE,
|
|
@@ -3777,9 +3788,7 @@ var getExtraInstruction = (schema, childSchema) => {
|
|
|
3777
3788
|
};
|
|
3778
3789
|
|
|
3779
3790
|
// src/validation/validateElementToLinkTo.ts
|
|
3780
|
-
var findElementLinkedTo2 = (xmlid, linkElements) =>
|
|
3781
|
-
return linkElements.includes(xmlid);
|
|
3782
|
-
};
|
|
3791
|
+
var findElementLinkedTo2 = (xmlid, linkElements) => hasLinkId(linkElements, xmlid);
|
|
3783
3792
|
var isFootnote = (element) => {
|
|
3784
3793
|
return matchesSchemaTag(element, FOOTNOTE_SCHEMA.tag);
|
|
3785
3794
|
};
|
|
@@ -3849,6 +3858,16 @@ var validateElementToLinkTo = (element, linkElements) => {
|
|
|
3849
3858
|
|
|
3850
3859
|
// src/validation/validateWeblink.ts
|
|
3851
3860
|
var import_mark2 = __toESM(require("mark.js"));
|
|
3861
|
+
|
|
3862
|
+
// src/validation/helpers/steps.ts
|
|
3863
|
+
var runSteps = (steps) => {
|
|
3864
|
+
for (; ; ) {
|
|
3865
|
+
const step = steps.next();
|
|
3866
|
+
if (step.done) return step.value;
|
|
3867
|
+
}
|
|
3868
|
+
};
|
|
3869
|
+
|
|
3870
|
+
// src/validation/validateWeblink.ts
|
|
3852
3871
|
var EDGE_PUNCTUATION = `:;.,\\-\u2013\u2014\u2012_(){}[\\]!'"+=\xAB\xBB\u2039\u203A\u201C\u201D\u2018\u2019<>`;
|
|
3853
3872
|
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}])?)?`;
|
|
3854
3873
|
var WEB_URI_IN_TEXT_REGEX = new RegExp(WEB_URI_PATTERN, "gi");
|
|
@@ -3929,11 +3948,62 @@ var markPossibleWeblinks = (editor) => {
|
|
|
3929
3948
|
});
|
|
3930
3949
|
return possibleWeblinks;
|
|
3931
3950
|
};
|
|
3932
|
-
var
|
|
3951
|
+
var TEXT_NODES_PER_STEP = 256;
|
|
3952
|
+
var MARK_EXCLUDED_PARENT_SELECTOR = [
|
|
3953
|
+
...POSSIBLE_WEBLINK_EXCLUDE_SELECTORS,
|
|
3954
|
+
"script",
|
|
3955
|
+
"style",
|
|
3956
|
+
"title",
|
|
3957
|
+
"head",
|
|
3958
|
+
"html"
|
|
3959
|
+
].join(", ");
|
|
3960
|
+
var createWeblinkMatchElement = (ownerDocument, text, storeId) => {
|
|
3961
|
+
const element = ownerDocument.createElement("mark");
|
|
3962
|
+
element.setAttribute("data-markjs", "true");
|
|
3963
|
+
element.setAttribute("class", POSSIBLE_WEBLINK_CLASS);
|
|
3964
|
+
element.setAttribute(STORE_ATTRIBUTE, storeId);
|
|
3965
|
+
element.textContent = text;
|
|
3966
|
+
return element;
|
|
3967
|
+
};
|
|
3968
|
+
function* findPossibleWeblinks(root) {
|
|
3969
|
+
const possibleWeblinks = /* @__PURE__ */ new Map();
|
|
3970
|
+
const ownerDocument = root.ownerDocument;
|
|
3971
|
+
const walker = ownerDocument.createTreeWalker(root, NodeFilter.SHOW_TEXT);
|
|
3972
|
+
const regex = new RegExp(WEB_URI_PATTERN, "gi");
|
|
3973
|
+
let nodesSinceStep = 0;
|
|
3974
|
+
for (let node = walker.nextNode(); node; node = walker.nextNode()) {
|
|
3975
|
+
if (++nodesSinceStep === TEXT_NODES_PER_STEP) {
|
|
3976
|
+
nodesSinceStep = 0;
|
|
3977
|
+
yield;
|
|
3978
|
+
}
|
|
3979
|
+
const text = node.textContent ?? "";
|
|
3980
|
+
if (!text) continue;
|
|
3981
|
+
const parent = node.parentNode;
|
|
3982
|
+
if (parent instanceof Element && parent.matches(MARK_EXCLUDED_PARENT_SELECTOR)) {
|
|
3983
|
+
continue;
|
|
3984
|
+
}
|
|
3985
|
+
regex.lastIndex = 0;
|
|
3986
|
+
for (let match = regex.exec(text); match; match = regex.exec(text)) {
|
|
3987
|
+
const storeId = getWeblinkMatchId(possibleWeblinks.size);
|
|
3988
|
+
possibleWeblinks.set(storeId, {
|
|
3989
|
+
weblink: match[0],
|
|
3990
|
+
elements: [createWeblinkMatchElement(ownerDocument, match[0], storeId)]
|
|
3991
|
+
});
|
|
3992
|
+
}
|
|
3993
|
+
}
|
|
3994
|
+
return possibleWeblinks;
|
|
3995
|
+
}
|
|
3996
|
+
var hasWeblinkMatches = (root) => root.getElementsByClassName(POSSIBLE_WEBLINK_CLASS).length > 0;
|
|
3997
|
+
function* validatePossibleWeblinksSteps(root) {
|
|
3933
3998
|
const issues = [];
|
|
3934
|
-
|
|
3935
|
-
|
|
3936
|
-
|
|
3999
|
+
let possibleWeblinks;
|
|
4000
|
+
if (hasWeblinkMatches(root)) {
|
|
4001
|
+
const cloneRoot = root.cloneNode(true);
|
|
4002
|
+
clearWeblinkMatches(cloneRoot);
|
|
4003
|
+
possibleWeblinks = markPossibleWeblinks(cloneRoot);
|
|
4004
|
+
} else {
|
|
4005
|
+
possibleWeblinks = yield* findPossibleWeblinks(root);
|
|
4006
|
+
}
|
|
3937
4007
|
for (const [storeId, { elements }] of Array.from(possibleWeblinks)) {
|
|
3938
4008
|
issues.push(
|
|
3939
4009
|
createValidationIssue(null, {
|
|
@@ -3947,7 +4017,8 @@ var validatePossibleWeblinks = (root) => {
|
|
|
3947
4017
|
);
|
|
3948
4018
|
}
|
|
3949
4019
|
return issues;
|
|
3950
|
-
}
|
|
4020
|
+
}
|
|
4021
|
+
var validatePossibleWeblinks = (root) => runSteps(validatePossibleWeblinksSteps(root));
|
|
3951
4022
|
var clearWeblinkMatches = (editor) => {
|
|
3952
4023
|
const instance = new import_mark2.default(editor);
|
|
3953
4024
|
instance.unmark({
|
|
@@ -4404,66 +4475,106 @@ var validateReference = (reference) => {
|
|
|
4404
4475
|
};
|
|
4405
4476
|
|
|
4406
4477
|
// src/validation/validateXml.ts
|
|
4407
|
-
var
|
|
4478
|
+
var ELEMENTS_PER_STEP = 64;
|
|
4479
|
+
var DEFAULT_TIME_BUDGET_MS = 8;
|
|
4480
|
+
var validateOwnElement = (element, {
|
|
4481
|
+
elementsToLink,
|
|
4482
|
+
linkElements,
|
|
4483
|
+
schemasToValidateAgainst,
|
|
4484
|
+
errors
|
|
4485
|
+
}) => {
|
|
4408
4486
|
if (isIgnoredElement(element)) {
|
|
4409
|
-
return
|
|
4487
|
+
return false;
|
|
4410
4488
|
}
|
|
4411
|
-
const errors = [];
|
|
4412
4489
|
const schema = findSchemaByElement(element);
|
|
4413
|
-
if (schema) {
|
|
4414
|
-
|
|
4415
|
-
errors.push(
|
|
4416
|
-
...schema.code === BIBLIOMIXED_SCHEMA.code ? validateReference(element) : validateElementAgainstSchema(element, schema)
|
|
4417
|
-
);
|
|
4418
|
-
}
|
|
4419
|
-
if (schema.tag === FOOTNOTE_SCHEMA.tag) {
|
|
4420
|
-
errors.push(...validateFootnoteNumber(element));
|
|
4421
|
-
}
|
|
4422
|
-
if (schema.code === HEADING_SCHEMA.code) {
|
|
4423
|
-
errors.push(...validateHierarchy(element, "heading"));
|
|
4424
|
-
}
|
|
4425
|
-
if (schema.code === BOX_SCHEMA.code) {
|
|
4426
|
-
errors.push(...validateHierarchy(element, "box"));
|
|
4427
|
-
}
|
|
4428
|
-
if (schema.code === OLINK_SCHEMA.code) {
|
|
4429
|
-
errors.push(...validateOlink(element));
|
|
4430
|
-
}
|
|
4431
|
-
errors.push(...validateLinkend(element, elementsToLink));
|
|
4432
|
-
errors.push(...validateElementToLinkTo(element, linkElements));
|
|
4433
|
-
if (isIgnoredValidation(schema.code)) {
|
|
4434
|
-
return errors;
|
|
4435
|
-
}
|
|
4490
|
+
if (!schema) {
|
|
4491
|
+
return true;
|
|
4436
4492
|
}
|
|
4437
|
-
|
|
4493
|
+
if (schemasToValidateAgainst.includes(schema.code)) {
|
|
4438
4494
|
errors.push(
|
|
4439
|
-
...
|
|
4440
|
-
child,
|
|
4441
|
-
root,
|
|
4442
|
-
elementsToLink,
|
|
4443
|
-
linkElements,
|
|
4444
|
-
schemasToValidateAgainst
|
|
4445
|
-
)
|
|
4495
|
+
...schema.code === BIBLIOMIXED_SCHEMA.code ? validateReference(element) : validateElementAgainstSchema(element, schema)
|
|
4446
4496
|
);
|
|
4447
4497
|
}
|
|
4448
|
-
|
|
4498
|
+
if (schema.tag === FOOTNOTE_SCHEMA.tag) {
|
|
4499
|
+
errors.push(...validateFootnoteNumber(element));
|
|
4500
|
+
}
|
|
4501
|
+
if (schema.code === HEADING_SCHEMA.code) {
|
|
4502
|
+
errors.push(...validateHierarchy(element, "heading"));
|
|
4503
|
+
}
|
|
4504
|
+
if (schema.code === BOX_SCHEMA.code) {
|
|
4505
|
+
errors.push(...validateHierarchy(element, "box"));
|
|
4506
|
+
}
|
|
4507
|
+
if (schema.code === OLINK_SCHEMA.code) {
|
|
4508
|
+
errors.push(...validateOlink(element));
|
|
4509
|
+
}
|
|
4510
|
+
errors.push(...validateLinkend(element, elementsToLink));
|
|
4511
|
+
errors.push(...validateElementToLinkTo(element, linkElements));
|
|
4512
|
+
return !isIgnoredValidation(schema.code);
|
|
4449
4513
|
};
|
|
4450
|
-
|
|
4514
|
+
function* validateElements(xml, context) {
|
|
4515
|
+
const pending = Array.from(xml.children).reverse();
|
|
4516
|
+
let elementsSinceStep = 0;
|
|
4517
|
+
for (let element = pending.pop(); element; element = pending.pop()) {
|
|
4518
|
+
if (validateOwnElement(element, context)) {
|
|
4519
|
+
const { children } = element;
|
|
4520
|
+
for (let index = children.length - 1; index >= 0; index -= 1) {
|
|
4521
|
+
pending.push(children[index]);
|
|
4522
|
+
}
|
|
4523
|
+
}
|
|
4524
|
+
if (++elementsSinceStep === ELEMENTS_PER_STEP) {
|
|
4525
|
+
elementsSinceStep = 0;
|
|
4526
|
+
yield;
|
|
4527
|
+
}
|
|
4528
|
+
}
|
|
4529
|
+
}
|
|
4530
|
+
function* validateXmlSteps(xml, elementsToLink, linkElements, schemasToValidateAgainst) {
|
|
4451
4531
|
const errors = [];
|
|
4452
4532
|
errors.push(...validateConsecutiveFootnotes(xml));
|
|
4453
4533
|
errors.push(...validateConsecutiveFootnoteCues(xml));
|
|
4454
|
-
|
|
4455
|
-
|
|
4456
|
-
|
|
4457
|
-
|
|
4458
|
-
|
|
4459
|
-
|
|
4460
|
-
|
|
4461
|
-
|
|
4462
|
-
schemasToValidateAgainst
|
|
4463
|
-
)
|
|
4464
|
-
);
|
|
4465
|
-
}
|
|
4534
|
+
yield;
|
|
4535
|
+
errors.push(...yield* validatePossibleWeblinksSteps(xml));
|
|
4536
|
+
yield* validateElements(xml, {
|
|
4537
|
+
elementsToLink: new Set(elementsToLink),
|
|
4538
|
+
linkElements: new Set(linkElements),
|
|
4539
|
+
schemasToValidateAgainst,
|
|
4540
|
+
errors
|
|
4541
|
+
});
|
|
4466
4542
|
return errors;
|
|
4543
|
+
}
|
|
4544
|
+
var validateXml = (xml, elementsToLink, linkElements, schemasToValidateAgainst) => runSteps(
|
|
4545
|
+
validateXmlSteps(
|
|
4546
|
+
xml,
|
|
4547
|
+
elementsToLink,
|
|
4548
|
+
linkElements,
|
|
4549
|
+
schemasToValidateAgainst
|
|
4550
|
+
)
|
|
4551
|
+
);
|
|
4552
|
+
var yieldToMainThread = () => {
|
|
4553
|
+
const scheduler = globalThis.scheduler;
|
|
4554
|
+
if (scheduler?.yield) return scheduler.yield();
|
|
4555
|
+
return new Promise((resolve) => setTimeout(resolve, 0));
|
|
4556
|
+
};
|
|
4557
|
+
var throwIfAborted = (signal) => {
|
|
4558
|
+
if (!signal?.aborted) return;
|
|
4559
|
+
throw signal.reason ?? new DOMException("Aborted", "AbortError");
|
|
4560
|
+
};
|
|
4561
|
+
var validateXmlAsync = async (xml, elementsToLink, linkElements, schemasToValidateAgainst, { signal, timeBudgetMs = DEFAULT_TIME_BUDGET_MS } = {}) => {
|
|
4562
|
+
const steps = validateXmlSteps(
|
|
4563
|
+
xml,
|
|
4564
|
+
elementsToLink,
|
|
4565
|
+
linkElements,
|
|
4566
|
+
schemasToValidateAgainst
|
|
4567
|
+
);
|
|
4568
|
+
let sliceStart = performance.now();
|
|
4569
|
+
for (; ; ) {
|
|
4570
|
+
throwIfAborted(signal);
|
|
4571
|
+
const step = steps.next();
|
|
4572
|
+
if (step.done) return step.value;
|
|
4573
|
+
if (performance.now() - sliceStart >= timeBudgetMs) {
|
|
4574
|
+
await yieldToMainThread();
|
|
4575
|
+
sliceStart = performance.now();
|
|
4576
|
+
}
|
|
4577
|
+
}
|
|
4467
4578
|
};
|
|
4468
4579
|
|
|
4469
4580
|
// src/helpers/getElementLinks.ts
|
|
@@ -4623,6 +4734,8 @@ var getAdjacentElement = ({
|
|
|
4623
4734
|
validateLinkend,
|
|
4624
4735
|
validateOlink,
|
|
4625
4736
|
validatePossibleWeblinks,
|
|
4737
|
+
validatePossibleWeblinksSteps,
|
|
4626
4738
|
validateReferenceStructure,
|
|
4627
|
-
validateXml
|
|
4739
|
+
validateXml,
|
|
4740
|
+
validateXmlAsync
|
|
4628
4741
|
});
|
package/dist/index.mjs
CHANGED
|
@@ -2730,12 +2730,19 @@ var findAttributeDefinitionByName = (definitions, name) => {
|
|
|
2730
2730
|
var findSchemaByCode = (code) => SCHEMAS[code];
|
|
2731
2731
|
|
|
2732
2732
|
// src/schema/helpers/findSchemaByElement.ts
|
|
2733
|
-
var
|
|
2734
|
-
|
|
2735
|
-
|
|
2736
|
-
);
|
|
2737
|
-
|
|
2733
|
+
var schemasByTag;
|
|
2734
|
+
var getSchemasByTag = () => {
|
|
2735
|
+
if (schemasByTag) return schemasByTag;
|
|
2736
|
+
schemasByTag = /* @__PURE__ */ new Map();
|
|
2737
|
+
for (const schema of Object.values(SCHEMAS)) {
|
|
2738
|
+
const tag = schema.tag.toUpperCase();
|
|
2739
|
+
const schemas = schemasByTag.get(tag);
|
|
2740
|
+
if (schemas) schemas.push(schema);
|
|
2741
|
+
else schemasByTag.set(tag, [schema]);
|
|
2742
|
+
}
|
|
2743
|
+
return schemasByTag;
|
|
2738
2744
|
};
|
|
2745
|
+
var findSchemaByElement = (element) => getSchemasByTag().get(element.tagName.toUpperCase())?.find((schema) => !schema.matchesElement || schema.matchesElement(element));
|
|
2739
2746
|
|
|
2740
2747
|
// src/schema/helpers/isAttributeRestricted.ts
|
|
2741
2748
|
var isAttributeRestricted = (attr) => typeof attr !== "string";
|
|
@@ -3279,7 +3286,8 @@ var IGNORED_ELEMENT_SELECTORS = [
|
|
|
3279
3286
|
"span.ref-drag",
|
|
3280
3287
|
"span#dummySpan"
|
|
3281
3288
|
];
|
|
3282
|
-
var
|
|
3289
|
+
var IGNORED_ELEMENT_SELECTOR = IGNORED_ELEMENT_SELECTORS.join(", ");
|
|
3290
|
+
var isIgnoredElement = (element) => element.tagName.toUpperCase() === "SPAN" && element.matches(IGNORED_ELEMENT_SELECTOR);
|
|
3283
3291
|
|
|
3284
3292
|
// src/validation/helpers/isIgnoredValidation.ts
|
|
3285
3293
|
var IGNORED_VALIDATION_ELEMENT_SELECTORS = [
|
|
@@ -3438,10 +3446,11 @@ var validateConsecutiveFootnoteCues = (root) => {
|
|
|
3438
3446
|
return errors;
|
|
3439
3447
|
};
|
|
3440
3448
|
|
|
3449
|
+
// src/validation/helpers/hasLinkId.ts
|
|
3450
|
+
var hasLinkId = (ids, id) => "has" in ids ? ids.has(id) : ids.includes(id);
|
|
3451
|
+
|
|
3441
3452
|
// src/validation/validateLinkend.ts
|
|
3442
|
-
var findElementLinkedTo = (linkend, elementsToLink) =>
|
|
3443
|
-
return elementsToLink.includes(linkend);
|
|
3444
|
-
};
|
|
3453
|
+
var findElementLinkedTo = (linkend, elementsToLink) => hasLinkId(elementsToLink, linkend);
|
|
3445
3454
|
var LINK_TO_CROSS_CHECK = [
|
|
3446
3455
|
TABLE_LINK_ROLE,
|
|
3447
3456
|
FIGURE_LINK_ROLE,
|
|
@@ -3662,9 +3671,7 @@ var getExtraInstruction = (schema, childSchema) => {
|
|
|
3662
3671
|
};
|
|
3663
3672
|
|
|
3664
3673
|
// src/validation/validateElementToLinkTo.ts
|
|
3665
|
-
var findElementLinkedTo2 = (xmlid, linkElements) =>
|
|
3666
|
-
return linkElements.includes(xmlid);
|
|
3667
|
-
};
|
|
3674
|
+
var findElementLinkedTo2 = (xmlid, linkElements) => hasLinkId(linkElements, xmlid);
|
|
3668
3675
|
var isFootnote = (element) => {
|
|
3669
3676
|
return matchesSchemaTag(element, FOOTNOTE_SCHEMA.tag);
|
|
3670
3677
|
};
|
|
@@ -3734,6 +3741,16 @@ var validateElementToLinkTo = (element, linkElements) => {
|
|
|
3734
3741
|
|
|
3735
3742
|
// src/validation/validateWeblink.ts
|
|
3736
3743
|
import Mark from "mark.js";
|
|
3744
|
+
|
|
3745
|
+
// src/validation/helpers/steps.ts
|
|
3746
|
+
var runSteps = (steps) => {
|
|
3747
|
+
for (; ; ) {
|
|
3748
|
+
const step = steps.next();
|
|
3749
|
+
if (step.done) return step.value;
|
|
3750
|
+
}
|
|
3751
|
+
};
|
|
3752
|
+
|
|
3753
|
+
// src/validation/validateWeblink.ts
|
|
3737
3754
|
var EDGE_PUNCTUATION = `:;.,\\-\u2013\u2014\u2012_(){}[\\]!'"+=\xAB\xBB\u2039\u203A\u201C\u201D\u2018\u2019<>`;
|
|
3738
3755
|
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}])?)?`;
|
|
3739
3756
|
var WEB_URI_IN_TEXT_REGEX = new RegExp(WEB_URI_PATTERN, "gi");
|
|
@@ -3814,11 +3831,62 @@ var markPossibleWeblinks = (editor) => {
|
|
|
3814
3831
|
});
|
|
3815
3832
|
return possibleWeblinks;
|
|
3816
3833
|
};
|
|
3817
|
-
var
|
|
3834
|
+
var TEXT_NODES_PER_STEP = 256;
|
|
3835
|
+
var MARK_EXCLUDED_PARENT_SELECTOR = [
|
|
3836
|
+
...POSSIBLE_WEBLINK_EXCLUDE_SELECTORS,
|
|
3837
|
+
"script",
|
|
3838
|
+
"style",
|
|
3839
|
+
"title",
|
|
3840
|
+
"head",
|
|
3841
|
+
"html"
|
|
3842
|
+
].join(", ");
|
|
3843
|
+
var createWeblinkMatchElement = (ownerDocument, text, storeId) => {
|
|
3844
|
+
const element = ownerDocument.createElement("mark");
|
|
3845
|
+
element.setAttribute("data-markjs", "true");
|
|
3846
|
+
element.setAttribute("class", POSSIBLE_WEBLINK_CLASS);
|
|
3847
|
+
element.setAttribute(STORE_ATTRIBUTE, storeId);
|
|
3848
|
+
element.textContent = text;
|
|
3849
|
+
return element;
|
|
3850
|
+
};
|
|
3851
|
+
function* findPossibleWeblinks(root) {
|
|
3852
|
+
const possibleWeblinks = /* @__PURE__ */ new Map();
|
|
3853
|
+
const ownerDocument = root.ownerDocument;
|
|
3854
|
+
const walker = ownerDocument.createTreeWalker(root, NodeFilter.SHOW_TEXT);
|
|
3855
|
+
const regex = new RegExp(WEB_URI_PATTERN, "gi");
|
|
3856
|
+
let nodesSinceStep = 0;
|
|
3857
|
+
for (let node = walker.nextNode(); node; node = walker.nextNode()) {
|
|
3858
|
+
if (++nodesSinceStep === TEXT_NODES_PER_STEP) {
|
|
3859
|
+
nodesSinceStep = 0;
|
|
3860
|
+
yield;
|
|
3861
|
+
}
|
|
3862
|
+
const text = node.textContent ?? "";
|
|
3863
|
+
if (!text) continue;
|
|
3864
|
+
const parent = node.parentNode;
|
|
3865
|
+
if (parent instanceof Element && parent.matches(MARK_EXCLUDED_PARENT_SELECTOR)) {
|
|
3866
|
+
continue;
|
|
3867
|
+
}
|
|
3868
|
+
regex.lastIndex = 0;
|
|
3869
|
+
for (let match = regex.exec(text); match; match = regex.exec(text)) {
|
|
3870
|
+
const storeId = getWeblinkMatchId(possibleWeblinks.size);
|
|
3871
|
+
possibleWeblinks.set(storeId, {
|
|
3872
|
+
weblink: match[0],
|
|
3873
|
+
elements: [createWeblinkMatchElement(ownerDocument, match[0], storeId)]
|
|
3874
|
+
});
|
|
3875
|
+
}
|
|
3876
|
+
}
|
|
3877
|
+
return possibleWeblinks;
|
|
3878
|
+
}
|
|
3879
|
+
var hasWeblinkMatches = (root) => root.getElementsByClassName(POSSIBLE_WEBLINK_CLASS).length > 0;
|
|
3880
|
+
function* validatePossibleWeblinksSteps(root) {
|
|
3818
3881
|
const issues = [];
|
|
3819
|
-
|
|
3820
|
-
|
|
3821
|
-
|
|
3882
|
+
let possibleWeblinks;
|
|
3883
|
+
if (hasWeblinkMatches(root)) {
|
|
3884
|
+
const cloneRoot = root.cloneNode(true);
|
|
3885
|
+
clearWeblinkMatches(cloneRoot);
|
|
3886
|
+
possibleWeblinks = markPossibleWeblinks(cloneRoot);
|
|
3887
|
+
} else {
|
|
3888
|
+
possibleWeblinks = yield* findPossibleWeblinks(root);
|
|
3889
|
+
}
|
|
3822
3890
|
for (const [storeId, { elements }] of Array.from(possibleWeblinks)) {
|
|
3823
3891
|
issues.push(
|
|
3824
3892
|
createValidationIssue(null, {
|
|
@@ -3832,7 +3900,8 @@ var validatePossibleWeblinks = (root) => {
|
|
|
3832
3900
|
);
|
|
3833
3901
|
}
|
|
3834
3902
|
return issues;
|
|
3835
|
-
}
|
|
3903
|
+
}
|
|
3904
|
+
var validatePossibleWeblinks = (root) => runSteps(validatePossibleWeblinksSteps(root));
|
|
3836
3905
|
var clearWeblinkMatches = (editor) => {
|
|
3837
3906
|
const instance = new Mark(editor);
|
|
3838
3907
|
instance.unmark({
|
|
@@ -4289,66 +4358,106 @@ var validateReference = (reference) => {
|
|
|
4289
4358
|
};
|
|
4290
4359
|
|
|
4291
4360
|
// src/validation/validateXml.ts
|
|
4292
|
-
var
|
|
4361
|
+
var ELEMENTS_PER_STEP = 64;
|
|
4362
|
+
var DEFAULT_TIME_BUDGET_MS = 8;
|
|
4363
|
+
var validateOwnElement = (element, {
|
|
4364
|
+
elementsToLink,
|
|
4365
|
+
linkElements,
|
|
4366
|
+
schemasToValidateAgainst,
|
|
4367
|
+
errors
|
|
4368
|
+
}) => {
|
|
4293
4369
|
if (isIgnoredElement(element)) {
|
|
4294
|
-
return
|
|
4370
|
+
return false;
|
|
4295
4371
|
}
|
|
4296
|
-
const errors = [];
|
|
4297
4372
|
const schema = findSchemaByElement(element);
|
|
4298
|
-
if (schema) {
|
|
4299
|
-
|
|
4300
|
-
errors.push(
|
|
4301
|
-
...schema.code === BIBLIOMIXED_SCHEMA.code ? validateReference(element) : validateElementAgainstSchema(element, schema)
|
|
4302
|
-
);
|
|
4303
|
-
}
|
|
4304
|
-
if (schema.tag === FOOTNOTE_SCHEMA.tag) {
|
|
4305
|
-
errors.push(...validateFootnoteNumber(element));
|
|
4306
|
-
}
|
|
4307
|
-
if (schema.code === HEADING_SCHEMA.code) {
|
|
4308
|
-
errors.push(...validateHierarchy(element, "heading"));
|
|
4309
|
-
}
|
|
4310
|
-
if (schema.code === BOX_SCHEMA.code) {
|
|
4311
|
-
errors.push(...validateHierarchy(element, "box"));
|
|
4312
|
-
}
|
|
4313
|
-
if (schema.code === OLINK_SCHEMA.code) {
|
|
4314
|
-
errors.push(...validateOlink(element));
|
|
4315
|
-
}
|
|
4316
|
-
errors.push(...validateLinkend(element, elementsToLink));
|
|
4317
|
-
errors.push(...validateElementToLinkTo(element, linkElements));
|
|
4318
|
-
if (isIgnoredValidation(schema.code)) {
|
|
4319
|
-
return errors;
|
|
4320
|
-
}
|
|
4373
|
+
if (!schema) {
|
|
4374
|
+
return true;
|
|
4321
4375
|
}
|
|
4322
|
-
|
|
4376
|
+
if (schemasToValidateAgainst.includes(schema.code)) {
|
|
4323
4377
|
errors.push(
|
|
4324
|
-
...
|
|
4325
|
-
child,
|
|
4326
|
-
root,
|
|
4327
|
-
elementsToLink,
|
|
4328
|
-
linkElements,
|
|
4329
|
-
schemasToValidateAgainst
|
|
4330
|
-
)
|
|
4378
|
+
...schema.code === BIBLIOMIXED_SCHEMA.code ? validateReference(element) : validateElementAgainstSchema(element, schema)
|
|
4331
4379
|
);
|
|
4332
4380
|
}
|
|
4333
|
-
|
|
4381
|
+
if (schema.tag === FOOTNOTE_SCHEMA.tag) {
|
|
4382
|
+
errors.push(...validateFootnoteNumber(element));
|
|
4383
|
+
}
|
|
4384
|
+
if (schema.code === HEADING_SCHEMA.code) {
|
|
4385
|
+
errors.push(...validateHierarchy(element, "heading"));
|
|
4386
|
+
}
|
|
4387
|
+
if (schema.code === BOX_SCHEMA.code) {
|
|
4388
|
+
errors.push(...validateHierarchy(element, "box"));
|
|
4389
|
+
}
|
|
4390
|
+
if (schema.code === OLINK_SCHEMA.code) {
|
|
4391
|
+
errors.push(...validateOlink(element));
|
|
4392
|
+
}
|
|
4393
|
+
errors.push(...validateLinkend(element, elementsToLink));
|
|
4394
|
+
errors.push(...validateElementToLinkTo(element, linkElements));
|
|
4395
|
+
return !isIgnoredValidation(schema.code);
|
|
4334
4396
|
};
|
|
4335
|
-
|
|
4397
|
+
function* validateElements(xml, context) {
|
|
4398
|
+
const pending = Array.from(xml.children).reverse();
|
|
4399
|
+
let elementsSinceStep = 0;
|
|
4400
|
+
for (let element = pending.pop(); element; element = pending.pop()) {
|
|
4401
|
+
if (validateOwnElement(element, context)) {
|
|
4402
|
+
const { children } = element;
|
|
4403
|
+
for (let index = children.length - 1; index >= 0; index -= 1) {
|
|
4404
|
+
pending.push(children[index]);
|
|
4405
|
+
}
|
|
4406
|
+
}
|
|
4407
|
+
if (++elementsSinceStep === ELEMENTS_PER_STEP) {
|
|
4408
|
+
elementsSinceStep = 0;
|
|
4409
|
+
yield;
|
|
4410
|
+
}
|
|
4411
|
+
}
|
|
4412
|
+
}
|
|
4413
|
+
function* validateXmlSteps(xml, elementsToLink, linkElements, schemasToValidateAgainst) {
|
|
4336
4414
|
const errors = [];
|
|
4337
4415
|
errors.push(...validateConsecutiveFootnotes(xml));
|
|
4338
4416
|
errors.push(...validateConsecutiveFootnoteCues(xml));
|
|
4339
|
-
|
|
4340
|
-
|
|
4341
|
-
|
|
4342
|
-
|
|
4343
|
-
|
|
4344
|
-
|
|
4345
|
-
|
|
4346
|
-
|
|
4347
|
-
schemasToValidateAgainst
|
|
4348
|
-
)
|
|
4349
|
-
);
|
|
4350
|
-
}
|
|
4417
|
+
yield;
|
|
4418
|
+
errors.push(...yield* validatePossibleWeblinksSteps(xml));
|
|
4419
|
+
yield* validateElements(xml, {
|
|
4420
|
+
elementsToLink: new Set(elementsToLink),
|
|
4421
|
+
linkElements: new Set(linkElements),
|
|
4422
|
+
schemasToValidateAgainst,
|
|
4423
|
+
errors
|
|
4424
|
+
});
|
|
4351
4425
|
return errors;
|
|
4426
|
+
}
|
|
4427
|
+
var validateXml = (xml, elementsToLink, linkElements, schemasToValidateAgainst) => runSteps(
|
|
4428
|
+
validateXmlSteps(
|
|
4429
|
+
xml,
|
|
4430
|
+
elementsToLink,
|
|
4431
|
+
linkElements,
|
|
4432
|
+
schemasToValidateAgainst
|
|
4433
|
+
)
|
|
4434
|
+
);
|
|
4435
|
+
var yieldToMainThread = () => {
|
|
4436
|
+
const scheduler = globalThis.scheduler;
|
|
4437
|
+
if (scheduler?.yield) return scheduler.yield();
|
|
4438
|
+
return new Promise((resolve) => setTimeout(resolve, 0));
|
|
4439
|
+
};
|
|
4440
|
+
var throwIfAborted = (signal) => {
|
|
4441
|
+
if (!signal?.aborted) return;
|
|
4442
|
+
throw signal.reason ?? new DOMException("Aborted", "AbortError");
|
|
4443
|
+
};
|
|
4444
|
+
var validateXmlAsync = async (xml, elementsToLink, linkElements, schemasToValidateAgainst, { signal, timeBudgetMs = DEFAULT_TIME_BUDGET_MS } = {}) => {
|
|
4445
|
+
const steps = validateXmlSteps(
|
|
4446
|
+
xml,
|
|
4447
|
+
elementsToLink,
|
|
4448
|
+
linkElements,
|
|
4449
|
+
schemasToValidateAgainst
|
|
4450
|
+
);
|
|
4451
|
+
let sliceStart = performance.now();
|
|
4452
|
+
for (; ; ) {
|
|
4453
|
+
throwIfAborted(signal);
|
|
4454
|
+
const step = steps.next();
|
|
4455
|
+
if (step.done) return step.value;
|
|
4456
|
+
if (performance.now() - sliceStart >= timeBudgetMs) {
|
|
4457
|
+
await yieldToMainThread();
|
|
4458
|
+
sliceStart = performance.now();
|
|
4459
|
+
}
|
|
4460
|
+
}
|
|
4352
4461
|
};
|
|
4353
4462
|
|
|
4354
4463
|
// src/helpers/getElementLinks.ts
|
|
@@ -4507,6 +4616,8 @@ export {
|
|
|
4507
4616
|
validateLinkend,
|
|
4508
4617
|
validateOlink,
|
|
4509
4618
|
validatePossibleWeblinks,
|
|
4619
|
+
validatePossibleWeblinksSteps,
|
|
4510
4620
|
validateReferenceStructure,
|
|
4511
|
-
validateXml
|
|
4621
|
+
validateXml,
|
|
4622
|
+
validateXmlAsync
|
|
4512
4623
|
};
|