pro-editor-schema 0.1.199 → 0.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 CHANGED
@@ -40,8 +40,8 @@ Each schema defines:
40
40
  - `tag`: uppercase XML tag name used in documents.
41
41
  - `requiredAttributes`: required attributes (free or restricted values).
42
42
  - `optionalAttributes`: optional attributes (free or restricted values).
43
- - `defaultChildTagName`: preferred child tag (optional, used by some block-like schemas).
44
- - `allowedChildTagNames`: allowed child tags and whether each child is required.
43
+ - `defaultChildCode`: preferred child tag (optional, used by some block-like schemas).
44
+ - `allowedChildrenCodes`: allowed child tags and whether each child is required.
45
45
 
46
46
  Schemas are combined in `SCHEMAS` from:
47
47
 
package/dist/index.d.mts CHANGED
@@ -17,20 +17,21 @@ type Schema<TRequiredAttributes = readonly AttributeDefinition[], TOptionalAttri
17
17
  requiredAttributes: TRequiredAttributes;
18
18
  optionalAttributes: TOptionalAttributes;
19
19
  defaultChildCode?: SchemaCode;
20
- allowedChildrenCodes: ReadonlySet<AllowedChildren>;
20
+ allowedChildrenCodes: AllowedChildren[];
21
+ matchesElement?: (element: Element) => boolean;
21
22
  };
22
23
  type SchemaCode = ElementSchemaCode | InlineSchemaCode | AtomSchemaCode;
23
24
  type ElementSchemaCode = "referenceBibliomixed" | "referenceBibliography" | "bibliodiv" | "degrees" | "email" | "equation" | "fignote" | "figsource" | "firstname" | "footnote" | "footnoteno" | "honorific" | "img" | "informalfigure" | "keyword" | "label1" | "li" | "line" | "lrh" | "math" | "mathphrase" | "merror" | "mfrac" | "mi" | "mmultiscripts" | "mn" | "mo" | "mover" | "mpadded" | "mphantom" | "mprescripts" | "mroot" | "mrow" | "ms" | "mspace" | "msqrt" | "mstyle" | "msub" | "msubsup" | "msup" | "mtable" | "mtd" | "mtext" | "mtr" | "munder" | "munderover" | "olink" | "org" | "orgname" | "para" | "punc" | "rrh" | "source1" | "speaker" | "subtitle1" | "surname" | "tag" | "tblfn" | "tblsource" | "thead" | "title1" | "token" | "tp" | "abstract1" | "affiliation" | "alttext" | "appendix" | "author" | "authorgroup" | "blockquote" | "caption1" | "chapter" | "dialogue" | "epigraph" | "figure1" | "footnoteSection" | "heading" | "imageobject" | "info1" | "keywordset" | "mediaobject" | "ol" | "personname" | "poem" | "sidebar" | "table" | "table1" | "tbody" | "td" | "tgroup" | "tr" | "ul";
24
25
  type AtomSchemaCode = "indexterm" | "primary" | "secondary" | "tertiary" | "quaternary" | "bookmark" | "see" | "commentQuerySection" | "comment" | "content" | "query" | "reply" | "deletion" | "emphasis" | "highlightmark" | "i" | "insertion" | "sc" | "strike" | "sub" | "sup" | "u" | "b" | "referenceMark";
25
26
  type InlineSchemaCode = "footnote1" | "inlineequation" | "link" | "uri" | "phrase";
26
- declare const ElementLabel: Record<SchemaCode, string>;
27
27
 
28
28
  declare const SCHEMAS: Record<SchemaCode, Schema>;
29
29
 
30
+ declare const isTrackChangesSchema: (schema: Schema) => boolean;
30
31
  declare const isIgnoredAttribute: (attribute: string) => boolean;
31
32
  declare const isIgnoredElement: (element: Element) => boolean;
32
33
  declare const isIgnoredValidation: (code: SchemaCode) => boolean;
33
- declare const findSchemaByCode: (code: SchemaCode) => Schema | undefined;
34
+ declare const findSchemaByCode: (code: SchemaCode) => Schema;
34
35
  declare const findSchemaByElement: (element: Element) => Schema | undefined;
35
36
  declare const isAttributeRestricted: (attr: AttributeDefinition) => attr is RestrictedAttribute;
36
37
  declare const getAttributeName: (attribute: AttributeDefinition) => string;
@@ -48,12 +49,20 @@ type CreateElementParams<TSchema extends Schema> = {
48
49
  };
49
50
  declare const createElement: <TSchema extends Schema>({ schemaCode, attributes, }: CreateElementParams<TSchema>) => HTMLElement;
50
51
 
52
+ declare const ElementLabel: Record<SchemaCode, string>;
53
+
51
54
  declare const IGNORED_ELEMENT_SELECTORS: string[];
52
55
  declare const IGNORED_VALIDATION_ELEMENT_SELECTORS: SchemaCode[];
53
56
 
54
57
  declare const IGNORED_ATTRIBUTES: string[];
55
58
  declare const IGNORED_ATTRIBUTES_STARTS_WITH: string[];
56
59
 
60
+ type DependentForbiddenElement = {
61
+ code: SchemaCode;
62
+ dependentElements: SchemaCode[];
63
+ };
64
+ declare const DEPENDENT_FORBIDDEN_ELEMENTS: DependentForbiddenElement[];
65
+
57
66
  declare const ALIGNMENT_ATTRIBUTE = "data-alignment";
58
67
  declare const LEFT_INDENT_ATTRIBUTE = "data-left-indent";
59
68
  declare const RIGHT_INDENT_ATTRIBUTE = "data-right-indent";
