@docx4j/core-ts 0.1.2 → 0.1.4
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/model/customxml/index.d.mts +1 -1
- package/dist/model/customxml/index.mjs +1 -1
- package/dist/model/customxml/xpath-fonto.d.mts +64 -0
- package/dist/model/customxml/xpath-fonto.mjs +161 -0
- package/dist/model/customxml/xpath.d.mts +32 -0
- package/dist/model/customxml/xpath.mjs +28 -0
- package/package.json +10 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { type XPathEngine, type XPathValue, DefaultXPathEngine, parsePrefixMappings, formatPrefixMappings, canonicalXPathOf, xmlOf, type CanonicalXPath } from './xpath.mjs';
|
|
1
|
+
export { type XPathEngine, type XPathValue, type BooleanConversionMode, booleanValue, DefaultXPathEngine, parsePrefixMappings, formatPrefixMappings, canonicalXPathOf, xmlOf, type CanonicalXPath } from './xpath.mjs';
|
|
2
2
|
export { CustomXmlPart, CustomXmlNode, CustomXmlPrefixMappingCollection, type CustomXmlNodeType, type CustomXmlPrefixMapping, type CustomXmlPartOwner } from './CustomXmlPart.mjs';
|
|
3
3
|
export { CustomXmlPartCollection, type CustomXmlHost } from './CustomXmlPartCollection.mjs';
|
|
4
4
|
export { XmlMapping, type CustomXmlPartLookup } from './XmlMapping.mjs';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// CR-002 phase E: custom XML parts, XML mapping, the XPath engine and the typed content controls
|
|
2
2
|
// (CR-002 sections 3.5 and 3.6). Exported from '.' and './model', as the content API is.
|
|
3
|
-
export { DefaultXPathEngine, parsePrefixMappings, formatPrefixMappings, canonicalXPathOf, xmlOf } from './xpath.mjs';
|
|
3
|
+
export { booleanValue, DefaultXPathEngine, parsePrefixMappings, formatPrefixMappings, canonicalXPathOf, xmlOf } from './xpath.mjs';
|
|
4
4
|
export { CustomXmlPart, CustomXmlNode, CustomXmlPrefixMappingCollection } from './CustomXmlPart.mjs';
|
|
5
5
|
export { CustomXmlPartCollection } from './CustomXmlPartCollection.mjs';
|
|
6
6
|
export { XmlMapping } from './XmlMapping.mjs';
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import type { BooleanConversionMode, XPathEngine, XPathValue } from './xpath.mjs';
|
|
2
|
+
/**
|
|
3
|
+
* XPath 3.1 through FontoXPath, for the `xpath2` boolean conversion mode and for expressions
|
|
4
|
+
* written in XPath 2.0 syntax. `select`, `selectValue` and the `java` and `xpath1` modes answer as
|
|
5
|
+
* `DefaultXPathEngine` does; `xpath2` is the mode this engine exists for.
|
|
6
|
+
*
|
|
7
|
+
* **In a browser or any bundled application, pass the module in.** The no-argument form loads
|
|
8
|
+
* `fontoxpath` by a dynamic `import()` of the bare specifier, which Node resolves and a browser
|
|
9
|
+
* does not: there is no import map, and the `@vite-ignore` that keeps a bundler from rewriting the
|
|
10
|
+
* specifier (needed so that a bundle never carries the optional peer against the consumer's will)
|
|
11
|
+
* also keeps it from resolving it. So the application imports the module itself, where its own
|
|
12
|
+
* bundler resolves it statically, and hands it over:
|
|
13
|
+
*
|
|
14
|
+
* import * as fontoxpath from 'fontoxpath';
|
|
15
|
+
* import { FontoXPathEngine } from '@docx4j/core-ts/xpath-fonto';
|
|
16
|
+
* pkg.xpathEngine = new FontoXPathEngine(fontoxpath); // ready at once
|
|
17
|
+
*
|
|
18
|
+
* In Node, `new FontoXPathEngine()` and `await ready()` still work and still say what to install
|
|
19
|
+
* if the peer is absent. Which module is loaded, and when, is the consumer's business either way -
|
|
20
|
+
* the same principle as `pkg.xpathEngine` being settable at all (CR-005 phase A, 2026-09-26).
|
|
21
|
+
*/
|
|
22
|
+
export declare class FontoXPathEngine implements XPathEngine {
|
|
23
|
+
private module;
|
|
24
|
+
private loading;
|
|
25
|
+
/**
|
|
26
|
+
* @param fontoxpath the `fontoxpath` module, imported by the caller. Omit it in Node to have
|
|
27
|
+
* `ready()` import it; supply it in a browser or a bundle, where a bare dynamic specifier
|
|
28
|
+
* cannot be resolved. Either the module's namespace object or its default export is accepted,
|
|
29
|
+
* the published ESM build having no named exports under Node's interop.
|
|
30
|
+
*/
|
|
31
|
+
constructor(fontoxpath?: unknown);
|
|
32
|
+
get isReady(): boolean;
|
|
33
|
+
ready(): Promise<void>;
|
|
34
|
+
select(expression: string, context: Node, namespaces?: Record<string, string>): Node[];
|
|
35
|
+
selectValue(expression: string, context: Node, namespaces?: Record<string, string>): XPathValue;
|
|
36
|
+
/**
|
|
37
|
+
* Table 7's three modes. `java` and `xpath1` are the rules the specification states, evaluated
|
|
38
|
+
* here rather than through the `booleanValue` function so that one engine answers all three.
|
|
39
|
+
* `xpath2` is the effective boolean value **with the specification's string rule**: see
|
|
40
|
+
* {@link xpath2BooleanValue}.
|
|
41
|
+
*/
|
|
42
|
+
booleanValue(expression: string, context: Node, namespaces: Record<string, string>, mode: BooleanConversionMode): boolean;
|
|
43
|
+
/**
|
|
44
|
+
* The `xpath2` mode of table 7, **as docx4j does it**: the expression is wrapped in
|
|
45
|
+
* `xs:boolean(...)` and the engine performs the cast, which is `XmlPart.cachedXPathGetBoolean`
|
|
46
|
+
* with `opendope.conditions.Xpathref.XPathBoolean=cast2` (measured against Saxon-HE 9.9.0-2 by
|
|
47
|
+
* the docx4j session, 2026-09-25, and matched here case for case). Doing what docx4j does,
|
|
48
|
+
* rather than casting by hand, is what keeps the two from drifting: the lexical space, the
|
|
49
|
+
* whitespace collapse, the multi-item rule and the empty sequence all come from the engine.
|
|
50
|
+
*
|
|
51
|
+
* So: `true`, `1` are true; `false`, `0` are false; leading and trailing space is collapsed
|
|
52
|
+
* first, so `" false "` is false; an expression selecting **nothing** is false; and anything
|
|
53
|
+
* else raises - `"yes"`, `"True"` (`xs:boolean`'s lexical space is case-sensitive where the
|
|
54
|
+
* `java` mode ignores case), `""` from an empty element, and a sequence of more than one node.
|
|
55
|
+
*
|
|
56
|
+
* A raise is not a false. docx4j turns it into an `InputIntegrityException` and the whole bind
|
|
57
|
+
* fails; here it is a `Docx4JException` from this call, and what a processor does with it is
|
|
58
|
+
* the processor's business (CR-005 phase B). That is the one place the two behaviours are not
|
|
59
|
+
* yet the same thing, and the specification does not say which is right.
|
|
60
|
+
*/
|
|
61
|
+
private xpath2BooleanValue;
|
|
62
|
+
private options;
|
|
63
|
+
private fonto;
|
|
64
|
+
}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
// CR-005 phase A: an XPath 2.0 (in fact 3.1) `XPathEngine`, for the OpenDoPE specification's
|
|
2
|
+
// `xpath2` boolean conversion mode (its section 7.2, table 7).
|
|
3
|
+
//
|
|
4
|
+
// `DefaultXPathEngine` is XPath 1.0, which is what `document.evaluate` and the `xpath` package
|
|
5
|
+
// give. The specification's `xpath2` mode needs a 2.0 evaluator, and expressions written for it
|
|
6
|
+
// may use 2.0 syntax; docx4j uses Saxon. [FontoXPath](https://github.com/FontoXML/fontoxpath) is
|
|
7
|
+
// XPath 3.1 in JavaScript (MIT), over DOM nodes in browsers and in Node, and XPath 3.1 is a
|
|
8
|
+
// superset of 2.0.
|
|
9
|
+
//
|
|
10
|
+
// It is an **optional peer dependency** and this module is its own entry point
|
|
11
|
+
// (`@docx4j/core-ts/xpath-fonto`), so nothing that imports the package pays its ~665 KB: only a
|
|
12
|
+
// consumer who needs the `xpath2` mode installs it and imports this.
|
|
13
|
+
//
|
|
14
|
+
// import { FontoXPathEngine } from '@docx4j/core-ts/xpath-fonto';
|
|
15
|
+
// pkg.xpathEngine = new FontoXPathEngine();
|
|
16
|
+
// await pkg.customXmlParts.load();
|
|
17
|
+
import { Docx4JException } from '../../opc/exceptions.mjs';
|
|
18
|
+
/** `evaluateXPath`'s ANY_TYPE: the value in its natural type, which is what `selectValue` reports. */
|
|
19
|
+
const ANY_TYPE = 0;
|
|
20
|
+
/**
|
|
21
|
+
* XPath 3.1 through FontoXPath, for the `xpath2` boolean conversion mode and for expressions
|
|
22
|
+
* written in XPath 2.0 syntax. `select`, `selectValue` and the `java` and `xpath1` modes answer as
|
|
23
|
+
* `DefaultXPathEngine` does; `xpath2` is the mode this engine exists for.
|
|
24
|
+
*
|
|
25
|
+
* **In a browser or any bundled application, pass the module in.** The no-argument form loads
|
|
26
|
+
* `fontoxpath` by a dynamic `import()` of the bare specifier, which Node resolves and a browser
|
|
27
|
+
* does not: there is no import map, and the `@vite-ignore` that keeps a bundler from rewriting the
|
|
28
|
+
* specifier (needed so that a bundle never carries the optional peer against the consumer's will)
|
|
29
|
+
* also keeps it from resolving it. So the application imports the module itself, where its own
|
|
30
|
+
* bundler resolves it statically, and hands it over:
|
|
31
|
+
*
|
|
32
|
+
* import * as fontoxpath from 'fontoxpath';
|
|
33
|
+
* import { FontoXPathEngine } from '@docx4j/core-ts/xpath-fonto';
|
|
34
|
+
* pkg.xpathEngine = new FontoXPathEngine(fontoxpath); // ready at once
|
|
35
|
+
*
|
|
36
|
+
* In Node, `new FontoXPathEngine()` and `await ready()` still work and still say what to install
|
|
37
|
+
* if the peer is absent. Which module is loaded, and when, is the consumer's business either way -
|
|
38
|
+
* the same principle as `pkg.xpathEngine` being settable at all (CR-005 phase A, 2026-09-26).
|
|
39
|
+
*/
|
|
40
|
+
export class FontoXPathEngine {
|
|
41
|
+
/**
|
|
42
|
+
* @param fontoxpath the `fontoxpath` module, imported by the caller. Omit it in Node to have
|
|
43
|
+
* `ready()` import it; supply it in a browser or a bundle, where a bare dynamic specifier
|
|
44
|
+
* cannot be resolved. Either the module's namespace object or its default export is accepted,
|
|
45
|
+
* the published ESM build having no named exports under Node's interop.
|
|
46
|
+
*/
|
|
47
|
+
constructor(fontoxpath) {
|
|
48
|
+
if (fontoxpath !== undefined)
|
|
49
|
+
this.module = moduleOf(fontoxpath);
|
|
50
|
+
}
|
|
51
|
+
get isReady() {
|
|
52
|
+
return this.module !== undefined;
|
|
53
|
+
}
|
|
54
|
+
async ready() {
|
|
55
|
+
var _a;
|
|
56
|
+
if (this.isReady)
|
|
57
|
+
return;
|
|
58
|
+
(_a = this.loading) !== null && _a !== void 0 ? _a : (this.loading = (async () => {
|
|
59
|
+
const specifier = 'fontoxpath';
|
|
60
|
+
try {
|
|
61
|
+
const loaded = await import(/* @vite-ignore */ specifier);
|
|
62
|
+
this.module = moduleOf(loaded);
|
|
63
|
+
}
|
|
64
|
+
catch (e) {
|
|
65
|
+
throw new Docx4JException("FontoXPathEngine needs the optional peer dependency 'fontoxpath' (npm install fontoxpath); "
|
|
66
|
+
+ 'in a browser or a bundle, import it yourself and pass it: new FontoXPathEngine(fontoxpath)', { cause: e });
|
|
67
|
+
}
|
|
68
|
+
})());
|
|
69
|
+
await this.loading;
|
|
70
|
+
}
|
|
71
|
+
select(expression, context, namespaces = {}) {
|
|
72
|
+
return this.fonto().evaluateXPathToNodes(expression, context, null, null, this.options(namespaces));
|
|
73
|
+
}
|
|
74
|
+
selectValue(expression, context, namespaces = {}) {
|
|
75
|
+
const value = this.fonto().evaluateXPath(expression, context, null, null, ANY_TYPE, this.options(namespaces));
|
|
76
|
+
return valueOf(value);
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Table 7's three modes. `java` and `xpath1` are the rules the specification states, evaluated
|
|
80
|
+
* here rather than through the `booleanValue` function so that one engine answers all three.
|
|
81
|
+
* `xpath2` is the effective boolean value **with the specification's string rule**: see
|
|
82
|
+
* {@link xpath2BooleanValue}.
|
|
83
|
+
*/
|
|
84
|
+
booleanValue(expression, context, namespaces, mode) {
|
|
85
|
+
switch (mode) {
|
|
86
|
+
case 'java': {
|
|
87
|
+
const value = this.selectValue(expression, context, namespaces);
|
|
88
|
+
return typeof value === 'boolean' ? value : String(value !== null && value !== void 0 ? value : '').toLowerCase() === 'true';
|
|
89
|
+
}
|
|
90
|
+
case 'xpath1':
|
|
91
|
+
// XPath 1.0's boolean() rules, asked for in that language so that 3.1's do not apply.
|
|
92
|
+
return this.fonto().evaluateXPathToBoolean(`boolean(${expression})`, context, null, null, { ...this.options(namespaces), language: 'XPath3.1' });
|
|
93
|
+
default:
|
|
94
|
+
return this.xpath2BooleanValue(expression, context, namespaces);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* The `xpath2` mode of table 7, **as docx4j does it**: the expression is wrapped in
|
|
99
|
+
* `xs:boolean(...)` and the engine performs the cast, which is `XmlPart.cachedXPathGetBoolean`
|
|
100
|
+
* with `opendope.conditions.Xpathref.XPathBoolean=cast2` (measured against Saxon-HE 9.9.0-2 by
|
|
101
|
+
* the docx4j session, 2026-09-25, and matched here case for case). Doing what docx4j does,
|
|
102
|
+
* rather than casting by hand, is what keeps the two from drifting: the lexical space, the
|
|
103
|
+
* whitespace collapse, the multi-item rule and the empty sequence all come from the engine.
|
|
104
|
+
*
|
|
105
|
+
* So: `true`, `1` are true; `false`, `0` are false; leading and trailing space is collapsed
|
|
106
|
+
* first, so `" false "` is false; an expression selecting **nothing** is false; and anything
|
|
107
|
+
* else raises - `"yes"`, `"True"` (`xs:boolean`'s lexical space is case-sensitive where the
|
|
108
|
+
* `java` mode ignores case), `""` from an empty element, and a sequence of more than one node.
|
|
109
|
+
*
|
|
110
|
+
* A raise is not a false. docx4j turns it into an `InputIntegrityException` and the whole bind
|
|
111
|
+
* fails; here it is a `Docx4JException` from this call, and what a processor does with it is
|
|
112
|
+
* the processor's business (CR-005 phase B). That is the one place the two behaviours are not
|
|
113
|
+
* yet the same thing, and the specification does not say which is right.
|
|
114
|
+
*/
|
|
115
|
+
xpath2BooleanValue(expression, context, namespaces) {
|
|
116
|
+
try {
|
|
117
|
+
return this.fonto().evaluateXPathToBoolean(`xs:boolean(${expression})`, context, null, null, this.options(namespaces));
|
|
118
|
+
}
|
|
119
|
+
catch (e) {
|
|
120
|
+
throw new Docx4JException(`The xpath2 boolean conversion mode casts to xs:boolean, which accepts only "true", "false", "1" and "0", `
|
|
121
|
+
+ `and one value at a time: ${expression} gives none of them`, { cause: e });
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
options(namespaces) {
|
|
125
|
+
return { namespaceResolver: (prefix) => { var _a; return (_a = namespaces[prefix]) !== null && _a !== void 0 ? _a : null; } };
|
|
126
|
+
}
|
|
127
|
+
fonto() {
|
|
128
|
+
if (!this.module) {
|
|
129
|
+
throw new Docx4JException('The XPath engine is not ready yet: await pkg.customXmlParts.load() (or pkg.xpathEngine.ready()) once before selecting nodes');
|
|
130
|
+
}
|
|
131
|
+
return this.module;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* The module, whether given as a namespace object or as a default export, checked for the one
|
|
136
|
+
* function every call goes through so that the wrong module is refused where it is passed rather
|
|
137
|
+
* than at the first evaluation.
|
|
138
|
+
*/
|
|
139
|
+
function moduleOf(loaded) {
|
|
140
|
+
const candidate = loaded;
|
|
141
|
+
const module = typeof (candidate === null || candidate === void 0 ? void 0 : candidate.evaluateXPath) === 'function' ? candidate : candidate === null || candidate === void 0 ? void 0 : candidate.default;
|
|
142
|
+
if (!module || typeof module.evaluateXPath !== 'function') {
|
|
143
|
+
throw new Docx4JException('FontoXPathEngine was given something that is not the fontoxpath module: '
|
|
144
|
+
+ "expected its evaluateXPath, as in new FontoXPathEngine(await import('fontoxpath'))");
|
|
145
|
+
}
|
|
146
|
+
return module;
|
|
147
|
+
}
|
|
148
|
+
/** A FontoXPath result in the four-type union `selectValue` reports. */
|
|
149
|
+
function valueOf(value) {
|
|
150
|
+
var _a;
|
|
151
|
+
if (value === null || value === undefined)
|
|
152
|
+
return undefined;
|
|
153
|
+
if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean')
|
|
154
|
+
return value;
|
|
155
|
+
if (Array.isArray(value))
|
|
156
|
+
return value.length === 0 ? undefined : valueOf(value[0]);
|
|
157
|
+
if (typeof value === 'object' && typeof value.nodeType === 'number') {
|
|
158
|
+
return (_a = value.textContent) !== null && _a !== void 0 ? _a : '';
|
|
159
|
+
}
|
|
160
|
+
return String(value);
|
|
161
|
+
}
|
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
/** The XPath result kinds `selectValue` can report. */
|
|
2
2
|
export type XPathValue = string | number | boolean | undefined;
|
|
3
|
+
/**
|
|
4
|
+
* How an XPaths entry becomes a boolean (OpenDoPE specification v3 section 7.2, table 7, declared
|
|
5
|
+
* in the XPaths part's `booleanConversion` attribute; CR-005 phase A):
|
|
6
|
+
*
|
|
7
|
+
* - `java`: the string value is true only if it equals `true`, ignoring case. `"1"` and `"yes"`
|
|
8
|
+
* are false. docx4j's `Boolean.parseBoolean`, and the default for a template that declares no
|
|
9
|
+
* mode.
|
|
10
|
+
* - `xpath1`: XPath 1.0 `boolean()`. A node-set is true if non-empty, a string if non-empty - so
|
|
11
|
+
* `"false"` is **true**.
|
|
12
|
+
* - `xpath2`: the effective boolean value, a string cast to `xs:boolean` accepting only `true`,
|
|
13
|
+
* `false`, `1` and `0` - so `"false"` is false and `"yes"` is an **error**. Needs an XPath 2.0
|
|
14
|
+
* engine: `FontoXPathEngine` from `@docx4j/core-ts/xpath-fonto`.
|
|
15
|
+
*/
|
|
16
|
+
export type BooleanConversionMode = 'java' | 'xpath1' | 'xpath2';
|
|
3
17
|
/**
|
|
4
18
|
* XPath 1.0 over a DOM (CR-002 section 3.6). `select` answers a node set; `selectValue` answers a
|
|
5
19
|
* string, number or boolean result. `namespaces` maps prefixes used in the expression to URIs.
|
|
@@ -11,7 +25,25 @@ export interface XPathEngine {
|
|
|
11
25
|
readonly isReady: boolean;
|
|
12
26
|
select(expression: string, context: Node, namespaces?: Record<string, string>): Node[];
|
|
13
27
|
selectValue(expression: string, context: Node, namespaces?: Record<string, string>): XPathValue;
|
|
28
|
+
/**
|
|
29
|
+
* The expression as a boolean in one conversion mode, for an engine that can do more than the
|
|
30
|
+
* function {@link booleanValue} can do over `selectValue` - in practice `xpath2`, which needs an
|
|
31
|
+
* XPath 2.0 evaluator. Optional: `XPathEngine` is public and a consumer may implement it, so a
|
|
32
|
+
* required member would break every implementation that predates this. Callers go through
|
|
33
|
+
* {@link booleanValue}, never here.
|
|
34
|
+
*/
|
|
35
|
+
booleanValue?(expression: string, context: Node, namespaces: Record<string, string>, mode: BooleanConversionMode): boolean;
|
|
14
36
|
}
|
|
37
|
+
/**
|
|
38
|
+
* The expression as a boolean in a declared conversion mode (table 7 above).
|
|
39
|
+
*
|
|
40
|
+
* `java` and `xpath1` need nothing an `XPathEngine` does not already have, so they work over any
|
|
41
|
+
* engine: `java` is the string value compared with `true`, `xpath1` is XPath 1.0 `boolean()` of the
|
|
42
|
+
* expression. `xpath2` is delegated to the engine's own `booleanValue` when it has one, and
|
|
43
|
+
* otherwise throws naming the engine to install - which is the specification's REQ-032, a processor
|
|
44
|
+
* evaluating in the declared mode or refusing to process the template.
|
|
45
|
+
*/
|
|
46
|
+
export declare function booleanValue(engine: XPathEngine, expression: string, context: Node, namespaces?: Record<string, string>, mode?: BooleanConversionMode): boolean;
|
|
15
47
|
/**
|
|
16
48
|
* The default engine: `document.evaluate` where the runtime has it, else the `xpath` package,
|
|
17
49
|
* imported on `ready()`. The import specifier is a variable so that a bundler does not follow it
|
|
@@ -12,6 +12,34 @@
|
|
|
12
12
|
// afterwards is synchronous. A call before the engine is ready throws, naming the fix.
|
|
13
13
|
import { Docx4JException } from '../../opc/exceptions.mjs';
|
|
14
14
|
import { serializeXml } from '../../xml/dom.mjs';
|
|
15
|
+
/**
|
|
16
|
+
* The expression as a boolean in a declared conversion mode (table 7 above).
|
|
17
|
+
*
|
|
18
|
+
* `java` and `xpath1` need nothing an `XPathEngine` does not already have, so they work over any
|
|
19
|
+
* engine: `java` is the string value compared with `true`, `xpath1` is XPath 1.0 `boolean()` of the
|
|
20
|
+
* expression. `xpath2` is delegated to the engine's own `booleanValue` when it has one, and
|
|
21
|
+
* otherwise throws naming the engine to install - which is the specification's REQ-032, a processor
|
|
22
|
+
* evaluating in the declared mode or refusing to process the template.
|
|
23
|
+
*/
|
|
24
|
+
export function booleanValue(engine, expression, context, namespaces = {}, mode = 'java') {
|
|
25
|
+
if (engine.booleanValue)
|
|
26
|
+
return engine.booleanValue(expression, context, namespaces, mode);
|
|
27
|
+
switch (mode) {
|
|
28
|
+
case 'java': {
|
|
29
|
+
const value = engine.selectValue(expression, context, namespaces);
|
|
30
|
+
return typeof value === 'boolean' ? value : String(value !== null && value !== void 0 ? value : '').toLowerCase() === 'true';
|
|
31
|
+
}
|
|
32
|
+
case 'xpath1': {
|
|
33
|
+
// boolean() is XPath 1.0's own conversion, so the engine applies the rules rather than this.
|
|
34
|
+
const value = engine.selectValue(`boolean(${expression})`, context, namespaces);
|
|
35
|
+
return value === true;
|
|
36
|
+
}
|
|
37
|
+
default:
|
|
38
|
+
throw new Docx4JException(`The boolean conversion mode "${mode}" needs an XPath 2.0 engine: `
|
|
39
|
+
+ "import { FontoXPathEngine } from '@docx4j/core-ts/xpath-fonto' (npm install fontoxpath) "
|
|
40
|
+
+ 'and set pkg.xpathEngine to it');
|
|
41
|
+
}
|
|
42
|
+
}
|
|
15
43
|
// XPathResult constants, spelled out because `XPathResult` is not a global in Node.
|
|
16
44
|
const ANY_TYPE = 0;
|
|
17
45
|
const NUMBER_TYPE = 1;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@docx4j/core-ts",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"description": "docx4j-core for TypeScript: Open Packaging (docx/pptx/xlsx zip and flat OPC), typed parts and relationships, style, numbering and font resolution over @docx4j/generated-objects-ts. Node, browsers, Word add-ins.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.mjs",
|
|
@@ -33,6 +33,10 @@
|
|
|
33
33
|
"./office-js": {
|
|
34
34
|
"types": "./dist/office-js/index.d.mts",
|
|
35
35
|
"import": "./dist/office-js/index.mjs"
|
|
36
|
+
},
|
|
37
|
+
"./xpath-fonto": {
|
|
38
|
+
"types": "./dist/model/customxml/xpath-fonto.d.mts",
|
|
39
|
+
"import": "./dist/model/customxml/xpath-fonto.mjs"
|
|
36
40
|
}
|
|
37
41
|
},
|
|
38
42
|
"files": [
|
|
@@ -79,13 +83,18 @@
|
|
|
79
83
|
"fflate": "^0.8.2"
|
|
80
84
|
},
|
|
81
85
|
"devDependencies": {
|
|
86
|
+
"fontoxpath": "^3.34.0",
|
|
82
87
|
"typescript": "~5.6.3",
|
|
83
88
|
"xpath": "^0.0.34"
|
|
84
89
|
},
|
|
85
90
|
"peerDependencies": {
|
|
91
|
+
"fontoxpath": "^3.30.0",
|
|
86
92
|
"xpath": "^0.0.34"
|
|
87
93
|
},
|
|
88
94
|
"peerDependenciesMeta": {
|
|
95
|
+
"fontoxpath": {
|
|
96
|
+
"optional": true
|
|
97
|
+
},
|
|
89
98
|
"xpath": {
|
|
90
99
|
"optional": true
|
|
91
100
|
}
|