@galaxy-tool-util/tool-xml 1.11.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 John Chilton
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,55 @@
1
+ # @galaxy-tool-util/tool-xml
2
+
3
+ XML tool-source layer for Galaxy tools. Holds the XML-specific parsing weight
4
+ (an XML parser dependency) out of the browser-safe `@galaxy-tool-util/schema`
5
+ package.
6
+
7
+ Currently ships a port of Galaxy's macro expander,
8
+ `lib/galaxy/util/xml_macros.py`: the XML-only, pre-parse transform that expands
9
+ `<macros>` — `<token>` substitution (including nested tokens and cycle
10
+ detection), `<xml>`/`<macro>` templates via `<expand>`, `<import>` of external
11
+ macro files, named/unnamed `yield`, and macro token parameters — mutating an
12
+ `XmlElement` tree in place.
13
+
14
+ ```ts
15
+ import { loadTool, canonicalize } from "@galaxy-tool-util/tool-xml";
16
+
17
+ const expanded = loadTool("tool.xml"); // reads + expands macros
18
+ ```
19
+
20
+ `parseXmlToTree(text)` parses XML into a mutable `XmlElement` tree;
21
+ `expandMacros(root, importResolver)` expands it (filesystem-agnostic);
22
+ `loadTool(path)` is the filesystem-backed convenience that resolves `<import>`
23
+ paths relative to the tool file. `canonicalize(el)` reduces a tree to a
24
+ whitespace-normalized shape for structural comparison.
25
+
26
+ Behavior is verified against golden macro-expansion fixtures synced from Galaxy
27
+ (`test/fixtures/macro-expansion/cases/`), compared structurally rather than
28
+ byte-for-byte so the port need not reproduce Galaxy's XML serializer.
29
+
30
+ On top of the expander, `XmlToolSource` ports the parse accessors from Galaxy's
31
+ `galaxy.tool_util.parser.xml.XmlToolSource` that don't need the input-parameter
32
+ tree — the tool metadata (id, version, name, description, profile, license,
33
+ edam operations/topics, xrefs, citations, help, command) and the `<outputs>`
34
+ tree (`parseOutputs()` → the `ToolOutput` union: data / collection / expression
35
+ outputs, with `discover_datasets`):
36
+
37
+ ```ts
38
+ import { loadXmlToolSource } from "@galaxy-tool-util/tool-xml";
39
+
40
+ const src = loadXmlToolSource("tool.xml");
41
+ src.parseId(); // "cat1"
42
+ src.parseCitations(); // [{ type: "doi", content: "..." }]
43
+ src.parseOutputs(); // [{ type: "data", name: "out1", format: "bam", ... }]
44
+ ```
45
+
46
+ Extraction is raw — the model-level validation Galaxy's pydantic models run
47
+ when the `ParsedTool` is assembled is not applied yet. `parseCitations` passes
48
+ `doi:`-prefixed or malformed citations through rather than normalizing/dropping
49
+ them (DOI/BibTeX shape checks, profile-gated skips), and `parseOutputs` does not
50
+ enforce the collection-structure invariants (e.g. both `type` and `type_source`
51
+ set) that Galaxy raises on.
52
+
53
+ Assembling these (plus inputs, behind the `InputSource` seam) into a full
54
+ `ParsedTool`, with that validation, is the remaining work; see the repository's
55
+ tool-parsing issue.
@@ -0,0 +1,73 @@
1
+ /**
2
+ * A minimal, mutable XML element tree modeled on Python's
3
+ * ``xml.etree.ElementTree.Element`` — enough to faithfully port
4
+ * ``galaxy.util.xml_macros`` (macro expansion) and to compare expanded trees
5
+ * structurally against golden fixtures.
6
+ *
7
+ * ``text`` mirrors ElementTree's ``.text``: the character data immediately
8
+ * following the start tag and preceding the first child element. Trailing /
9
+ * inter-element ("tail") text is not modeled — it is whitespace-only in tool
10
+ * XML and is normalized away by {@link canonicalize}.
11
+ */
12
+ export declare class XmlElement {
13
+ tag: string;
14
+ /** Attributes in document order. */
15
+ attrs: Map<string, string>;
16
+ /** Leading text content (ElementTree ``.text``); "" when absent. */
17
+ text: string;
18
+ children: XmlElement[];
19
+ parent: XmlElement | null;
20
+ constructor(tag: string);
21
+ /** Deep copy with a detached parent (mirrors ``copy.deepcopy``). */
22
+ clone(): XmlElement;
23
+ /** Remove all children, attributes and text (mirrors ``Element.clear``). */
24
+ clear(): void;
25
+ /** First direct child with the given tag, or null (mirrors ``find(tag)``). */
26
+ findChild(tag: string): XmlElement | null;
27
+ /** Direct children with the given tag (mirrors ``findall(tag)``). */
28
+ findChildren(tag: string): XmlElement[];
29
+ /**
30
+ * First descendant (excluding self) matching ``tag`` in document order —
31
+ * mirrors ``Element.find(".//tag")``.
32
+ */
33
+ findFirstDescendant(tag: string): XmlElement | null;
34
+ /**
35
+ * All descendants (excluding self) matching ``tag`` (and optional predicate)
36
+ * in document order — mirrors ``Element.findall(".//tag")``.
37
+ */
38
+ findAllDescendants(tag: string, predicate?: (el: XmlElement) => boolean): XmlElement[];
39
+ }
40
+ /** Parse XML text into an {@link XmlElement} tree, returning the root element. */
41
+ export declare function parseXmlToTree(text: string): XmlElement;
42
+ export interface CanonicalElement {
43
+ tag: string;
44
+ text: string;
45
+ attrs: Record<string, string>;
46
+ children: CanonicalElement[];
47
+ }
48
+ /**
49
+ * Reduce an element tree to a whitespace-normalized, serializer-independent
50
+ * shape for structural comparison: tag, trimmed text, attributes (compared
51
+ * order-insensitively), and ordered children.
52
+ */
53
+ export declare function canonicalize(el: XmlElement): CanonicalElement;
54
+ /**
55
+ * Attribute-first text lookup — tries ``root``'s ``name`` attribute, then the
56
+ * ``<name>`` child element's text with line breaks collapsed
57
+ * (``"".join(splitlines())``) and the result trimmed; ``null`` if neither is
58
+ * present. The shared core of ``galaxy.util.xml_text``.
59
+ */
60
+ export declare function xmlTextOrNull(root: XmlElement, name: string): string | null;
61
+ /** Port of ``galaxy.util.xml_text`` — {@link xmlTextOrNull} with a string default. */
62
+ export declare function xmlText(root: XmlElement, name: string, defaultValue?: string): string;
63
+ /**
64
+ * Port of ``galaxy.util.string_as_bool`` — truthy for ``true``/``yes``/``on``/``1``
65
+ * (case-insensitive), false otherwise (including ``undefined``/empty string).
66
+ */
67
+ export declare function stringAsBool(value: string | undefined): boolean;
68
+ /**
69
+ * Insert deep copies of ``targets`` where ``query`` sits among its parent's
70
+ * children, then remove ``query`` — port of ``xml_macros._xml_replace``.
71
+ */
72
+ export declare function xmlReplace(query: XmlElement, targets: XmlElement[]): void;
73
+ //# sourceMappingURL=element.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"element.d.ts","sourceRoot":"","sources":["../src/element.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;GAUG;AACH,qBAAa,UAAU;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,oCAAoC;IACpC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC3B,oEAAoE;IACpE,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,UAAU,EAAE,CAAC;IACvB,MAAM,EAAE,UAAU,GAAG,IAAI,CAAC;gBAEd,GAAG,EAAE,MAAM;IAQvB,oEAAoE;IACpE,KAAK,IAAI,UAAU;IAYnB,4EAA4E;IAC5E,KAAK,IAAI,IAAI;IAMb,8EAA8E;IAC9E,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI;IAOzC,qEAAqE;IACrE,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,EAAE;IAIvC;;;OAGG;IACH,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI;IASnD;;;OAGG;IACH,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,CAAC,EAAE,EAAE,UAAU,KAAK,OAAO,GAAG,UAAU,EAAE;CAWvF;AAsED,kFAAkF;AAClF,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,CAOvD;AAMD,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,QAAQ,EAAE,gBAAgB,EAAE,CAAC;CAC9B;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,EAAE,EAAE,UAAU,GAAG,gBAAgB,CAO7D;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAW3E;AAED,sFAAsF;AACtF,wBAAgB,OAAO,CAAC,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE,YAAY,SAAK,GAAG,MAAM,CAEjF;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAG/D;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,UAAU,EAAE,GAAG,IAAI,CAWzE"}
@@ -0,0 +1,226 @@
1
+ import { XMLParser } from "fast-xml-parser";
2
+ /**
3
+ * A minimal, mutable XML element tree modeled on Python's
4
+ * ``xml.etree.ElementTree.Element`` — enough to faithfully port
5
+ * ``galaxy.util.xml_macros`` (macro expansion) and to compare expanded trees
6
+ * structurally against golden fixtures.
7
+ *
8
+ * ``text`` mirrors ElementTree's ``.text``: the character data immediately
9
+ * following the start tag and preceding the first child element. Trailing /
10
+ * inter-element ("tail") text is not modeled — it is whitespace-only in tool
11
+ * XML and is normalized away by {@link canonicalize}.
12
+ */
13
+ export class XmlElement {
14
+ tag;
15
+ /** Attributes in document order. */
16
+ attrs;
17
+ /** Leading text content (ElementTree ``.text``); "" when absent. */
18
+ text;
19
+ children;
20
+ parent;
21
+ constructor(tag) {
22
+ this.tag = tag;
23
+ this.attrs = new Map();
24
+ this.text = "";
25
+ this.children = [];
26
+ this.parent = null;
27
+ }
28
+ /** Deep copy with a detached parent (mirrors ``copy.deepcopy``). */
29
+ clone() {
30
+ const copy = new XmlElement(this.tag);
31
+ copy.attrs = new Map(this.attrs);
32
+ copy.text = this.text;
33
+ for (const child of this.children) {
34
+ const childCopy = child.clone();
35
+ childCopy.parent = copy;
36
+ copy.children.push(childCopy);
37
+ }
38
+ return copy;
39
+ }
40
+ /** Remove all children, attributes and text (mirrors ``Element.clear``). */
41
+ clear() {
42
+ this.attrs = new Map();
43
+ this.text = "";
44
+ this.children = [];
45
+ }
46
+ /** First direct child with the given tag, or null (mirrors ``find(tag)``). */
47
+ findChild(tag) {
48
+ for (const child of this.children) {
49
+ if (child.tag === tag)
50
+ return child;
51
+ }
52
+ return null;
53
+ }
54
+ /** Direct children with the given tag (mirrors ``findall(tag)``). */
55
+ findChildren(tag) {
56
+ return this.children.filter((c) => c.tag === tag);
57
+ }
58
+ /**
59
+ * First descendant (excluding self) matching ``tag`` in document order —
60
+ * mirrors ``Element.find(".//tag")``.
61
+ */
62
+ findFirstDescendant(tag) {
63
+ for (const child of this.children) {
64
+ if (child.tag === tag)
65
+ return child;
66
+ const found = child.findFirstDescendant(tag);
67
+ if (found)
68
+ return found;
69
+ }
70
+ return null;
71
+ }
72
+ /**
73
+ * All descendants (excluding self) matching ``tag`` (and optional predicate)
74
+ * in document order — mirrors ``Element.findall(".//tag")``.
75
+ */
76
+ findAllDescendants(tag, predicate) {
77
+ const out = [];
78
+ const walk = (el) => {
79
+ for (const child of el.children) {
80
+ if (child.tag === tag && (!predicate || predicate(child)))
81
+ out.push(child);
82
+ walk(child);
83
+ }
84
+ };
85
+ walk(this);
86
+ return out;
87
+ }
88
+ }
89
+ // ---------------------------------------------------------------------------
90
+ // Parsing (fast-xml-parser preserveOrder tree → XmlElement)
91
+ // ---------------------------------------------------------------------------
92
+ const PARSER = new XMLParser({
93
+ preserveOrder: true,
94
+ ignoreAttributes: false,
95
+ attributeNamePrefix: "",
96
+ attributesGroupName: ":@",
97
+ parseTagValue: false,
98
+ parseAttributeValue: false,
99
+ trimValues: false,
100
+ processEntities: true,
101
+ cdataPropName: "#cdata",
102
+ // No commentPropName → comments are dropped (matches remove_comments=True).
103
+ });
104
+ /** Text carried by a preserveOrder "#text"/"#cdata" node, else null. */
105
+ function nodeText(node) {
106
+ if ("#text" in node)
107
+ return String(node["#text"]);
108
+ if ("#cdata" in node) {
109
+ const parts = node["#cdata"];
110
+ return parts.map((p) => ("#text" in p ? String(p["#text"]) : "")).join("");
111
+ }
112
+ return null;
113
+ }
114
+ /** Tag name of a preserveOrder element node (the non-special, non-attrs key). */
115
+ function nodeTag(node) {
116
+ for (const key of Object.keys(node)) {
117
+ // Skip attribute group, text/cdata specials, and the "?xml"/PI declaration.
118
+ if (key === ":@" || key.startsWith("#") || key.startsWith("?"))
119
+ continue;
120
+ return key;
121
+ }
122
+ return null;
123
+ }
124
+ function buildElement(node) {
125
+ const tag = nodeTag(node);
126
+ if (tag === null)
127
+ return null;
128
+ const el = new XmlElement(tag);
129
+ const rawAttrs = node[":@"];
130
+ if (rawAttrs) {
131
+ for (const [k, v] of Object.entries(rawAttrs))
132
+ el.attrs.set(k, String(v));
133
+ }
134
+ const childNodes = node[tag] ?? [];
135
+ let sawElement = false;
136
+ for (const child of childNodes) {
137
+ const text = nodeText(child);
138
+ if (text !== null) {
139
+ // Leading text only (before the first child element); tails are dropped.
140
+ if (!sawElement)
141
+ el.text += text;
142
+ continue;
143
+ }
144
+ const childEl = buildElement(child);
145
+ if (childEl) {
146
+ childEl.parent = el;
147
+ el.children.push(childEl);
148
+ sawElement = true;
149
+ }
150
+ }
151
+ return el;
152
+ }
153
+ /** Parse XML text into an {@link XmlElement} tree, returning the root element. */
154
+ export function parseXmlToTree(text) {
155
+ const parsed = PARSER.parse(text);
156
+ for (const node of parsed) {
157
+ const el = buildElement(node);
158
+ if (el)
159
+ return el;
160
+ }
161
+ throw new Error("No root element found in XML input.");
162
+ }
163
+ /**
164
+ * Reduce an element tree to a whitespace-normalized, serializer-independent
165
+ * shape for structural comparison: tag, trimmed text, attributes (compared
166
+ * order-insensitively), and ordered children.
167
+ */
168
+ export function canonicalize(el) {
169
+ return {
170
+ tag: el.tag,
171
+ text: el.text.trim(),
172
+ attrs: Object.fromEntries(el.attrs),
173
+ children: el.children.map(canonicalize),
174
+ };
175
+ }
176
+ /**
177
+ * Attribute-first text lookup — tries ``root``'s ``name`` attribute, then the
178
+ * ``<name>`` child element's text with line breaks collapsed
179
+ * (``"".join(splitlines())``) and the result trimmed; ``null`` if neither is
180
+ * present. The shared core of ``galaxy.util.xml_text``.
181
+ */
182
+ export function xmlTextOrNull(root, name) {
183
+ const attr = root.attrs.get(name);
184
+ if (attr)
185
+ return attr;
186
+ const elem = root.findChild(name);
187
+ if (elem !== null && elem.text) {
188
+ return elem.text
189
+ .split(/\r\n|\r|\n/)
190
+ .join("")
191
+ .trim();
192
+ }
193
+ return null;
194
+ }
195
+ /** Port of ``galaxy.util.xml_text`` — {@link xmlTextOrNull} with a string default. */
196
+ export function xmlText(root, name, defaultValue = "") {
197
+ return xmlTextOrNull(root, name) ?? defaultValue;
198
+ }
199
+ /**
200
+ * Port of ``galaxy.util.string_as_bool`` — truthy for ``true``/``yes``/``on``/``1``
201
+ * (case-insensitive), false otherwise (including ``undefined``/empty string).
202
+ */
203
+ export function stringAsBool(value) {
204
+ if (value === undefined)
205
+ return false;
206
+ return ["true", "yes", "on", "1"].includes(value.toLowerCase());
207
+ }
208
+ /**
209
+ * Insert deep copies of ``targets`` where ``query`` sits among its parent's
210
+ * children, then remove ``query`` — port of ``xml_macros._xml_replace``.
211
+ */
212
+ export function xmlReplace(query, targets) {
213
+ const parent = query.parent;
214
+ if (parent === null)
215
+ throw new Error("xmlReplace: element has no parent");
216
+ const index = parent.children.indexOf(query);
217
+ if (index < 0)
218
+ throw new Error("xmlReplace: element not found in parent");
219
+ const clones = targets.map((t) => {
220
+ const c = t.clone();
221
+ c.parent = parent;
222
+ return c;
223
+ });
224
+ parent.children.splice(index, 1, ...clones);
225
+ }
226
+ //# sourceMappingURL=element.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"element.js","sourceRoot":"","sources":["../src/element.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ export { XmlElement, parseXmlToTree, canonicalize, xmlReplace, type CanonicalElement, } from "./element.js";
2
+ export { expandMacros, XmlMacroDef, type ImportResolver } from "./macros.js";
3
+ export { loadTool } from "./loader.js";
4
+ export { XmlToolSource, loadXmlToolSource, xmlToolSourceFromString, xmlToolSourceFromStringNoImports, } from "./tool-source.js";
5
+ export { parseOutputs } from "./outputs.js";
6
+ export { parseInputs, XmlPageSource, XmlInputSource } from "./inputs.js";
7
+ export { parseXmlTool, loadXmlTool, loadYamlTool, loadToolFile, parsedToolFromSource, } from "./parse.js";
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EACV,cAAc,EACd,YAAY,EACZ,UAAU,EACV,KAAK,gBAAgB,GACtB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,KAAK,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7E,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EACL,aAAa,EACb,iBAAiB,EACjB,uBAAuB,EACvB,gCAAgC,GACjC,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AACzE,OAAO,EACL,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,oBAAoB,GACrB,MAAM,YAAY,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,8 @@
1
+ export { XmlElement, parseXmlToTree, canonicalize, xmlReplace, } from "./element.js";
2
+ export { expandMacros, XmlMacroDef } from "./macros.js";
3
+ export { loadTool } from "./loader.js";
4
+ export { XmlToolSource, loadXmlToolSource, xmlToolSourceFromString, xmlToolSourceFromStringNoImports, } from "./tool-source.js";
5
+ export { parseOutputs } from "./outputs.js";
6
+ export { parseInputs, XmlPageSource, XmlInputSource } from "./inputs.js";
7
+ export { parseXmlTool, loadXmlTool, loadYamlTool, loadToolFile, parsedToolFromSource, } from "./parse.js";
8
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EACV,cAAc,EACd,YAAY,EACZ,UAAU,GAEX,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,YAAY,EAAE,WAAW,EAAuB,MAAM,aAAa,CAAC;AAC7E,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EACL,aAAa,EACb,iBAAiB,EACjB,uBAAuB,EACvB,gCAAgC,GACjC,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AACzE,OAAO,EACL,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,oBAAoB,GACrB,MAAM,YAAY,CAAC"}
@@ -0,0 +1,48 @@
1
+ import type { DrillDownOption, InputSource, InputType, LabelValue, PageSource, ToolParameterModel, ValidatorModel } from "@galaxy-tool-util/schema";
2
+ import type { XmlElement } from "./element.js";
3
+ /**
4
+ * XML-backed `InputSource` / `PageSource` — the TS port of Galaxy's
5
+ * `parser.xml.XmlInputSource` / `XmlPageSource`. It adapts an `<inputs>` tree
6
+ * (already macro-expanded) onto the seam consumed by the shared parameter-model
7
+ * factory in `@galaxy-tool-util/schema`, so XML and the inline/YAML dict path
8
+ * build the same `ToolParameterModel` union.
9
+ *
10
+ * Coercion here is XML-native: attribute reads default to string, booleans go
11
+ * through `string_as_bool`, and `parse_static_options` deduplicates `<option>`
12
+ * children by `value` (mirroring the Python source). Dynamic-option detection
13
+ * nulls a select's / drill-down's options but the option source itself is not
14
+ * modeled. Accessors the factory does not consume yet (conversion tuples,
15
+ * sanitizers) are stubbed to their empty forms and grow with the feature slices
16
+ * that need them.
17
+ */
18
+ /** Port of `XmlToolSource.parse_inputs` entry — `<inputs>` tree → models. */
19
+ export declare function parseInputs(root: XmlElement): ToolParameterModel[];
20
+ /** Port of `parser.xml.XmlPageSource`. */
21
+ export declare class XmlPageSource implements PageSource {
22
+ private readonly parentElem;
23
+ constructor(parentElem: XmlElement);
24
+ parseInputSources(): InputSource[];
25
+ }
26
+ /** Port of `parser.xml.XmlInputSource`. */
27
+ export declare class XmlInputSource implements InputSource {
28
+ private readonly inputElem;
29
+ constructor(inputElem: XmlElement);
30
+ get(key: string, defaultValue?: unknown): unknown;
31
+ getBool(key: string, defaultValue: boolean): boolean;
32
+ parseInputType(): InputType;
33
+ parseName(): string;
34
+ parseLabel(): string | null;
35
+ parseHelp(): string | null;
36
+ parseOptional(defaultValue?: boolean): boolean;
37
+ parseExtensions(): string[];
38
+ hasDynamicOptions(): boolean;
39
+ parseStaticOptions(): LabelValue[] | null;
40
+ hasDrillDownDynamicOptions(): boolean;
41
+ parseDrillDownStaticOptions(): DrillDownOption[] | null;
42
+ parseValidators(): ValidatorModel[];
43
+ parseNestedInputsSource(): PageSource;
44
+ parseTestInputSource(): InputSource;
45
+ parseWhenInputSources(): Array<[unknown, PageSource]>;
46
+ parseDefault(): unknown;
47
+ }
48
+ //# sourceMappingURL=inputs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inputs.d.ts","sourceRoot":"","sources":["../src/inputs.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,eAAe,EACf,WAAW,EACX,SAAS,EACT,UAAU,EACV,UAAU,EACV,kBAAkB,EAClB,cAAc,EACf,MAAM,0BAA0B,CAAC;AAGlC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE/C;;;;;;;;;;;;;;GAcG;AAEH,6EAA6E;AAC7E,wBAAgB,WAAW,CAAC,IAAI,EAAE,UAAU,GAAG,kBAAkB,EAAE,CAIlE;AAED,0CAA0C;AAC1C,qBAAa,aAAc,YAAW,UAAU;IAClC,OAAO,CAAC,QAAQ,CAAC,UAAU;gBAAV,UAAU,EAAE,UAAU;IAEnD,iBAAiB,IAAI,WAAW,EAAE;CAGnC;AAED,2CAA2C;AAC3C,qBAAa,cAAe,YAAW,WAAW;IACpC,OAAO,CAAC,QAAQ,CAAC,SAAS;gBAAT,SAAS,EAAE,UAAU;IAElD,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,OAAO,GAAG,OAAO;IAKjD,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,YAAY,EAAE,OAAO,GAAG,OAAO;IAKpD,cAAc,IAAI,SAAS;IAS3B,SAAS,IAAI,MAAM;IAYnB,UAAU,IAAI,MAAM,GAAG,IAAI;IAK3B,SAAS,IAAI,MAAM,GAAG,IAAI;IAI1B,aAAa,CAAC,YAAY,UAAQ,GAAG,OAAO;IAY5C,eAAe,IAAI,MAAM,EAAE;IAQ3B,iBAAiB,IAAI,OAAO;IAQ5B,kBAAkB,IAAI,UAAU,EAAE,GAAG,IAAI;IAYzC,0BAA0B,IAAI,OAAO;IAMrC,2BAA2B,IAAI,eAAe,EAAE,GAAG,IAAI;IAMvD,eAAe,IAAI,cAAc,EAAE;IAInC,uBAAuB,IAAI,UAAU;IAIrC,oBAAoB,IAAI,WAAW;IAQnC,qBAAqB,IAAI,KAAK,CAAC,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;IAMrD,YAAY,IAAI,OAAO;CAgBxB"}