@@ -104,6 +113,6 @@ type ValidationError = {
104
113
  * * ValidateConsecutiveFootnotes and ValidateConsecutiveFootnoteCues are default validations.
105
114
  * @returns The validation errors.
106
115
  */
107
- declare const validateXml: (xml: Element, elementsToLink: readonly string[], linkElements: readonly string[], schemasToValidateAgainst: SchemaCode[]) => ValidationError[];
116
+ declare const validateXml: (xml: Element, elementsToLink: string[], linkElements: string[], schemasToValidateAgainst: SchemaCode[]) => ValidationError[];
108
117
 
109
- export { ALIGNMENT_ATTRIBUTE, ATOM_SCHEMAS, type AllowedChildren, type AtomSchemaCode, type AttributeDefinition, ELEMENT_SCHEMAS, ELE_ID_ATTRIBUTE, ElementLabel, type ElementSchemaCode, FIGURE_PLACEMENT_ATTRIBUTE, type FreeAttribute, ID_ATTRS, IGNORED_ATTRIBUTES, IGNORED_ATTRIBUTES_STARTS_WITH, IGNORED_ELEMENT_SELECTORS, IGNORED_VALIDATION_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, RIGHT_INDENT_ATTRIBUTE, type RestrictedAttribute, SCHEMAS, SPACE_ABOVE_ATTRIBUTE, SPACE_BELOW_ATTRIBUTE, SPECIAL_INDENT_ATTRIBUTE, STORE_ATTRIBUTE, STYLE_NAME_ATTRIBUTE, type Schema, type SchemaCode, type SchemaKind, TRACK_CHANGES_ATTRS, TRACK_CHANGES_ATTR_DATA_DATE, TRACK_CHANGES_ATTR_DATA_TIME, TRACK_CHANGES_ATTR_DATA_USERID, TRACK_CHANGES_ATTR_DATA_USERNAME, type ValidationError, type ValidationErrorKind, type ValidationErrorLevel, createElement, findAttributeDefinitionByName, findSchemaByCode, findSchemaByElement, getAttributeName, isAttributeRestricted, isIgnoredAttribute, isIgnoredElement, isIgnoredValidation, validateXml };
118
+ export { ALIGNMENT_ATTRIBUTE, ATOM_SCHEMAS, type AllowedChildren, type AtomSchemaCode, type AttributeDefinition, 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, IGNORED_VALIDATION_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, RIGHT_INDENT_ATTRIBUTE, type RestrictedAttribute, SCHEMAS, SPACE_ABOVE_ATTRIBUTE, SPACE_BELOW_ATTRIBUTE, SPECIAL_INDENT_ATTRIBUTE, STORE_ATTRIBUTE, STYLE_NAME_ATTRIBUTE, type Schema, type SchemaCode, type SchemaKind, TRACK_CHANGES_ATTRS, TRACK_CHANGES_ATTR_DATA_DATE, TRACK_CHANGES_ATTR_DATA_TIME, TRACK_CHANGES_ATTR_DATA_USERID, TRACK_CHANGES_ATTR_DATA_USERNAME, type ValidationError, type ValidationErrorKind, type ValidationErrorLevel, createElement, findAttributeDefinitionByName, findSchemaByCode, findSchemaByElement, getAttributeName, isAttributeRestricted, isIgnoredAttribute, isIgnoredElement, isIgnoredValidation, isTrackChangesSchema, validateXml };
package/dist/index.d.ts CHANGED
@@ -17,20 +17,21 @@ type Schema<TRequiredAttributes = readonly AttributeDefinition[], TOptionalAttri
17
17
  requiredAttributes: TRequiredAttributes;
18
18
  optionalAttributes: TOptionalAttributes;
19
19
  defaultChildCode?: SchemaCode;
20
- allowedChildrenCodes: ReadonlySet<AllowedChildren>;
20
+ allowedChildrenCodes: AllowedChildren[];
21
+ matchesElement?: (element: Element) => boolean;
21
22
  };
22
23
  type SchemaCode = ElementSchemaCode | InlineSchemaCode | AtomSchemaCode;
23
24
  type ElementSchemaCode = "referenceBibliomixed" | "referenceBibliography" | "bibliodiv" | "degrees" | "email" | "equation" | "fignote" | "figsource" | "firstname" | "footnote" | "footnoteno" | "honorific" | "img" | "informalfigure" | "keyword" | "label1" | "li" | "line" | "lrh" | "math" | "mathphrase" | "merror" | "mfrac" | "mi" | "mmultiscripts" | "mn" | "mo" | "mover" | "mpadded" | "mphantom" | "mprescripts" | "mroot" | "mrow" | "ms" | "mspace" | "msqrt" | "mstyle" | "msub" | "msubsup" | "msup" | "mtable" | "mtd" | "mtext" | "mtr" | "munder" | "munderover" | "olink" | "org" | "orgname" | "para" | "punc" | "rrh" | "source1" | "speaker" | "subtitle1" | "surname" | "tag" | "tblfn" | "tblsource" | "thead" | "title1" | "token" | "tp" | "abstract1" | "affiliation" | "alttext" | "appendix" | "author" | "authorgroup" | "blockquote" | "caption1" | "chapter" | "dialogue" | "epigraph" | "figure1" | "footnoteSection" | "heading" | "imageobject" | "info1" | "keywordset" | "mediaobject" | "ol" | "personname" | "poem" | "sidebar" | "table" | "table1" | "tbody" | "td" | "tgroup" | "tr" | "ul";
24
25
  type AtomSchemaCode = "indexterm" | "primary" | "secondary" | "tertiary" | "quaternary" | "bookmark" | "see" | "commentQuerySection" | "comment" | "content" | "query" | "reply" | "deletion" | "emphasis" | "highlightmark" | "i" | "insertion" | "sc" | "strike" | "sub" | "sup" | "u" | "b" | "referenceMark";
25
26
  type InlineSchemaCode = "footnote1" | "inlineequation" | "link" | "uri" | "phrase";
26
- declare const ElementLabel: Record<SchemaCode, string>;
27
27
 
28
28
  declare const SCHEMAS: Record<SchemaCode, Schema>;
29
29
 
30
+ declare const isTrackChangesSchema: (schema: Schema) => boolean;
30
31
  declare const isIgnoredAttribute: (attribute: string) => boolean;
31
32
  declare const isIgnoredElement: (element: Element) => boolean;
32
33
  declare const isIgnoredValidation: (code: SchemaCode) => boolean;
33
- declare const findSchemaByCode: (code: SchemaCode) => Schema | undefined;
34
+ declare const findSchemaByCode: (code: SchemaCode) => Schema;
34
35
  declare const findSchemaByElement: (element: Element) => Schema | undefined;
35
36
  declare const isAttributeRestricted: (attr: AttributeDefinition) => attr is RestrictedAttribute;
36
37
  declare const getAttributeName: (attribute: AttributeDefinition) => string;
@@ -48,12 +49,20 @@ type CreateElementParams<TSchema extends Schema> = {
48
49
  };
49
50
  declare const createElement: <TSchema extends Schema>({ schemaCode, attributes, }: CreateElementParams<TSchema>) => HTMLElement;
50
51
 
52
+ declare const ElementLabel: Record<SchemaCode, string>;
53
+
51
54
  declare const IGNORED_ELEMENT_SELECTORS: string[];
52
55
  declare const IGNORED_VALIDATION_ELEMENT_SELECTORS: SchemaCode[];
53
56
 
54
57
  declare const IGNORED_ATTRIBUTES: string[];
55
58
  declare const IGNORED_ATTRIBUTES_STARTS_WITH: string[];
56
59
 
60
+ type DependentForbiddenElement = {
61
+ code: SchemaCode;
62
+ dependentElements: SchemaCode[];
63
+ };
64
+ declare const DEPENDENT_FORBIDDEN_ELEMENTS: DependentForbiddenElement[];
65
+
57
66
  declare const ALIGNMENT_ATTRIBUTE = "data-alignment";
58
67
  declare const LEFT_INDENT_ATTRIBUTE = "data-left-indent";
59
68
  declare const RIGHT_INDENT_ATTRIBUTE = "data-right-indent";
