@plurnk/plurnk-mimetypes-application-xml 1.26.0 → 1.28.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/dist/ApplicationXml.d.ts.map +1 -1
- package/dist/ApplicationXml.js +49 -187
- package/dist/ApplicationXml.js.map +1 -1
- package/dist/XmlSource.d.ts +9 -0
- package/dist/XmlSource.d.ts.map +1 -0
- package/dist/XmlSource.js +87 -0
- package/dist/XmlSource.js.map +1 -0
- package/package.json +5 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ApplicationXml.d.ts","sourceRoot":"","sources":["../src/ApplicationXml.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,WAAW,
|
|
1
|
+
{"version":3,"file":"ApplicationXml.d.ts","sourceRoot":"","sources":["../src/ApplicationXml.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,WAAW,EAMd,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,YAAY,EAAE,UAAU,EAAc,MAAM,0BAA0B,CAAC;AAKjH,MAAM,CAAC,OAAO,OAAO,cAAe,SAAQ,WAAW;IAC1C,UAAU,CAAC,OAAO,EAAE,cAAc,GAAG,UAAU,EAAE,CAmBzD;IAEQ,QAAQ,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAKlD;IAEc,KAAK,CAAC,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAqB3H;CACJ"}
|
package/dist/ApplicationXml.js
CHANGED
|
@@ -1,213 +1,75 @@
|
|
|
1
|
-
import { BaseHandler, InvalidExpressionError, QueryParseFailureError,
|
|
2
|
-
import { DOMParser } from "@xmldom/xmldom";
|
|
1
|
+
import { BaseHandler, InvalidExpressionError, QueryParseFailureError, queryJsonpathObject, projectDomToJson, serializeXpathNode, } from "@plurnk/plurnk-mimetypes";
|
|
3
2
|
import * as xpath from "xpath";
|
|
4
|
-
|
|
5
|
-
//
|
|
6
|
-
// Symbols (extractRaw):
|
|
7
|
-
// - the root element → module, with its tag name
|
|
8
|
-
// - direct children of the root that carry an `id` or `name` attribute →
|
|
9
|
-
// field, named by the attribute value (preferring id over name)
|
|
10
|
-
// - direct children without identifiers → field, named by tag name
|
|
11
|
-
//
|
|
12
|
-
// Deep-json ({§mimetype-channel-architecture}):
|
|
13
|
-
// - { type: "document", line, endLine, children: [<root element tree>] }
|
|
14
|
-
// - each element: { type: tagName, attrs: {...}, children: [...] }
|
|
15
|
-
// - text content collapses to a `text` field when it's the only child;
|
|
16
|
-
// mixed content keeps text nodes as { type: "#text", text } siblings
|
|
17
|
-
//
|
|
18
|
-
// Query (query, xpath dialect overridden):
|
|
19
|
-
// - xpath dispatches against the parsed XML DOM directly (the xpath package
|
|
20
|
-
// gives us a real XPath 1.0 engine over xmldom's DOM)
|
|
21
|
-
// - jsonpath inherits BaseHandler's default — runs against deepJson via the
|
|
22
|
-
// framework's pipeline
|
|
23
|
-
// - regex/glob inherit the BaseHandler defaults (against raw text)
|
|
24
|
-
const TEXT_NODE = 3;
|
|
25
|
-
const ELEMENT_NODE = 1;
|
|
26
|
-
const CDATA_SECTION_NODE = 4;
|
|
3
|
+
import XmlSource from "./XmlSource.js";
|
|
27
4
|
export default class ApplicationXml extends BaseHandler {
|
|
28
5
|
extractRaw(content) {
|
|
29
|
-
const text =
|
|
30
|
-
|
|
31
|
-
: new TextDecoder("utf-8").decode(content);
|
|
32
|
-
const doc = parseXmlSilent(text);
|
|
33
|
-
if (doc === null)
|
|
6
|
+
const text = textOf(content);
|
|
7
|
+
if (text.length === 0)
|
|
34
8
|
return [];
|
|
35
|
-
const
|
|
9
|
+
const source = new XmlSource(text);
|
|
10
|
+
const root = source.document.documentElement;
|
|
36
11
|
if (root === null)
|
|
37
12
|
return [];
|
|
38
|
-
const symbols = [
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
13
|
+
const symbols = [];
|
|
14
|
+
const append = (element, name, kind, container) => {
|
|
15
|
+
const region = source.region(element);
|
|
16
|
+
if (region === undefined)
|
|
17
|
+
return;
|
|
18
|
+
symbols.push({ name, kind, ...span(region), ...(container === undefined ? {} : { container }) });
|
|
19
|
+
};
|
|
20
|
+
append(root, root.tagName, "module");
|
|
21
|
+
for (let child = root.firstChild; child !== null; child = child.nextSibling) {
|
|
22
|
+
if (child.nodeType !== 1)
|
|
46
23
|
continue;
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
const nameAttr = el.getAttribute?.("name");
|
|
50
|
-
const name = (idAttr && idAttr.length > 0)
|
|
51
|
-
? idAttr
|
|
52
|
-
: ((nameAttr && nameAttr.length > 0) ? nameAttr : el.tagName);
|
|
53
|
-
symbols.push({ name, kind: "field", line: lineOf(el) ?? 1, endLine: spanEnd(el), container: root.tagName });
|
|
24
|
+
const element = child;
|
|
25
|
+
append(element, element.getAttribute("id") || element.getAttribute("name") || element.tagName, "field", root.tagName);
|
|
54
26
|
}
|
|
55
27
|
return symbols;
|
|
56
28
|
}
|
|
57
|
-
// Deep-channel ({§mimetype-channel-architecture}). DOM tree with attrs
|
|
58
|
-
// convention so xpath like //*[@id='x'] and //channel/item work against the
|
|
59
|
-
// projected deep-xml.
|
|
60
29
|
deepJson(content) {
|
|
61
|
-
const text =
|
|
62
|
-
|
|
63
|
-
: new TextDecoder("utf-8").decode(content);
|
|
64
|
-
const doc = parseXmlSilent(text);
|
|
65
|
-
if (doc === null)
|
|
66
|
-
return null;
|
|
67
|
-
const root = doc.documentElement;
|
|
68
|
-
if (root === null)
|
|
30
|
+
const text = textOf(content);
|
|
31
|
+
if (text.length === 0)
|
|
69
32
|
return null;
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
line: 1,
|
|
73
|
-
endLine: spanEnd(root),
|
|
74
|
-
children: [elementToDeep(root)],
|
|
75
|
-
};
|
|
33
|
+
const source = new XmlSource(text);
|
|
34
|
+
return projectDomToJson(source.document, (node) => source.region(node)).value;
|
|
76
35
|
}
|
|
77
|
-
// Override xpath dispatch. The xpath package gives us a real XPath 1.0
|
|
78
|
-
// engine over xmldom's DOM. Line numbers default to 1 because xmldom
|
|
79
|
-
// doesn't track source positions.
|
|
80
36
|
async query(content, dialect, pattern, flags) {
|
|
81
|
-
if (dialect
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
try {
|
|
87
|
-
doc = new DOMParser().parseFromString(text, "text/xml");
|
|
88
|
-
}
|
|
89
|
-
catch (cause) {
|
|
90
|
-
throw new QueryParseFailureError({ mimetype: this.mimetype, cause });
|
|
91
|
-
}
|
|
92
|
-
let result;
|
|
93
|
-
try {
|
|
94
|
-
result = xpath.select(pattern, doc);
|
|
95
|
-
}
|
|
96
|
-
catch (cause) {
|
|
97
|
-
throw new InvalidExpressionError({ dialect: "xpath", expression: pattern, cause });
|
|
98
|
-
}
|
|
99
|
-
return shapeXpathResult(pattern, result, text);
|
|
37
|
+
if (dialect !== "xpath" && dialect !== "jsonpath")
|
|
38
|
+
return super.query(content, dialect, pattern, flags);
|
|
39
|
+
let source;
|
|
40
|
+
try {
|
|
41
|
+
source = new XmlSource(textOf(content));
|
|
100
42
|
}
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
}
|
|
104
|
-
function parseXmlSilent(text) {
|
|
105
|
-
if (text.length === 0)
|
|
106
|
-
return null;
|
|
107
|
-
// xmldom 0.9's errorHandler is a single function (level, msg, context).
|
|
108
|
-
// No-op silences both warnings and parse errors for our extraction path —
|
|
109
|
-
// we want a best-effort parse, not a strict gate. Anything genuinely
|
|
110
|
-
// unparseable returns a document with no documentElement and we route
|
|
111
|
-
// that through the "no symbols" path upstream.
|
|
112
|
-
return new DOMParser({
|
|
113
|
-
errorHandler: () => undefined,
|
|
114
|
-
}).parseFromString(text, "text/xml");
|
|
115
|
-
}
|
|
116
|
-
// 1-indexed source line of an xmldom node (start), or undefined.
|
|
117
|
-
function lineOf(node) {
|
|
118
|
-
return typeof node.lineNumber === "number" && node.lineNumber > 0 ? node.lineNumber : undefined;
|
|
119
|
-
}
|
|
120
|
-
// An element's source-line span end = start line + newlines in its serialized
|
|
121
|
-
// form (covers the closing tag). xmldom gives per-node start lines but no end;
|
|
122
|
-
// the serialized extent is accurate and parser-agnostic, so jsonpath (deepJson)
|
|
123
|
-
// and xpath agree on the same element. Never a faked 1.
|
|
124
|
-
function spanEnd(el) {
|
|
125
|
-
const start = lineOf(el) ?? 1;
|
|
126
|
-
const serialized = el.toString();
|
|
127
|
-
return start + (serialized.match(/\n/g)?.length ?? 0);
|
|
128
|
-
}
|
|
129
|
-
function elementToDeep(el) {
|
|
130
|
-
const line = lineOf(el) ?? 1;
|
|
131
|
-
const node = {
|
|
132
|
-
type: el.tagName,
|
|
133
|
-
line,
|
|
134
|
-
endLine: spanEnd(el),
|
|
135
|
-
};
|
|
136
|
-
if (el.attributes && el.attributes.length > 0) {
|
|
137
|
-
const attrs = {};
|
|
138
|
-
for (let i = 0; i < el.attributes.length; i += 1) {
|
|
139
|
-
const a = el.attributes.item(i);
|
|
140
|
-
if (a)
|
|
141
|
-
attrs[a.name] = a.value;
|
|
43
|
+
catch (cause) {
|
|
44
|
+
throw new QueryParseFailureError({ mimetype: this.mimetype, cause });
|
|
142
45
|
}
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
for (let i = 0; i < el.childNodes.length; i += 1) {
|
|
147
|
-
const child = el.childNodes.item(i);
|
|
148
|
-
if (child === null)
|
|
149
|
-
continue;
|
|
150
|
-
if (child.nodeType === TEXT_NODE || child.nodeType === CDATA_SECTION_NODE) {
|
|
151
|
-
const value = child.data;
|
|
152
|
-
if (value.length > 0)
|
|
153
|
-
children.push({ type: "#text", text: value });
|
|
154
|
-
continue;
|
|
46
|
+
if (dialect === "jsonpath") {
|
|
47
|
+
const { value, regions } = projectDomToJson(source.document, (node) => source.region(node));
|
|
48
|
+
return queryJsonpathObject(value, pattern, (pointer) => regions.get(pointer));
|
|
155
49
|
}
|
|
156
|
-
|
|
157
|
-
|
|
50
|
+
let result;
|
|
51
|
+
try {
|
|
52
|
+
result = xpath.select(pattern, source.document);
|
|
158
53
|
}
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
}
|
|
167
|
-
else if (children.length > 0) {
|
|
168
|
-
node.children = children;
|
|
169
|
-
}
|
|
170
|
-
return node;
|
|
171
|
-
}
|
|
172
|
-
// Translate xpath.select results per {§mimetype-query}, with real source-line
|
|
173
|
-
// spans from @xmldom/xmldom's node lineNumber.
|
|
174
|
-
function shapeXpathResult(pattern, result, content) {
|
|
175
|
-
if (Array.isArray(result)) {
|
|
176
|
-
return result.map((node, i) => {
|
|
177
|
-
const line = nodeLine(node);
|
|
178
|
-
// Real span (consistent with deepJson): element matches end at their
|
|
179
|
-
// last descendant's line; non-elements span a single line.
|
|
180
|
-
const endLine = line !== undefined && node.nodeType === ELEMENT_NODE
|
|
181
|
-
? spanEnd(node)
|
|
182
|
-
: line;
|
|
183
|
-
const regions = line === undefined
|
|
184
|
-
? undefined
|
|
185
|
-
: regionsForLineSpans(content, [{ line, endLine: endLine ?? line }]);
|
|
54
|
+
catch (cause) {
|
|
55
|
+
throw new InvalidExpressionError({ dialect, expression: pattern, cause });
|
|
56
|
+
}
|
|
57
|
+
if (!Array.isArray(result))
|
|
58
|
+
return result === null || result === undefined ? [] : [{ matched: String(result), matching: pattern }];
|
|
59
|
+
return result.map((node, index) => {
|
|
60
|
+
const region = source.region(node);
|
|
186
61
|
return {
|
|
187
62
|
matched: serializeXpathNode(node),
|
|
188
|
-
matching: result.length > 1 ?
|
|
189
|
-
...(
|
|
63
|
+
matching: result.length > 1 ? "(" + pattern + ")[" + (index + 1) + "]" : pattern,
|
|
64
|
+
...(region === undefined ? {} : { regions: [region] }),
|
|
190
65
|
};
|
|
191
66
|
});
|
|
192
67
|
}
|
|
193
|
-
if (result === null || result === undefined)
|
|
194
|
-
return [];
|
|
195
|
-
// Computed scalar (string()/count()/boolean()): no source node → no `lines`
|
|
196
|
-
// under {§mimetype-query}. The value is reported; the location is honestly absent.
|
|
197
|
-
return [{
|
|
198
|
-
matched: typeof result === "string" ? result : String(result),
|
|
199
|
-
matching: pattern,
|
|
200
|
-
}];
|
|
201
68
|
}
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
return direct;
|
|
208
|
-
const owner = node.ownerElement
|
|
209
|
-
?? node.parentNode ?? null;
|
|
210
|
-
const ln = owner?.lineNumber;
|
|
211
|
-
return typeof ln === "number" && ln > 0 ? ln : undefined;
|
|
69
|
+
function textOf(content) {
|
|
70
|
+
return typeof content === "string" ? content : new TextDecoder("utf-8").decode(content);
|
|
71
|
+
}
|
|
72
|
+
function span(region) {
|
|
73
|
+
return { line: region.startLine, column: region.startColumn, endLine: region.endLine, endColumn: region.endColumn };
|
|
212
74
|
}
|
|
213
75
|
//# sourceMappingURL=ApplicationXml.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ApplicationXml.js","sourceRoot":"","sources":["../src/ApplicationXml.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,WAAW,EACX,sBAAsB,EACtB,sBAAsB,EACtB,mBAAmB,EACnB,kBAAkB,GACrB,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"ApplicationXml.js","sourceRoot":"","sources":["../src/ApplicationXml.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type Node } from "@xmldom/xmldom";
|
|
2
|
+
import { type TextRegion } from "@plurnk/plurnk-mimetypes";
|
|
3
|
+
export default class XmlSource {
|
|
4
|
+
#private;
|
|
5
|
+
readonly document: import("@xmldom/xmldom").Document;
|
|
6
|
+
constructor(content: string);
|
|
7
|
+
region(node: Node): TextRegion | undefined;
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=XmlSource.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"XmlSource.d.ts","sourceRoot":"","sources":["../src/XmlSource.ts"],"names":[],"mappings":"AACA,OAAO,EAAa,KAAK,IAAI,EAAE,MAAM,gBAAgB,CAAC;AACtD,OAAO,EAAmB,KAAK,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAI5E,MAAM,CAAC,OAAO,OAAO,SAAS;;IAC1B,QAAQ,CAAC,QAAQ,oCAAC;IAMlB,YAAY,OAAO,EAAE,MAAM,EAqC1B;IAED,MAAM,CAAC,IAAI,EAAE,IAAI,GAAG,UAAU,GAAG,SAAS,CA2BzC;CACJ"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { parser } from "@lezer/xml";
|
|
2
|
+
import { DOMParser } from "@xmldom/xmldom";
|
|
3
|
+
import { TextCoordinates } from "@plurnk/plurnk-mimetypes";
|
|
4
|
+
// {§mimetype-query} — XPath owns node identity; the concrete syntax tree owns
|
|
5
|
+
// source extents. DOM serialization cannot recover lexical quotes or entities.
|
|
6
|
+
export default class XmlSource {
|
|
7
|
+
document;
|
|
8
|
+
#tree;
|
|
9
|
+
#coordinates;
|
|
10
|
+
#lineStarts;
|
|
11
|
+
#length;
|
|
12
|
+
constructor(content) {
|
|
13
|
+
this.document = new DOMParser({ onError: (level, message) => {
|
|
14
|
+
if (level !== "warning")
|
|
15
|
+
throw new SyntaxError(message);
|
|
16
|
+
} }).parseFromString(content, "text/xml");
|
|
17
|
+
this.#tree = parser.parse(content);
|
|
18
|
+
this.#coordinates = new TextCoordinates(content);
|
|
19
|
+
this.#length = content.length;
|
|
20
|
+
// xmldom's XML line normalization; its columns count UTF-16 code units.
|
|
21
|
+
// Convert its locator back to original offsets before applying Plurnk coordinates.
|
|
22
|
+
this.#lineStarts = [0, ...[...content.matchAll(/\r[\n\u0085]|[\r\n\u0085\u2028\u2029]/g)].map((match) => match.index + match[0].length)];
|
|
23
|
+
// XPath 1.0 §5.7 has logical text nodes, not separate CDATA nodes.
|
|
24
|
+
const pending = [this.document];
|
|
25
|
+
while (pending.length > 0) {
|
|
26
|
+
const parent = pending.pop();
|
|
27
|
+
for (let child = parent.firstChild; child !== null;) {
|
|
28
|
+
const next = child.nextSibling;
|
|
29
|
+
if (child.nodeType === 4) {
|
|
30
|
+
const text = this.document.createTextNode(child.nodeValue ?? "");
|
|
31
|
+
text.lineNumber = child.lineNumber;
|
|
32
|
+
text.columnNumber = child.columnNumber;
|
|
33
|
+
parent.replaceChild(text, child);
|
|
34
|
+
}
|
|
35
|
+
else if (child.nodeType === 1)
|
|
36
|
+
pending.push(child);
|
|
37
|
+
child = next;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
this.document.normalize();
|
|
41
|
+
pending.push(this.document);
|
|
42
|
+
while (pending.length > 0) {
|
|
43
|
+
const parent = pending.pop();
|
|
44
|
+
for (let child = parent.firstChild; child !== null;) {
|
|
45
|
+
const next = child.nextSibling;
|
|
46
|
+
if ((child.nodeType === 3 && (parent === this.document || child.nodeValue === ""))
|
|
47
|
+
|| (child.nodeType === 7 && child.nodeName === "xml"))
|
|
48
|
+
parent.removeChild(child);
|
|
49
|
+
else if (child.nodeType === 1)
|
|
50
|
+
pending.push(child);
|
|
51
|
+
child = next;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
region(node) {
|
|
56
|
+
if (node.nodeType === 9)
|
|
57
|
+
return this.#coordinates.regionFromOffsets(0, this.#length) ?? undefined;
|
|
58
|
+
const { lineNumber, columnNumber } = node;
|
|
59
|
+
const start = lineNumber === undefined ? undefined : this.#lineStarts[lineNumber - 1];
|
|
60
|
+
if (start === undefined || columnNumber === undefined)
|
|
61
|
+
return undefined;
|
|
62
|
+
const offset = start + columnNumber - 1;
|
|
63
|
+
const kind = node.nodeType === 1 ? "Element"
|
|
64
|
+
: node.nodeType === 2 ? "Attribute"
|
|
65
|
+
: node.nodeType === 4 ? "Cdata"
|
|
66
|
+
: node.nodeType === 7 ? "ProcessingInst"
|
|
67
|
+
: node.nodeType === 8 ? "Comment"
|
|
68
|
+
: node.nodeType === 10 ? "DoctypeDecl" : undefined;
|
|
69
|
+
let syntax = this.#tree.resolveInner(offset, 1);
|
|
70
|
+
const text = (name) => name === "Text" || name === "EntityReference" || name === "CharacterReference" || name === "Cdata";
|
|
71
|
+
while (kind === undefined ? node.nodeType !== 3 || !text(syntax.name) : syntax.name !== kind) {
|
|
72
|
+
if (syntax.parent === null)
|
|
73
|
+
return undefined;
|
|
74
|
+
syntax = syntax.parent;
|
|
75
|
+
}
|
|
76
|
+
const from = syntax.from;
|
|
77
|
+
let to = syntax.to;
|
|
78
|
+
if (node.nodeType === 3) {
|
|
79
|
+
while (syntax.nextSibling !== null && syntax.nextSibling.from === to && text(syntax.nextSibling.name)) {
|
|
80
|
+
syntax = syntax.nextSibling;
|
|
81
|
+
to = syntax.to;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return this.#coordinates.regionFromOffsets(from, to) ?? undefined;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=XmlSource.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"XmlSource.js","sourceRoot":"","sources":["../src/XmlSource.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@plurnk/plurnk-mimetypes-application-xml",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.28.0",
|
|
4
4
|
"description": "application/xml and text/xml mimetype handler for plurnk-service. DOM-tree extraction via @xmldom/xmldom; xpath via the xpath package; framework structural projections.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"plurnk",
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"handlers": [
|
|
21
21
|
{
|
|
22
22
|
"name": "application/xml",
|
|
23
|
-
"revision": "
|
|
23
|
+
"revision": "2",
|
|
24
24
|
"glyph": "📐",
|
|
25
25
|
"extensions": [
|
|
26
26
|
".xml"
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
},
|
|
29
29
|
{
|
|
30
30
|
"name": "text/xml",
|
|
31
|
-
"revision": "
|
|
31
|
+
"revision": "2",
|
|
32
32
|
"glyph": "📐",
|
|
33
33
|
"extensions": []
|
|
34
34
|
}
|
|
@@ -56,11 +56,12 @@
|
|
|
56
56
|
"prepack": "npm run build"
|
|
57
57
|
},
|
|
58
58
|
"dependencies": {
|
|
59
|
+
"@lezer/xml": "^1.0.6",
|
|
59
60
|
"@xmldom/xmldom": "^0.9.10",
|
|
60
61
|
"xpath": "^0.0.34"
|
|
61
62
|
},
|
|
62
63
|
"peerDependencies": {
|
|
63
|
-
"@plurnk/plurnk-mimetypes": "^1.
|
|
64
|
+
"@plurnk/plurnk-mimetypes": "^1.28.0"
|
|
64
65
|
},
|
|
65
66
|
"homepage": "https://github.com/plurnk/plurnk-service/tree/main/plurnk-mimetypes-application-xml#readme",
|
|
66
67
|
"bugs": {
|