@@ -104,6 +113,6 @@ type ValidationError = {
104
113
  * * ValidateConsecutiveFootnotes and ValidateConsecutiveFootnoteCues are default validations.
105
114
  * @returns The validation errors.
106
115
  */
107
- declare const validateXml: (xml: Element, elementsToLink: readonly string[], linkElements: readonly string[], schemasToValidateAgainst: SchemaCode[]) => ValidationError[];
116
+ declare const validateXml: (xml: Element, elementsToLink: string[], linkElements: string[], schemasToValidateAgainst: SchemaCode[]) => ValidationError[];
108
117
 
109
- export { ALIGNMENT_ATTRIBUTE, ATOM_SCHEMAS, type AllowedChildren, type AtomSchemaCode, type AttributeDefinition, ELEMENT_SCHEMAS, ELE_ID_ATTRIBUTE, ElementLabel, type ElementSchemaCode, FIGURE_PLACEMENT_ATTRIBUTE, type FreeAttribute, ID_ATTRS, IGNORED_ATTRIBUTES, IGNORED_ATTRIBUTES_STARTS_WITH, IGNORED_ELEMENT_SELECTORS, IGNORED_VALIDATION_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, RIGHT_INDENT_ATTRIBUTE, type RestrictedAttribute, SCHEMAS, SPACE_ABOVE_ATTRIBUTE, SPACE_BELOW_ATTRIBUTE, SPECIAL_INDENT_ATTRIBUTE, STORE_ATTRIBUTE, STYLE_NAME_ATTRIBUTE, type Schema, type SchemaCode, type SchemaKind, TRACK_CHANGES_ATTRS, TRACK_CHANGES_ATTR_DATA_DATE, TRACK_CHANGES_ATTR_DATA_TIME, TRACK_CHANGES_ATTR_DATA_USERID, TRACK_CHANGES_ATTR_DATA_USERNAME, type ValidationError, type ValidationErrorKind, type ValidationErrorLevel, createElement, findAttributeDefinitionByName, findSchemaByCode, findSchemaByElement, getAttributeName, isAttributeRestricted, isIgnoredAttribute, isIgnoredElement, isIgnoredValidation, validateXml };
118
+ export { ALIGNMENT_ATTRIBUTE, ATOM_SCHEMAS, type AllowedChildren, type AtomSchemaCode, type AttributeDefinition, 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, IGNORED_VALIDATION_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, RIGHT_INDENT_ATTRIBUTE, type RestrictedAttribute, SCHEMAS, SPACE_ABOVE_ATTRIBUTE, SPACE_BELOW_ATTRIBUTE, SPECIAL_INDENT_ATTRIBUTE, STORE_ATTRIBUTE, STYLE_NAME_ATTRIBUTE, type Schema, type SchemaCode, type SchemaKind, TRACK_CHANGES_ATTRS, TRACK_CHANGES_ATTR_DATA_DATE, TRACK_CHANGES_ATTR_DATA_TIME, TRACK_CHANGES_ATTR_DATA_USERID, TRACK_CHANGES_ATTR_DATA_USERNAME, type ValidationError, type ValidationErrorKind, type ValidationErrorLevel, createElement, findAttributeDefinitionByName, findSchemaByCode, findSchemaByElement, getAttributeName, isAttributeRestricted, isIgnoredAttribute, isIgnoredElement, isIgnoredValidation, isTrackChangesSchema, validateXml };
package/dist/index.js CHANGED
@@ -22,6 +22,7 @@ var index_exports = {};
22
22
  __export(index_exports, {
23
23
  ALIGNMENT_ATTRIBUTE: () => ALIGNMENT_ATTRIBUTE,
24
24
  ATOM_SCHEMAS: () => ATOM_SCHEMAS,
25
+ DEPENDENT_FORBIDDEN_ELEMENTS: () => DEPENDENT_FORBIDDEN_ELEMENTS,
25
26
  ELEMENT_SCHEMAS: () => ELEMENT_SCHEMAS,
26
27
  ELE_ID_ATTRIBUTE: () => ELE_ID_ATTRIBUTE,
27
28
  ElementLabel: () => ElementLabel,
@@ -60,29 +61,14 @@ __export(index_exports, {
60
61
  isIgnoredAttribute: () => isIgnoredAttribute,
61
62
  isIgnoredElement: () => isIgnoredElement,
62
63
  isIgnoredValidation: () => isIgnoredValidation,
64
+ isTrackChangesSchema: () => isTrackChangesSchema,
63
65
  validateXml: () => validateXml
64
66
  });
65
67
  module.exports = __toCommonJS(index_exports);
66
68
 
67
69
  // src/schema/utils/createSchema.ts
68
- var createSchema = ({
69
- code,
70
- kind,
71
- tag,
72
- requiredAttributes,
73
- optionalAttributes,
74
- defaultChildCode,
75
- allowedChildrenCodes
76
- }) => {
77
- return {
78
- code,
79
- kind,
80
- tag,
81
- requiredAttributes,
82
- optionalAttributes,
83
- defaultChildCode,
84
- allowedChildrenCodes: new Set(allowedChildrenCodes)
85
- };
70
+ var createSchema = (params) => {
71
+ return params;
86
72
  };
87
73
 
88
74
  // src/schema/shared/globalAttributes.ts
@@ -183,6 +169,7 @@ var COMMENT_QUERY_SECTION_SCHEMA = createSchema({
183
169
  kind: "atom",
184
170
  tag: SPAN_TAG,
185
171
  code: "commentQuerySection",
172
+ matchesElement: (element) => element.classList.contains("cmtQurySection"),
186
173
  requiredAttributes: [...ID_ATTRS, "id"],
187
174
  optionalAttributes: [...TRACK_CHANGES_ATTRS, "title"],
188
175
  allowedChildrenCodes: [...ATOM_CODES_ALLOWED_CHILDREN]
@@ -202,6 +189,7 @@ var DELETION_SCHEMA = createSchema({
202
189
  code: "deletion",
203
190
  kind: "atom",
204
191
  tag: SPAN_TAG,
192
+ matchesElement: (element) => element.classList.contains("del"),
205
193
  requiredAttributes: [...TRACK_CHANGES_ATTRS, ...ID_ATTRS],
206
194
  optionalAttributes: [],
207
195
  allowedChildrenCodes: [
@@ -252,6 +240,7 @@ var INSERTION_SCHEMA = createSchema({
252
240
  code: "insertion",
253
241
  kind: "atom",
254
242
  tag: SPAN_TAG,
243
+ matchesElement: (element) => element.classList.contains("ins"),
255
244
  requiredAttributes: [...TRACK_CHANGES_ATTRS, ...ID_ATTRS],
256
245
  optionalAttributes: [],
257
246
  allowedChildrenCodes: [
@@ -1973,15 +1962,21 @@ var EPIGRAPH_SCHEMA = createSchema({
1973
1962
  });
1974
1963
 
1975
1964
  // src/schema/elementSchemas/elements/footnoteSection.ts
1965
+ var FOOTNOTE_SECTION_ROLES = ["ch", "bk"];
1976
1966
  var FOOTNOTE_SECTION_SCHEMA = createSchema({
1977
1967
  code: "footnoteSection",
1978
1968
  kind: "element",
1979
1969
  tag: SECTION_TAG,
1970
+ matchesElement: (element) => {
1971
+ const role = element.getAttribute("role");
1972
+ if (role && FOOTNOTE_SECTION_ROLES.includes(role)) return true;
1973
+ return element.querySelector(FOOTNOTE_TAG) !== null;
1974
+ },
1980
1975
  requiredAttributes: [
1981
1976
  ...ID_ATTRS,
1982
1977
  {
1983
1978
  name: "role",
1984
- values: ["ch", "bk"],
1979
+ values: FOOTNOTE_SECTION_ROLES,
1985
1980
  defaultValue: "ch"
1986
1981
  }
1987
1982
  ],
@@ -1994,16 +1989,22 @@ var FOOTNOTE_SECTION_SCHEMA = createSchema({
1994
1989
  });
1995
1990
 
1996
1991
  // src/schema/elementSchemas/elements/heading.ts
1992
+ var HEADING_ROLES = ["H1", "H2", "H3", "H4", "H5", "H6", "vignette_group"];
1997
1993
  var HEADING_SCHEMA = createSchema({
1998
1994
  code: "heading",
1999
1995
  kind: "element",
2000
1996
  tag: SECTION_TAG,
1997
+ matchesElement: (element) => {
1998
+ const role = element.getAttribute("role");
1999
+ if (!role) return false;
2000
+ return HEADING_ROLES.includes(role);
2001
+ },
2001
2002
  requiredAttributes: [
2002
2003
  ...ID_ATTRS,
2003
2004
  "xmlid",
2004
2005
  {
2005
2006
  name: "role",
2006
- values: ["H1", "H2", "H3", "H4", "H5", "H6", "vignette_group"],
2007
+ values: HEADING_ROLES,
2007
2008
  defaultValue: "H1"
2008
2009
  }
2009
2010
  ],
@@ -2070,17 +2071,7 @@ var MATHPHRASE_SCHEMA = createSchema({
2070
2071
  tag: MATHPHRASE_TAG,
2071
2072
  requiredAttributes: [ELE_ID_ATTRIBUTE],
2072
2073
  optionalAttributes: [],
2073
- allowedChildrenCodes: [
2074
- { code: MATH_SCHEMA.code, required: true },
2075
- {
2076
- code: INSERTION_SCHEMA.code,
2077
- required: false
2078
- },
2079
- {
2080
- code: DELETION_SCHEMA.code,
2081
- required: false
2082
- }
2083
- ]
2074
+ allowedChildrenCodes: [{ code: MATH_SCHEMA.code, required: true }]
2084
2075
  });
2085
2076
 
2086
2077
  // src/schema/elementSchemas/elements/reference/bibliodiv.ts
@@ -2338,7 +2329,78 @@ var SCHEMAS = {
2338
2329
  ...INLINE_ELEMENT_SCHEMAS
2339
2330
  };
2340
2331
 
2341
- // src/schema/schema.types.ts
2332
+ // src/schema/shared/ignoredElements.ts
2333
+ var IGNORED_ELEMENT_SELECTORS = [
2334
+ "span.rhlabel",
2335
+ "span.printlabel",
2336
+ "span.refIcon",
2337
+ "span.missLink",
2338
+ "span.ref-drag"
2339
+ ];
2340
+ var IGNORED_VALIDATION_ELEMENT_SELECTORS = [
2341
+ "referenceBibliomixed"
2342
+ ];
2343
+
2344
+ // src/schema/shared/ignoredAttributes.ts
2345
+ var IGNORED_ATTRIBUTES = [
2346
+ // Styling & layout
2347
+ "class",
2348
+ "style",
2349
+ // Editor state
2350
+ "contenteditable",
2351
+ "draggable",
2352
+ "data-prevpos",
2353
+ "tabindex",
2354
+ // Browser behaviour
2355
+ "spellcheck",
2356
+ "translate",
2357
+ "lang",
2358
+ "dir",
2359
+ "hidden",
2360
+ "data-gramm"
2361
+ ];
2362
+ var IGNORED_ATTRIBUTES_STARTS_WITH = ["er-", "er_", "drop", "drag"];
2363
+
2364
+ // src/schema/utils/utils.ts
2365
+ var isTrackChangesSchema = (schema) => schema.code === "insertion" || schema.code === "deletion";
2366
+ var isIgnoredAttribute = (attribute) => IGNORED_ATTRIBUTES.includes(attribute) || IGNORED_ATTRIBUTES_STARTS_WITH.some(
2367
+ (startsWith) => attribute.startsWith(startsWith)
2368
+ );
2369
+ var isIgnoredElement = (element) => IGNORED_ELEMENT_SELECTORS.some((selector) => element.matches(selector));
2370
+ var isIgnoredValidation = (code) => IGNORED_VALIDATION_ELEMENT_SELECTORS.includes(code);
2371
+ var findSchemaByCode = (code) => SCHEMAS[code];
2372
+ var findSchemaByElement = (element) => {
2373
+ const schema = Object.values(SCHEMAS).find(
2374
+ (schema2) => schema2.tag == element.tagName && schema2.matchesElement?.(element)
2375
+ );
2376
+ return schema;
2377
+ };
2378
+ var isAttributeRestricted = (attr) => typeof attr !== "string";
2379
+ var getAttributeName = (attribute) => typeof attribute === "string" ? attribute.toLowerCase() : attribute.name.toLowerCase();
2380
+ var findAttributeDefinitionByName = (definitions, name) => {
2381
+ for (const def of definitions) {
2382
+ if (getAttributeName(def) === name.toLowerCase()) {
2383
+ return def;
2384
+ }
2385
+ }
2386
+ return void 0;
2387
+ };
2388
+
2389
+ // src/schema/utils/createElement.ts
2390
+ var createElement = ({
2391
+ schemaCode,
2392
+ attributes
2393
+ }) => {
2394
+ const schema = findSchemaByCode(schemaCode);
2395
+ const element = document.createElement(schema.tag.toLowerCase());
2396
+ for (const [name, value] of Object.entries(attributes)) {
2397
+ if (!value) continue;
2398
+ element.setAttribute(name, String(value));
2399
+ }
2400
+ return element;
2401
+ };
2402
+
2403
+ // src/schema/utils/labelElements.ts
2342
2404
  var ElementLabel = {
2343
2405
  referenceBibliomixed: "Reference Bibliomixed",
2344
2406
  referenceBibliography: "Reference Bibliography",
@@ -2463,106 +2525,13 @@ var ElementLabel = {
2463
2525
  phrase: "Phrase"
2464
2526
  };
2465
2527
 
2466
- // src/schema/shared/ignoredElements.ts
2467
- var IGNORED_ELEMENT_SELECTORS = [
2468
- "span.rhlabel",
2469
- "span.printlabel",
2470
- "span.refIcon",
2471
- "span.missLink",
2472
- "span.ref-drag"
2473
- ];
2474
- var IGNORED_VALIDATION_ELEMENT_SELECTORS = [
2475
- "referenceBibliomixed"
2476
- ];
2477
-
2478
- // src/schema/shared/ignoredAttributes.ts
2479
- var IGNORED_ATTRIBUTES = [
2480
- // Styling & layout
2481
- "class",
2482
- "style",
2483
- // Editor state
2484
- "contenteditable",
2485
- "draggable",
2486
- "data-prevpos",
2487
- "tabindex",
2488
- // Browser behaviour
2489
- "spellcheck",
2490
- "translate",
2491
- "lang",
2492
- "dir",
2493
- "hidden",
2494
- "data-gramm"
2495
- ];
2496
- var IGNORED_ATTRIBUTES_STARTS_WITH = ["er-", "er_", "drop", "drag"];
2497
-
2498
- // src/schema/utils/utils.ts
2499
- var isIgnoredAttribute = (attribute) => IGNORED_ATTRIBUTES.includes(attribute) || IGNORED_ATTRIBUTES_STARTS_WITH.some(
2500
- (startsWith) => attribute.startsWith(startsWith)
2501
- );
2502
- var isIgnoredElement = (element) => IGNORED_ELEMENT_SELECTORS.some((selector) => element.matches(selector));
2503
- var isIgnoredValidation = (code) => IGNORED_VALIDATION_ELEMENT_SELECTORS.includes(code);
2504
- var findSchemaByCode = (code) => SCHEMAS[code];
2505
- var findSchemaByElement = (element) => {
2506
- const tagName = element.tagName.toUpperCase();
2507
- const isInsertion = element.classList.contains("ins");
2508
- const isDeletion = element.classList.contains("del");
2509
- const isQueryComment = element.classList.contains("cmtQurySection");
2510
- const role = element.getAttribute("role");
2511
- if (tagName === SPAN_TAG) {
2512
- if (isQueryComment) {
2513
- return findSchemaByCode("commentQuerySection");
2514
- }
2515
- if (isInsertion) {
2516
- return findSchemaByCode("insertion");
2517
- }
2518
- if (isDeletion) {
2519
- return findSchemaByCode("deletion");
2520
- }
2521
- }
2522
- if (tagName === SECTION_TAG) {
2523
- if (role) {
2524
- if (role.startsWith("H")) {
2525
- return findSchemaByCode("heading");
2526
- }
2527
- if (role === "ch" || role === "bk") {
2528
- return findSchemaByCode("footnoteSection");
2529
- }
2530
- }
2531
- const isFootnoteSectionWithoutRole = element.querySelector(FOOTNOTE_TAG);
2532
- if (isFootnoteSectionWithoutRole) {
2533
- return findSchemaByCode("footnoteSection");
2534
- }
2535
- }
2536
- };
2537
- var isAttributeRestricted = (attr) => typeof attr !== "string";
2538
- var getAttributeName = (attribute) => typeof attribute === "string" ? attribute.toLowerCase() : attribute.name.toLowerCase();
2539
- var findAttributeDefinitionByName = (definitions, name) => {
2540
- for (const def of definitions) {
2541
- if (getAttributeName(def) === name.toLowerCase()) {
2542
- return def;
2543
- }
2544
- }
2545
- return void 0;
2546
- };
2547
-
2548
- // src/schema/utils/createElement.ts
2549
- var createElement = ({
2550
- schemaCode,
2551
- attributes
2552
- }) => {
2553
- const schema = findSchemaByCode(schemaCode);
2554
- if (!schema) {
2555
- throw new Error(`Schema not found for code: ${schemaCode}`);
2556
- }
2557
- const element = document.createElement(schema.tag.toLowerCase());
2558
- for (const [name, value] of Object.entries(attributes)) {
2559
- if (value === void 0) {
2560
- continue;
2561
- }
2562
- element.setAttribute(name, String(value));
2528
+ // src/schema/shared/dependentsForbiddenElements.ts
2529
+ var DEPENDENT_FORBIDDEN_ELEMENTS = [
2530
+ {
2531
+ code: "commentQuerySection",
2532
+ dependentElements: ["query", "comment", "reply", "content"]
2563
2533
  }
2564
- return element;
2565
- };
2534
+ ];
2566
2535
 
2567
2536
  // src/validation/utils/generateValidationIssueId.ts
2568
2537
  var generateValidationIssueId = () => {
@@ -2785,12 +2754,47 @@ var validateElementAgainstSchema = (element, schema) => {
2785
2754
  errors.push(...validateChildren(element, schema));
2786
2755
  return errors;
2787
2756
  };
2788
- var validateChildren = (element, schema) => {
2757
+ var validateRequiredChildren = (element, schema, childElements) => {
2789
2758
  const errors = [];
2759
+ for (const allowedChild of schema.allowedChildrenCodes) {
2760
+ if (!allowedChild.required) {
2761
+ continue;
2762
+ }
2763
+ const hasChild = childElements.some((child) => {
2764
+ const childSchema = findSchemaByElement(child);
2765
+ return childSchema?.code === allowedChild.code;
2766
+ });
2767
+ if (!hasChild) {
2768
+ const requiredChildrenTag = findSchemaByCode(allowedChild.code).tag;
2769
+ addValidationIssue(errors, {
2770
+ store: getStore(element),
2771
+ title: `Missing required child element ${requiredChildrenTag}`,
2772
+ level: "warning",
2773
+ kind: "missing",
2774
+ description: `The child element ${requiredChildrenTag} is required but not present.`
2775
+ });
2776
+ }
2777
+ }
2778
+ return errors;
2779
+ };
2780
+ var getEffectiveChildElements = (element) => {
2781
+ const effectiveChildren = [];
2790
2782
  const childElements = [...element.children].filter(
2791
2783
  (child) => !isIgnoredElement(child)
2792
2784
  );
2793
- const allowedChildren = [...schema.allowedChildrenCodes];
2785
+ for (const child of childElements) {
2786
+ const childSchema = findSchemaByElement(child);
2787
+ if (childSchema && isTrackChangesSchema(childSchema)) {
2788
+ effectiveChildren.push(...getEffectiveChildElements(child));
2789
+ continue;
2790
+ }
2791
+ effectiveChildren.push(child);
2792
+ }
2793
+ return effectiveChildren;
2794
+ };
2795
+ var validateChildren = (element, schema) => {
2796
+ const errors = [];
2797
+ const childElements = getEffectiveChildElements(element);
2794
2798
  if (schema.kind === "atom") {
2795
2799
  return errors;
2796
2800
  }
@@ -2806,7 +2810,7 @@ var validateChildren = (element, schema) => {
2806
2810
  });
2807
2811
  continue;
2808
2812
  }
2809
- const allowedChild = allowedChildren.find(
2813
+ const allowedChild = schema.allowedChildrenCodes.find(
2810
2814
  (candidate) => candidate.code === childSchema.code
2811
2815
  );
2812
2816
  if (!allowedChild) {
@@ -2821,34 +2825,7 @@ var validateChildren = (element, schema) => {
2821
2825
  }
2822
2826
  errors.push(...validateElementAgainstSchema(child, childSchema));
2823
2827
  }
2824
- for (const allowedChild of allowedChildren) {
2825
- if (!allowedChild.required) {
2826
- continue;
2827
- }
2828
- const hasChild = childElements.some((child) => {
2829
- const childSchema = findSchemaByElement(child);
2830
- return childSchema?.code === allowedChild.code;
2831
- });
2832
- if (!hasChild) {
2833
- const requiredChildLabel = ElementLabel[allowedChild.code];
2834
- addValidationIssue(errors, {
2835
- store: getStore(element),
2836
- title: `Missing required child element ${requiredChildLabel}`,
2837
- level: "warning",
2838
- kind: "missing",
2839
- description: `The child element ${requiredChildLabel} is required but not present.`
2840
- });
2841
- }
2842
- }
2843
- if (schema.allowedChildrenCodes.size === 0 && childElements.length > 0) {
2844
- addValidationIssue(errors, {
2845
- store: getStore(element),
2846
- title: "Atom element cannot contain child elements",
2847
- level: "warning",
2848
- kind: "forbidden",
2849
- description: `The element is an atom element and cannot contain child elements.`
2850
- });
2851
- }
2828
+ errors.push(...validateRequiredChildren(element, schema, childElements));
2852
2829
  return errors;
2853
2830
  };
2854
2831
 
@@ -2901,9 +2878,9 @@ var validateElement = (element, root, elementsToLink, linkElements, schemasToVal
2901
2878
  if (schemasToValidateAgainst.includes(schema.code)) {
2902
2879
  errors.push(...validateElementAgainstSchema(element, schema));
2903
2880
  }
2904
- const role = element.getAttribute("role") || "";
2881
+ const role = element.getAttribute("role");
2905
2882
  const linkableRoles = getLinkableRoles();
2906
- if (schema.tag === LINK_SCHEMA.tag && linkableRoles.includes(role) || schema.tag === FOOTNOTE_LINK_SCHEMA.tag) {
2883
+ if (schema.tag === LINK_SCHEMA.tag && role && linkableRoles.includes(role) || schema.tag === FOOTNOTE_LINK_SCHEMA.tag) {
2907
2884
  errors.push(...validateLinkend(element, elementsToLink));
2908
2885
  }
2909
2886
  if (schema.tag === BIBLIOMIXED_SCHEMA.tag) {
@@ -2913,7 +2890,7 @@ var validateElement = (element, root, elementsToLink, linkElements, schemasToVal
2913
2890
  errors.push(...validateFootnoteCue(element, root));
2914
2891
  }
2915
2892
  if (isIgnoredValidation(schema.code)) {
2916
- return [];
2893
+ return errors;
2917
2894
  }
2918
2895
  }
2919
2896
  for (const child of Array.from(element.children)) {
@@ -2950,6 +2927,7 @@ var validateXml = (xml, elementsToLink, linkElements, schemasToValidateAgainst)
2950
2927
  0 && (module.exports = {
2951
2928
  ALIGNMENT_ATTRIBUTE,
2952
2929
  ATOM_SCHEMAS,
2930
+ DEPENDENT_FORBIDDEN_ELEMENTS,
2953
2931
  ELEMENT_SCHEMAS,
2954
2932
  ELE_ID_ATTRIBUTE,
2955
2933
  ElementLabel,
@@ -2988,5 +2966,6 @@ var validateXml = (xml, elementsToLink, linkElements, schemasToValidateAgainst)
2988
2966
  isIgnoredAttribute,
2989
2967
  isIgnoredElement,
2990
2968
  isIgnoredValidation,
2969
+ isTrackChangesSchema,
2991
2970
  validateXml
2992
2971
  });
package/dist/index.mjs CHANGED
@@ -1,22 +1,6 @@
1
1
  // src/schema/utils/createSchema.ts
2
- var createSchema = ({
3
- code,
4
- kind,
5
- tag,
6
- requiredAttributes,
7
- optionalAttributes,
8
- defaultChildCode,
9
- allowedChildrenCodes
10
- }) => {
11
- return {
12
- code,
13
- kind,
14
- tag,
15
- requiredAttributes,
16
- optionalAttributes,
17
- defaultChildCode,
18
- allowedChildrenCodes: new Set(allowedChildrenCodes)
19
- };
2
+ var createSchema = (params) => {
3
+ return params;
20
4
  };
21
5
 
22
6
  // src/schema/shared/globalAttributes.ts
@@ -117,6 +101,7 @@ var COMMENT_QUERY_SECTION_SCHEMA = createSchema({
117
101
  kind: "atom",
118
102
  tag: SPAN_TAG,
119
103
  code: "commentQuerySection",
104
+ matchesElement: (element) => element.classList.contains("cmtQurySection"),
120
105
  requiredAttributes: [...ID_ATTRS, "id"],
121
106
  optionalAttributes: [...TRACK_CHANGES_ATTRS, "title"],
122
107
  allowedChildrenCodes: [...ATOM_CODES_ALLOWED_CHILDREN]
@@ -136,6 +121,7 @@ var DELETION_SCHEMA = createSchema({
136
121
  code: "deletion",
137
122
  kind: "atom",
138
123
  tag: SPAN_TAG,
124
+ matchesElement: (element) => element.classList.contains("del"),
139
125
  requiredAttributes: [...TRACK_CHANGES_ATTRS, ...ID_ATTRS],
140
126
  optionalAttributes: [],
141
127
  allowedChildrenCodes: [
@@ -186,6 +172,7 @@ var INSERTION_SCHEMA = createSchema({
186
172
  code: "insertion",
187
173
  kind: "atom",
188
174
  tag: SPAN_TAG,
175
+ matchesElement: (element) => element.classList.contains("ins"),
189
176
  requiredAttributes: [...TRACK_CHANGES_ATTRS, ...ID_ATTRS],
190
177
  optionalAttributes: [],
191
178
  allowedChildrenCodes: [
@@ -1907,15 +1894,21 @@ var EPIGRAPH_SCHEMA = createSchema({
1907
1894
  });
1908
1895
 
1909
1896
  // src/schema/elementSchemas/elements/footnoteSection.ts
1897
+ var FOOTNOTE_SECTION_ROLES = ["ch", "bk"];
1910
1898
  var FOOTNOTE_SECTION_SCHEMA = createSchema({
1911
1899
  code: "footnoteSection",
1912
1900
  kind: "element",
1913
1901
  tag: SECTION_TAG,
1902
+ matchesElement: (element) => {
1903
+ const role = element.getAttribute("role");
1904
+ if (role && FOOTNOTE_SECTION_ROLES.includes(role)) return true;
1905
+ return element.querySelector(FOOTNOTE_TAG) !== null;
1906
+ },
1914
1907
  requiredAttributes: [
1915
1908
  ...ID_ATTRS,
1916
1909
  {
1917
1910
  name: "role",
1918
- values: ["ch", "bk"],
1911
+ values: FOOTNOTE_SECTION_ROLES,
1919
1912
  defaultValue: "ch"
1920
1913
  }
1921
1914
  ],
@@ -1928,16 +1921,22 @@ var FOOTNOTE_SECTION_SCHEMA = createSchema({
1928
1921
  });
1929
1922
 
1930
1923
  // src/schema/elementSchemas/elements/heading.ts
1924
+ var HEADING_ROLES = ["H1", "H2", "H3", "H4", "H5", "H6", "vignette_group"];
1931
1925
  var HEADING_SCHEMA = createSchema({
1932
1926
  code: "heading",
1933
1927
  kind: "element",
1934
1928
  tag: SECTION_TAG,
1929
+ matchesElement: (element) => {
1930
+ const role = element.getAttribute("role");
1931
+ if (!role) return false;
1932
+ return HEADING_ROLES.includes(role);
1933
+ },
1935
1934
  requiredAttributes: [
1936
1935
  ...ID_ATTRS,
1937
1936
  "xmlid",
1938
1937
  {
1939
1938
  name: "role",
1940
- values: ["H1", "H2", "H3", "H4", "H5", "H6", "vignette_group"],
1939
+ values: HEADING_ROLES,
1941
1940
  defaultValue: "H1"
1942
1941
  }
1943
1942
  ],
@@ -2004,17 +2003,7 @@ var MATHPHRASE_SCHEMA = createSchema({
2004
2003
  tag: MATHPHRASE_TAG,
2005
2004
  requiredAttributes: [ELE_ID_ATTRIBUTE],
2006
2005
  optionalAttributes: [],
2007
- allowedChildrenCodes: [
2008
- { code: MATH_SCHEMA.code, required: true },
2009
- {
2010
- code: INSERTION_SCHEMA.code,
2011
- required: false
2012
- },
2013
- {
2014
- code: DELETION_SCHEMA.code,
2015
- required: false
2016
- }
2017
- ]
2006
+ allowedChildrenCodes: [{ code: MATH_SCHEMA.code, required: true }]
2018
2007
  });
2019
2008
 
2020
2009
  // src/schema/elementSchemas/elements/reference/bibliodiv.ts
@@ -2272,7 +2261,78 @@ var SCHEMAS = {
2272
2261
  ...INLINE_ELEMENT_SCHEMAS
2273
2262
  };
2274
2263
 
2275
- // src/schema/schema.types.ts
2264
+ // src/schema/shared/ignoredElements.ts
2265
+ var IGNORED_ELEMENT_SELECTORS = [
2266
+ "span.rhlabel",
2267
+ "span.printlabel",
2268
+ "span.refIcon",
2269
+ "span.missLink",
2270
+ "span.ref-drag"
2271
+ ];
2272
+ var IGNORED_VALIDATION_ELEMENT_SELECTORS = [
2273
+ "referenceBibliomixed"
2274
+ ];
2275
+
2276
+ // src/schema/shared/ignoredAttributes.ts
2277
+ var IGNORED_ATTRIBUTES = [
2278
+ // Styling & layout
2279
+ "class",
2280
+ "style",
2281
+ // Editor state
2282
+ "contenteditable",
2283
+ "draggable",
2284
+ "data-prevpos",
2285
+ "tabindex",
2286
+ // Browser behaviour
2287
+ "spellcheck",
2288
+ "translate",
2289
+ "lang",
2290
+ "dir",
2291
+ "hidden",
2292
+ "data-gramm"
2293
+ ];
2294
+ var IGNORED_ATTRIBUTES_STARTS_WITH = ["er-", "er_", "drop", "drag"];
2295
+
2296
+ // src/schema/utils/utils.ts
2297
+ var isTrackChangesSchema = (schema) => schema.code === "insertion" || schema.code === "deletion";
2298
+ var isIgnoredAttribute = (attribute) => IGNORED_ATTRIBUTES.includes(attribute) || IGNORED_ATTRIBUTES_STARTS_WITH.some(
2299
+ (startsWith) => attribute.startsWith(startsWith)
2300
+ );
2301
+ var isIgnoredElement = (element) => IGNORED_ELEMENT_SELECTORS.some((selector) => element.matches(selector));
2302
+ var isIgnoredValidation = (code) => IGNORED_VALIDATION_ELEMENT_SELECTORS.includes(code);
2303
+ var findSchemaByCode = (code) => SCHEMAS[code];
2304
+ var findSchemaByElement = (element) => {
2305
+ const schema = Object.values(SCHEMAS).find(
2306
+ (schema2) => schema2.tag == element.tagName && schema2.matchesElement?.(element)
2307
+ );
2308
+ return schema;
2309
+ };
2310
+ var isAttributeRestricted = (attr) => typeof attr !== "string";
2311
+ var getAttributeName = (attribute) => typeof attribute === "string" ? attribute.toLowerCase() : attribute.name.toLowerCase();
2312
+ var findAttributeDefinitionByName = (definitions, name) => {
2313
+ for (const def of definitions) {
2314
+ if (getAttributeName(def) === name.toLowerCase()) {
2315
+ return def;
2316
+ }
2317
+ }
2318
+ return void 0;
2319
+ };
2320
+
2321
+ // src/schema/utils/createElement.ts
2322
+ var createElement = ({
2323
+ schemaCode,
2324
+ attributes
2325
+ }) => {
2326
+ const schema = findSchemaByCode(schemaCode);
2327
+ const element = document.createElement(schema.tag.toLowerCase());
2328
+ for (const [name, value] of Object.entries(attributes)) {
2329
+ if (!value) continue;
2330
+ element.setAttribute(name, String(value));
2331
+ }
2332
+ return element;
2333
+ };
2334
+
2335
+ // src/schema/utils/labelElements.ts
2276
2336
  var ElementLabel = {
2277
2337
  referenceBibliomixed: "Reference Bibliomixed",
2278
2338
  referenceBibliography: "Reference Bibliography",
@@ -2397,106 +2457,13 @@ var ElementLabel = {
2397
2457
  phrase: "Phrase"
2398
2458
  };
2399
2459
 
2400
- // src/schema/shared/ignoredElements.ts
2401
- var IGNORED_ELEMENT_SELECTORS = [
2402
- "span.rhlabel",
2403
- "span.printlabel",
2404
- "span.refIcon",
2405
- "span.missLink",
2406
- "span.ref-drag"
2407
- ];
2408
- var IGNORED_VALIDATION_ELEMENT_SELECTORS = [
2409
- "referenceBibliomixed"
2410
- ];
2411
-
2412
- // src/schema/shared/ignoredAttributes.ts
2413
- var IGNORED_ATTRIBUTES = [
2414
- // Styling & layout
2415
- "class",
2416
- "style",
2417
- // Editor state
2418
- "contenteditable",
2419
- "draggable",
2420
- "data-prevpos",
2421
- "tabindex",
2422
- // Browser behaviour
2423
- "spellcheck",
2424
- "translate",
2425
- "lang",
2426
- "dir",
2427
- "hidden",
2428
- "data-gramm"
2429
- ];
2430
- var IGNORED_ATTRIBUTES_STARTS_WITH = ["er-", "er_", "drop", "drag"];
2431
-
2432
- // src/schema/utils/utils.ts
2433
- var isIgnoredAttribute = (attribute) => IGNORED_ATTRIBUTES.includes(attribute) || IGNORED_ATTRIBUTES_STARTS_WITH.some(
2434
- (startsWith) => attribute.startsWith(startsWith)
2435
- );
2436
- var isIgnoredElement = (element) => IGNORED_ELEMENT_SELECTORS.some((selector) => element.matches(selector));
2437
- var isIgnoredValidation = (code) => IGNORED_VALIDATION_ELEMENT_SELECTORS.includes(code);
2438
- var findSchemaByCode = (code) => SCHEMAS[code];
2439
- var findSchemaByElement = (element) => {
2440
- const tagName = element.tagName.toUpperCase();
2441
- const isInsertion = element.classList.contains("ins");
2442
- const isDeletion = element.classList.contains("del");
2443
- const isQueryComment = element.classList.contains("cmtQurySection");
2444
- const role = element.getAttribute("role");
2445
- if (tagName === SPAN_TAG) {
2446
- if (isQueryComment) {
2447
- return findSchemaByCode("commentQuerySection");
2448
- }
2449
- if (isInsertion) {
2450
- return findSchemaByCode("insertion");
2451
- }
2452
- if (isDeletion) {
2453
- return findSchemaByCode("deletion");
2454
- }
2455
- }
2456
- if (tagName === SECTION_TAG) {
2457
- if (role) {
2458
- if (role.startsWith("H")) {
2459
- return findSchemaByCode("heading");
2460
- }
2461
- if (role === "ch" || role === "bk") {
2462
- return findSchemaByCode("footnoteSection");
2463
- }
2464
- }
2465
- const isFootnoteSectionWithoutRole = element.querySelector(FOOTNOTE_TAG);
2466
- if (isFootnoteSectionWithoutRole) {
2467
- return findSchemaByCode("footnoteSection");
2468
- }
2469
- }
2470
- };
2471
- var isAttributeRestricted = (attr) => typeof attr !== "string";
2472
- var getAttributeName = (attribute) => typeof attribute === "string" ? attribute.toLowerCase() : attribute.name.toLowerCase();
2473
- var findAttributeDefinitionByName = (definitions, name) => {
2474
- for (const def of definitions) {
2475
- if (getAttributeName(def) === name.toLowerCase()) {
2476
- return def;
2477
- }
2478
- }
2479
- return void 0;
2480
- };
2481
-
2482
- // src/schema/utils/createElement.ts
2483
- var createElement = ({
2484
- schemaCode,
2485
- attributes
2486
- }) => {
2487
- const schema = findSchemaByCode(schemaCode);
2488
- if (!schema) {
2489
- throw new Error(`Schema not found for code: ${schemaCode}`);
2490
- }
2491
- const element = document.createElement(schema.tag.toLowerCase());
2492
- for (const [name, value] of Object.entries(attributes)) {
2493
- if (value === void 0) {
2494
- continue;
2495
- }
2496
- element.setAttribute(name, String(value));
2460
+ // src/schema/shared/dependentsForbiddenElements.ts
2461
+ var DEPENDENT_FORBIDDEN_ELEMENTS = [
2462
+ {
2463
+ code: "commentQuerySection",
2464
+ dependentElements: ["query", "comment", "reply", "content"]
2497
2465
  }
2498
- return element;
2499
- };
2466
+ ];
2500
2467
 
2501
2468
  // src/validation/utils/generateValidationIssueId.ts
2502
2469
  var generateValidationIssueId = () => {
@@ -2719,12 +2686,47 @@ var validateElementAgainstSchema = (element, schema) => {
2719
2686
  errors.push(...validateChildren(element, schema));
2720
2687
  return errors;
2721
2688
  };
2722
- var validateChildren = (element, schema) => {
2689
+ var validateRequiredChildren = (element, schema, childElements) => {
2723
2690
  const errors = [];
2691
+ for (const allowedChild of schema.allowedChildrenCodes) {
2692
+ if (!allowedChild.required) {
2693
+ continue;
2694
+ }
2695
+ const hasChild = childElements.some((child) => {
2696
+ const childSchema = findSchemaByElement(child);
2697
+ return childSchema?.code === allowedChild.code;
2698
+ });
2699
+ if (!hasChild) {
2700
+ const requiredChildrenTag = findSchemaByCode(allowedChild.code).tag;
2701
+ addValidationIssue(errors, {
2702
+ store: getStore(element),
2703
+ title: `Missing required child element ${requiredChildrenTag}`,
2704
+ level: "warning",
2705
+ kind: "missing",
2706
+ description: `The child element ${requiredChildrenTag} is required but not present.`
2707
+ });
2708
+ }
2709
+ }
2710
+ return errors;
2711
+ };
2712
+ var getEffectiveChildElements = (element) => {
2713
+ const effectiveChildren = [];
2724
2714
  const childElements = [...element.children].filter(
2725
2715
  (child) => !isIgnoredElement(child)
2726
2716
  );
2727
- const allowedChildren = [...schema.allowedChildrenCodes];
2717
+ for (const child of childElements) {
2718
+ const childSchema = findSchemaByElement(child);
2719
+ if (childSchema && isTrackChangesSchema(childSchema)) {
2720
+ effectiveChildren.push(...getEffectiveChildElements(child));
2721
+ continue;
2722
+ }
2723
+ effectiveChildren.push(child);
2724
+ }
2725
+ return effectiveChildren;
2726
+ };
2727
+ var validateChildren = (element, schema) => {
2728
+ const errors = [];
2729
+ const childElements = getEffectiveChildElements(element);
2728
2730
  if (schema.kind === "atom") {
2729
2731
  return errors;
2730
2732
  }
@@ -2740,7 +2742,7 @@ var validateChildren = (element, schema) => {
2740
2742
  });
2741
2743
  continue;
2742
2744
  }
2743
- const allowedChild = allowedChildren.find(
2745
+ const allowedChild = schema.allowedChildrenCodes.find(
2744
2746
  (candidate) => candidate.code === childSchema.code
2745
2747
  );
2746
2748
  if (!allowedChild) {
@@ -2755,34 +2757,7 @@ var validateChildren = (element, schema) => {
2755
2757
  }
2756
2758
  errors.push(...validateElementAgainstSchema(child, childSchema));
2757
2759
  }
2758
- for (const allowedChild of allowedChildren) {
2759
- if (!allowedChild.required) {
2760
- continue;
2761
- }
2762
- const hasChild = childElements.some((child) => {
2763
- const childSchema = findSchemaByElement(child);
2764
- return childSchema?.code === allowedChild.code;
2765
- });
2766
- if (!hasChild) {
2767
- const requiredChildLabel = ElementLabel[allowedChild.code];
2768
- addValidationIssue(errors, {
2769
- store: getStore(element),
2770
- title: `Missing required child element ${requiredChildLabel}`,
2771
- level: "warning",
2772
- kind: "missing",
2773
- description: `The child element ${requiredChildLabel} is required but not present.`
2774
- });
2775
- }
2776
- }
2777
- if (schema.allowedChildrenCodes.size === 0 && childElements.length > 0) {
2778
- addValidationIssue(errors, {
2779
- store: getStore(element),
2780
- title: "Atom element cannot contain child elements",
2781
- level: "warning",
2782
- kind: "forbidden",
2783
- description: `The element is an atom element and cannot contain child elements.`
2784
- });
2785
- }
2760
+ errors.push(...validateRequiredChildren(element, schema, childElements));
2786
2761
  return errors;
2787
2762
  };
2788
2763
 
@@ -2835,9 +2810,9 @@ var validateElement = (element, root, elementsToLink, linkElements, schemasToVal
2835
2810
  if (schemasToValidateAgainst.includes(schema.code)) {
2836
2811
  errors.push(...validateElementAgainstSchema(element, schema));
2837
2812
  }
2838
- const role = element.getAttribute("role") || "";
2813
+ const role = element.getAttribute("role");
2839
2814
  const linkableRoles = getLinkableRoles();
2840
- if (schema.tag === LINK_SCHEMA.tag && linkableRoles.includes(role) || schema.tag === FOOTNOTE_LINK_SCHEMA.tag) {
2815
+ if (schema.tag === LINK_SCHEMA.tag && role && linkableRoles.includes(role) || schema.tag === FOOTNOTE_LINK_SCHEMA.tag) {
2841
2816
  errors.push(...validateLinkend(element, elementsToLink));
2842
2817
  }
2843
2818
  if (schema.tag === BIBLIOMIXED_SCHEMA.tag) {
@@ -2847,7 +2822,7 @@ var validateElement = (element, root, elementsToLink, linkElements, schemasToVal
2847
2822
  errors.push(...validateFootnoteCue(element, root));
2848
2823
  }
2849
2824
  if (isIgnoredValidation(schema.code)) {
2850
- return [];
2825
+ return errors;
2851
2826
  }
2852
2827
  }
2853
2828
  for (const child of Array.from(element.children)) {
@@ -2883,6 +2858,7 @@ var validateXml = (xml, elementsToLink, linkElements, schemasToValidateAgainst)
2883
2858
  export {
2884
2859
  ALIGNMENT_ATTRIBUTE,
2885
2860
  ATOM_SCHEMAS,
2861
+ DEPENDENT_FORBIDDEN_ELEMENTS,
2886
2862
  ELEMENT_SCHEMAS,
2887
2863
  ELE_ID_ATTRIBUTE,
2888
2864
  ElementLabel,
@@ -2921,5 +2897,6 @@ export {
2921
2897
  isIgnoredAttribute,
2922
2898
  isIgnoredElement,
2923
2899
  isIgnoredValidation,
2900
+ isTrackChangesSchema,
2924
2901
  validateXml
2925
2902
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pro-editor-schema",
3
- "version": "0.1.199",
3
+ "version": "0.2.0",
4
4
  "description": "Pro Editor XML schemas",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",