@mcpher/gas-fakes 2.5.2 → 2.5.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/README.md +17 -3
- package/package.json +1 -1
- package/pngs/srv.jpg +0 -0
- package/src/cli/app.js +1 -0
- package/src/cli/togas.js +23 -14
- package/src/index.js +1 -0
- package/src/services/advslides/fakeadvslides.js +11 -5
- package/src/services/base/app.js +9 -0
- package/src/services/base/fakebase.js +28 -0
- package/src/services/common/fakeadvresource.js +3 -2
- package/src/services/content/contentservice.js +3 -2
- package/src/services/enums/baseenums.js +47 -0
- package/src/services/enums/contentenums.js +1 -3
- package/src/services/enums/scriptenums.js +31 -4
- package/src/services/enums/slidesenums.js +3 -1
- package/src/services/enums/xmlenums.js +14 -0
- package/src/services/html/serverworker.js +1 -1
- package/src/services/scriptapp/app.js +14 -7
- package/src/services/scriptapp/fakeauthorizationinfo.js +4 -4
- package/src/services/slidesapp/app.js +5 -0
- package/src/services/slidesapp/fakeautofit.js +1 -1
- package/src/services/slidesapp/fakeborder.js +106 -0
- package/src/services/slidesapp/fakecolorscheme.js +1 -1
- package/src/services/slidesapp/fakefill.js +216 -0
- package/src/services/slidesapp/fakegroup.js +35 -0
- package/src/services/slidesapp/fakeimage.js +118 -0
- package/src/services/slidesapp/fakelayout.js +351 -0
- package/src/services/slidesapp/fakeline.js +2 -2
- package/src/services/slidesapp/fakelinefill.js +15 -16
- package/src/services/slidesapp/fakelink.js +20 -3
- package/src/services/slidesapp/fakelist.js +36 -0
- package/src/services/slidesapp/fakeliststyle.js +105 -0
- package/src/services/slidesapp/fakemaster.js +358 -0
- package/src/services/slidesapp/fakenotesmaster.js +125 -0
- package/src/services/slidesapp/fakenotespage.js +102 -2
- package/src/services/slidesapp/fakepagebackground.js +109 -1
- package/src/services/slidesapp/fakepageelement.js +157 -18
- package/src/services/slidesapp/fakepageelementrange.js +28 -0
- package/src/services/slidesapp/fakepagerange.js +28 -0
- package/src/services/slidesapp/fakeparagraphstyle.js +139 -0
- package/src/services/slidesapp/fakepicturefill.js +32 -0
- package/src/services/slidesapp/fakepresentation.js +126 -2
- package/src/services/slidesapp/fakeshape.js +9 -0
- package/src/services/slidesapp/fakeslide.js +216 -24
- package/src/services/slidesapp/fakesolidfill.js +45 -0
- package/src/services/slidesapp/fakespeakerspotlight.js +18 -0
- package/src/services/slidesapp/faketable.js +55 -9
- package/src/services/slidesapp/faketablecell.js +141 -12
- package/src/services/slidesapp/faketablecellrange.js +28 -0
- package/src/services/slidesapp/faketablecolumn.js +72 -0
- package/src/services/slidesapp/faketablerow.js +31 -0
- package/src/services/slidesapp/faketextrange.js +179 -135
- package/src/services/slidesapp/faketextstyle.js +158 -0
- package/src/services/slidesapp/fakevideo.js +35 -0
- package/src/services/slidesapp/fakewordart.js +22 -0
- package/src/services/slidesapp/pageelementfactory.js +24 -1
- package/src/services/spreadsheetapp/fakeembeddedchartbuilder.js +92 -12
- package/src/services/spreadsheetapp/fakespreadsheet.js +360 -62
- package/src/services/spreadsheetapp/fakespreadsheettheme.js +53 -0
- package/src/services/urlfetchapp/app.js +216 -175
- package/src/services/xmlservice/app.js +3 -78
- package/src/services/xmlservice/fakeattribute.js +15 -0
- package/src/services/xmlservice/fakecdata.js +40 -0
- package/src/services/xmlservice/fakecomment.js +34 -0
- package/src/services/xmlservice/fakecontent.js +51 -0
- package/src/services/xmlservice/fakedoctype.js +68 -0
- package/src/services/xmlservice/fakedocument.js +110 -13
- package/src/services/xmlservice/fakeelement.js +297 -82
- package/src/services/xmlservice/fakeentityref.js +54 -0
- package/src/services/xmlservice/fakeformat.js +67 -22
- package/src/services/xmlservice/fakeprocessinginstruction.js +44 -0
- package/src/services/xmlservice/faketext.js +39 -0
- package/src/services/xmlservice/fakexmlservice.js +118 -0
- package/src/support/sxfetch.js +60 -0
- package/tools/omlx.env.example +6 -0
- package/tools/omlx_mcp_server.cjs +157 -0
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { FakeContent } from './fakecontent.js';
|
|
2
|
+
import * as Enums from '../enums/xmlenums.js';
|
|
3
|
+
|
|
4
|
+
export class FakeDocType extends FakeContent {
|
|
5
|
+
constructor(name, publicId = null, systemId = null) {
|
|
6
|
+
super(Enums.ContentTypes.DOCTYPE);
|
|
7
|
+
this._name = name || '';
|
|
8
|
+
this._publicId = publicId || '';
|
|
9
|
+
this._systemId = systemId || '';
|
|
10
|
+
this._internalSubset = '';
|
|
11
|
+
this._parent = null;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
getElementName() {
|
|
15
|
+
return this._name;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
getInternalSubset() {
|
|
19
|
+
return this._internalSubset;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
getPublicId() {
|
|
23
|
+
return this._publicId;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
getSystemId() {
|
|
27
|
+
return this._systemId;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
getValue() {
|
|
31
|
+
return '';
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
setElementName(name) {
|
|
35
|
+
this._name = name || '';
|
|
36
|
+
return this;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
setInternalSubset(data) {
|
|
40
|
+
if (data === null || data === undefined) {
|
|
41
|
+
throw new Error("Argument cannot be null: data");
|
|
42
|
+
}
|
|
43
|
+
this._internalSubset = data;
|
|
44
|
+
return this;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
setPublicId(id) {
|
|
48
|
+
this._publicId = id || '';
|
|
49
|
+
return this;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
setSystemId(id) {
|
|
53
|
+
this._systemId = id || '';
|
|
54
|
+
return this;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
detach() {
|
|
58
|
+
return super.detach();
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
getParentElement() {
|
|
62
|
+
return super.getParentElement();
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
toString() {
|
|
66
|
+
return `[DocType: ${this._name}]`;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
@@ -1,20 +1,117 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import { FakeElement } from './fakeelement.js';
|
|
2
|
+
import { FakeDocType } from './fakedoctype.js';
|
|
3
|
+
|
|
4
4
|
export class FakeDocument {
|
|
5
|
-
constructor(rootElement) {
|
|
5
|
+
constructor(rootElement = null) {
|
|
6
|
+
this._content = [];
|
|
6
7
|
this._rootElement = rootElement;
|
|
8
|
+
if (rootElement) {
|
|
9
|
+
this._content.push(rootElement);
|
|
10
|
+
if (typeof rootElement.setParentElement === 'function') {
|
|
11
|
+
rootElement.setParentElement(this);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
7
14
|
}
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
+
getRootElement() { return this._rootElement; }
|
|
16
|
+
setRootElement(element) {
|
|
17
|
+
if (this._rootElement) {
|
|
18
|
+
const idx = this._content.indexOf(this._rootElement);
|
|
19
|
+
if (idx !== -1) {
|
|
20
|
+
this._content[idx] = element;
|
|
21
|
+
}
|
|
22
|
+
if (typeof this._rootElement.setParentElement === 'function') {
|
|
23
|
+
this._rootElement.setParentElement(null);
|
|
24
|
+
}
|
|
25
|
+
} else {
|
|
26
|
+
this._content.push(element);
|
|
27
|
+
}
|
|
28
|
+
this._rootElement = element;
|
|
29
|
+
if (element && typeof element.setParentElement === 'function') {
|
|
30
|
+
element.setParentElement(this);
|
|
31
|
+
}
|
|
32
|
+
return this;
|
|
33
|
+
}
|
|
34
|
+
hasRootElement() { return !!this._rootElement; }
|
|
35
|
+
detachRootElement() {
|
|
36
|
+
const root = this._rootElement;
|
|
37
|
+
if (root) {
|
|
38
|
+
const idx = this._content.indexOf(root);
|
|
39
|
+
if (idx !== -1) this._content.splice(idx, 1);
|
|
40
|
+
if (typeof root.setParentElement === 'function') {
|
|
41
|
+
root.setParentElement(null);
|
|
42
|
+
}
|
|
43
|
+
this._rootElement = null;
|
|
44
|
+
}
|
|
45
|
+
return root;
|
|
46
|
+
}
|
|
47
|
+
getDocType() {
|
|
48
|
+
return this._content.find(c => c instanceof FakeDocType) || null;
|
|
49
|
+
}
|
|
50
|
+
setDocType(doctype) {
|
|
51
|
+
const existing = this.getDocType();
|
|
52
|
+
if (existing) {
|
|
53
|
+
const idx = this._content.indexOf(existing);
|
|
54
|
+
this._content[idx] = doctype;
|
|
55
|
+
} else {
|
|
56
|
+
this._content.unshift(doctype);
|
|
57
|
+
}
|
|
58
|
+
if (doctype && typeof doctype.setParentElement === 'function') {
|
|
59
|
+
doctype.setParentElement(this);
|
|
60
|
+
}
|
|
61
|
+
return this;
|
|
62
|
+
}
|
|
63
|
+
addContent(content, index = null) {
|
|
64
|
+
if (content instanceof FakeElement) {
|
|
65
|
+
if (this.hasRootElement()) {
|
|
66
|
+
throw new Error("XmlService: Document already has a root element");
|
|
67
|
+
}
|
|
68
|
+
this._rootElement = content;
|
|
69
|
+
}
|
|
70
|
+
if (content && typeof content.setParentElement === 'function') {
|
|
71
|
+
content.setParentElement(this);
|
|
72
|
+
}
|
|
73
|
+
if (index === null) {
|
|
74
|
+
this._content.push(content);
|
|
75
|
+
} else {
|
|
76
|
+
this._content.splice(index, 0, content);
|
|
77
|
+
}
|
|
78
|
+
return this;
|
|
79
|
+
}
|
|
80
|
+
cloneContent() {
|
|
81
|
+
return [...this._content];
|
|
82
|
+
}
|
|
83
|
+
getAllContent() { return [...this._content]; }
|
|
84
|
+
getContent(index) { return this._content[index] || null; }
|
|
85
|
+
getContentSize() { return this._content.length; }
|
|
86
|
+
getDescendants() {
|
|
87
|
+
const descendants = [];
|
|
88
|
+
const traverse = (node) => {
|
|
89
|
+
descendants.push(node);
|
|
90
|
+
if (node instanceof FakeElement) {
|
|
91
|
+
node.getChildren().forEach(child => traverse(child));
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
this._content.forEach(c => traverse(c));
|
|
95
|
+
return descendants;
|
|
96
|
+
}
|
|
97
|
+
removeContent(contentOrIndex) {
|
|
98
|
+
if (typeof contentOrIndex === 'number') {
|
|
99
|
+
const removed = this._content.splice(contentOrIndex, 1)[0];
|
|
100
|
+
if (removed === this._rootElement) this._rootElement = null;
|
|
101
|
+
return removed || null;
|
|
102
|
+
} else {
|
|
103
|
+
const idx = this._content.indexOf(contentOrIndex);
|
|
104
|
+
if (idx !== -1) {
|
|
105
|
+
this._content.splice(idx, 1);
|
|
106
|
+
if (contentOrIndex === this._rootElement) this._rootElement = null;
|
|
107
|
+
return true;
|
|
108
|
+
}
|
|
109
|
+
return false;
|
|
110
|
+
}
|
|
15
111
|
}
|
|
16
|
-
|
|
17
112
|
toString() {
|
|
18
|
-
|
|
113
|
+
const rootName = this._rootElement ? this._rootElement.getName() : '';
|
|
114
|
+
const hasDocType = this.getDocType() ? 'has DOCTYPE declaration' : 'No DOCTYPE declaration';
|
|
115
|
+
return `[Document: ${hasDocType}, Root is [Element: <${rootName}/>]]`;
|
|
19
116
|
}
|
|
20
117
|
}
|
|
@@ -1,128 +1,343 @@
|
|
|
1
|
+
import { FakeAttribute } from './fakeattribute.js';
|
|
2
|
+
import { FakeContent } from './fakecontent.js';
|
|
3
|
+
import { FakeText } from './faketext.js';
|
|
4
|
+
import * as Enums from '../enums/xmlenums.js';
|
|
5
|
+
|
|
1
6
|
/**
|
|
2
|
-
*
|
|
7
|
+
* Represents a fake XML Element node.
|
|
8
|
+
* Inherits from FakeContent.
|
|
3
9
|
*/
|
|
4
|
-
export class FakeElement {
|
|
10
|
+
export class FakeElement extends FakeContent {
|
|
11
|
+
/**
|
|
12
|
+
* @param {string} name - The qualified name (e.g., "ns:tag").
|
|
13
|
+
* @param {Object} data - Initial data structure (attributes, children, #text).
|
|
14
|
+
* @param {FakeContent | null} parent - The parent element.
|
|
15
|
+
*/
|
|
5
16
|
constructor(name, data = {}, parent = null) {
|
|
17
|
+
super(Enums.ContentTypes.ELEMENT);
|
|
18
|
+
|
|
6
19
|
const parts = name.split(':');
|
|
7
20
|
this._localName = parts.pop();
|
|
8
21
|
this._prefix = parts.length > 0 ? parts[0] : "";
|
|
9
22
|
this._qualifiedName = name;
|
|
10
|
-
this._data = data
|
|
23
|
+
this._data = data || {};
|
|
11
24
|
this._parent = parent;
|
|
25
|
+
this._namespace = null;
|
|
26
|
+
this._content = [];
|
|
27
|
+
this._contentInitialized = false;
|
|
12
28
|
}
|
|
13
29
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
* @return {string} The local name of the element.
|
|
17
|
-
*/
|
|
30
|
+
// --- Core Properties & Getters ---
|
|
31
|
+
|
|
18
32
|
getName() {
|
|
19
33
|
return this._localName;
|
|
20
34
|
}
|
|
21
35
|
|
|
22
|
-
/**
|
|
23
|
-
* Returns the full qualified name of the element.
|
|
24
|
-
* (Not part of GAS public API, but useful internally)
|
|
25
|
-
*/
|
|
26
36
|
getQualifiedName() {
|
|
27
37
|
return this._qualifiedName;
|
|
28
38
|
}
|
|
29
39
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
40
|
+
getNamespace(prefix) {
|
|
41
|
+
if (prefix === undefined) {
|
|
42
|
+
return this._namespace;
|
|
43
|
+
}
|
|
44
|
+
if (this._namespace && this._namespace.getPrefix() === prefix) {
|
|
45
|
+
return this._namespace;
|
|
46
|
+
}
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
setNamespace(namespace) {
|
|
51
|
+
this._namespace = namespace;
|
|
52
|
+
return this;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
setName(name) {
|
|
56
|
+
this._localName = name;
|
|
57
|
+
this._qualifiedName = this._prefix ? `${this._prefix}:${name}` : name;
|
|
58
|
+
return this;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// --- Lazy Content Loader ---
|
|
62
|
+
|
|
63
|
+
_ensureContent() {
|
|
64
|
+
if (this._contentInitialized) return;
|
|
65
|
+
this._contentInitialized = true;
|
|
66
|
+
this._content = [];
|
|
67
|
+
if (!this._data || typeof this._data !== 'object') return;
|
|
68
|
+
|
|
69
|
+
// Load text if present
|
|
70
|
+
if (this._data['#text']) {
|
|
71
|
+
const textNode = new FakeText(this._data['#text']);
|
|
72
|
+
textNode.setParentElement(this);
|
|
73
|
+
this._content.push(textNode);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Load child elements
|
|
77
|
+
Object.keys(this._data).forEach(key => {
|
|
78
|
+
if (key.startsWith('@_') || key === '#text') return;
|
|
79
|
+
const childData = this._data[key];
|
|
80
|
+
if (Array.isArray(childData)) {
|
|
81
|
+
childData.forEach(d => {
|
|
82
|
+
const childEl = new FakeElement(key, d, this);
|
|
83
|
+
this._content.push(childEl);
|
|
84
|
+
});
|
|
85
|
+
} else {
|
|
86
|
+
const childEl = new FakeElement(key, childData, this);
|
|
87
|
+
this._content.push(childEl);
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
_syncData() {
|
|
93
|
+
const attrs = {};
|
|
36
94
|
if (this._data && typeof this._data === 'object') {
|
|
37
|
-
|
|
38
|
-
|
|
95
|
+
Object.keys(this._data).forEach(key => {
|
|
96
|
+
if (key.startsWith('@_')) {
|
|
97
|
+
attrs[key] = this._data[key];
|
|
98
|
+
}
|
|
99
|
+
});
|
|
39
100
|
}
|
|
40
|
-
|
|
101
|
+
this._data = attrs;
|
|
102
|
+
|
|
103
|
+
this._content.forEach(c => {
|
|
104
|
+
if (c instanceof FakeElement) {
|
|
105
|
+
const key = c.getQualifiedName();
|
|
106
|
+
if (!this._data[key]) {
|
|
107
|
+
this._data[key] = c._data;
|
|
108
|
+
} else if (Array.isArray(this._data[key])) {
|
|
109
|
+
this._data[key].push(c._data);
|
|
110
|
+
} else {
|
|
111
|
+
this._data[key] = [this._data[key], c._data];
|
|
112
|
+
}
|
|
113
|
+
} else {
|
|
114
|
+
const textVal = c.getText ? c.getText() : (c.getValue ? c.getValue() : "");
|
|
115
|
+
if (!this._data['#text']) {
|
|
116
|
+
this._data['#text'] = textVal;
|
|
117
|
+
} else {
|
|
118
|
+
this._data['#text'] += textVal;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// --- Content Accessors ---
|
|
125
|
+
|
|
126
|
+
getText() {
|
|
127
|
+
this._ensureContent();
|
|
128
|
+
return this._content
|
|
129
|
+
.filter(c => c.getType() === Enums.ContentTypes.TEXT || c.getType() === Enums.ContentTypes.CDATA)
|
|
130
|
+
.map(c => c.getValue())
|
|
131
|
+
.join('');
|
|
41
132
|
}
|
|
42
133
|
|
|
43
|
-
/**
|
|
44
|
-
* Returns the value of the element.
|
|
45
|
-
* @return {string} The value of the element.
|
|
46
|
-
*/
|
|
47
134
|
getValue() {
|
|
48
135
|
return this.getText();
|
|
49
136
|
}
|
|
50
137
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
* @param {string} name The name of the child element.
|
|
54
|
-
* @param {FakeNamespace} namespace Optional namespace.
|
|
55
|
-
* @return {FakeElement} The child element, or null if not found.
|
|
56
|
-
*/
|
|
138
|
+
// --- Child/Descendant Navigation ---
|
|
139
|
+
|
|
57
140
|
getChild(name, namespace) {
|
|
58
141
|
const children = this.getChildren(name, namespace);
|
|
59
142
|
return children.length > 0 ? children[0] : null;
|
|
60
143
|
}
|
|
61
144
|
|
|
62
|
-
/**
|
|
63
|
-
* Returns all child elements.
|
|
64
|
-
* @param {string} name Optional name of the child elements.
|
|
65
|
-
* @param {FakeNamespace} namespace Optional namespace.
|
|
66
|
-
* @return {FakeElement[]} The child elements.
|
|
67
|
-
*/
|
|
68
145
|
getChildren(name, namespace) {
|
|
146
|
+
this._ensureContent();
|
|
147
|
+
let result = this._content.filter(c => c instanceof FakeElement);
|
|
148
|
+
if (name) {
|
|
149
|
+
let targetKey = name;
|
|
150
|
+
if (namespace) {
|
|
151
|
+
const prefix = namespace.getPrefix();
|
|
152
|
+
targetKey = prefix ? `${prefix}:${name}` : name;
|
|
153
|
+
}
|
|
154
|
+
result = result.filter(c => c.getQualifiedName() === targetKey);
|
|
155
|
+
}
|
|
156
|
+
return result;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
getChildText(name, namespace) {
|
|
160
|
+
const child = this.getChild(name, namespace);
|
|
161
|
+
return child ? child.getText() : '';
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
getDescendants() {
|
|
165
|
+
this._ensureContent();
|
|
166
|
+
const descendants = [];
|
|
167
|
+
const traverse = (node) => {
|
|
168
|
+
descendants.push(node);
|
|
169
|
+
if (node instanceof FakeElement) {
|
|
170
|
+
node._ensureContent();
|
|
171
|
+
node._content.forEach(child => traverse(child));
|
|
172
|
+
}
|
|
173
|
+
};
|
|
174
|
+
this._content.forEach(c => traverse(c));
|
|
175
|
+
return descendants;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// --- Attribute Management ---
|
|
179
|
+
|
|
180
|
+
getAttribute(name, namespace = null) {
|
|
181
|
+
if (!this._data || typeof this._data !== 'object') return null;
|
|
182
|
+
const attrValue = this._data[`@_${name}`];
|
|
183
|
+
if (attrValue === undefined) return null;
|
|
184
|
+
return new FakeAttribute(name, String(attrValue), namespace);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
getAttributes() {
|
|
69
188
|
if (!this._data || typeof this._data !== 'object') return [];
|
|
189
|
+
return Object.keys(this._data)
|
|
190
|
+
.filter(key => key.startsWith('@_'))
|
|
191
|
+
.map(key => {
|
|
192
|
+
const name = key.slice(2);
|
|
193
|
+
return new FakeAttribute(name, String(this._data[key]));
|
|
194
|
+
});
|
|
195
|
+
}
|
|
70
196
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
// If user passed "ns:child", it might work in our fake even if not in GAS
|
|
78
|
-
targetKey = name;
|
|
197
|
+
setAttribute(name, value, namespace = null) {
|
|
198
|
+
if (typeof name === 'object') {
|
|
199
|
+
const attr = name;
|
|
200
|
+
this._data[`@_${attr.getName()}`] = String(attr.getValue());
|
|
201
|
+
} else {
|
|
202
|
+
this._data[`@_${name}`] = String(value);
|
|
79
203
|
}
|
|
204
|
+
return this;
|
|
205
|
+
}
|
|
80
206
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
207
|
+
removeAttribute(name, namespace = null) {
|
|
208
|
+
const key = typeof name === 'object' ? `@_${name.getName()}` : `@_${name}`;
|
|
209
|
+
if (this._data && this._data[key] !== undefined) {
|
|
210
|
+
delete this._data[key];
|
|
211
|
+
return true;
|
|
212
|
+
}
|
|
213
|
+
return false;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// --- Text Content Management ---
|
|
217
|
+
|
|
218
|
+
setText(text) {
|
|
219
|
+
this._ensureContent();
|
|
220
|
+
this._content = this._content.filter(c => c.getType() !== Enums.ContentTypes.TEXT && c.getType() !== Enums.ContentTypes.CDATA);
|
|
221
|
+
const textNode = new FakeText(text);
|
|
222
|
+
textNode.setParentElement(this);
|
|
223
|
+
this._content.push(textNode);
|
|
224
|
+
this._syncData();
|
|
225
|
+
return this;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// --- Parent/Structure Management ---
|
|
229
|
+
|
|
230
|
+
setParentElement(parent) {
|
|
231
|
+
this._parent = parent;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
getParentElement() {
|
|
235
|
+
return this._parent;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
isRootElement() {
|
|
239
|
+
return this._parent === null;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
isAncestorOf(element) {
|
|
243
|
+
let current = element.getParentElement();
|
|
244
|
+
while (current) {
|
|
245
|
+
if (current === this) return true;
|
|
246
|
+
current = current.getParentElement();
|
|
247
|
+
}
|
|
248
|
+
return false;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
getDocument() {
|
|
252
|
+
let current = this;
|
|
253
|
+
while (current._parent) {
|
|
254
|
+
if (current._parent.constructor && current._parent.constructor.name === 'FakeDocument') {
|
|
255
|
+
return current._parent;
|
|
86
256
|
}
|
|
87
|
-
|
|
257
|
+
current = current._parent;
|
|
88
258
|
}
|
|
259
|
+
return null;
|
|
260
|
+
}
|
|
89
261
|
|
|
90
|
-
|
|
91
|
-
return
|
|
92
|
-
.filter(key => !key.startsWith('@_') && key !== '#text')
|
|
93
|
-
.flatMap(key => {
|
|
94
|
-
const d = this._data[key];
|
|
95
|
-
if (Array.isArray(d)) {
|
|
96
|
-
return d.map(item => new FakeElement(key, item, this));
|
|
97
|
-
}
|
|
98
|
-
return new FakeElement(key, d, this);
|
|
99
|
-
});
|
|
262
|
+
detach() {
|
|
263
|
+
return super.detach();
|
|
100
264
|
}
|
|
101
265
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
*/
|
|
107
|
-
getAttribute(name) {
|
|
108
|
-
if (!this._data || typeof this._data !== 'object') return null;
|
|
109
|
-
const attrValue = this._data[`@_${name}`];
|
|
110
|
-
if (attrValue === undefined) return null;
|
|
111
|
-
return {
|
|
112
|
-
getName: () => name,
|
|
113
|
-
getValue: () => String(attrValue)
|
|
114
|
-
};
|
|
266
|
+
// --- Content Manipulation ---
|
|
267
|
+
|
|
268
|
+
addChild(element) {
|
|
269
|
+
return this.addContent(element);
|
|
115
270
|
}
|
|
116
271
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
272
|
+
addContent(content, index = null) {
|
|
273
|
+
this._ensureContent();
|
|
274
|
+
if (typeof content.setParentElement === 'function') {
|
|
275
|
+
content.setParentElement(this);
|
|
276
|
+
}
|
|
277
|
+
if (index === null) {
|
|
278
|
+
this._content.push(content);
|
|
279
|
+
} else {
|
|
280
|
+
this._content.splice(index, 0, content);
|
|
281
|
+
}
|
|
282
|
+
this._syncData();
|
|
283
|
+
return this;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
removeContent(contentOrIndex) {
|
|
287
|
+
this._ensureContent();
|
|
288
|
+
if (contentOrIndex === undefined) {
|
|
289
|
+
const old = [...this._content];
|
|
290
|
+
this._content = [];
|
|
291
|
+
this._syncData();
|
|
292
|
+
return old;
|
|
293
|
+
}
|
|
294
|
+
if (typeof contentOrIndex === 'number') {
|
|
295
|
+
const removed = this._content.splice(contentOrIndex, 1)[0];
|
|
296
|
+
if (removed) {
|
|
297
|
+
removed.setParentElement(null);
|
|
298
|
+
this._syncData();
|
|
299
|
+
}
|
|
300
|
+
return removed || null;
|
|
301
|
+
} else {
|
|
302
|
+
const idx = this._content.indexOf(contentOrIndex);
|
|
303
|
+
if (idx !== -1) {
|
|
304
|
+
this._content.splice(idx, 1);
|
|
305
|
+
contentOrIndex.setParentElement(null);
|
|
306
|
+
this._syncData();
|
|
307
|
+
return true;
|
|
308
|
+
}
|
|
309
|
+
return false;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
cloneContent() {
|
|
314
|
+
this._ensureContent();
|
|
315
|
+
return this._content.map(c => {
|
|
316
|
+
if (c instanceof FakeElement) {
|
|
317
|
+
return new FakeElement(c.getQualifiedName(), JSON.parse(JSON.stringify(c._data)));
|
|
318
|
+
} else if (c.getType) {
|
|
319
|
+
const text = c.getText ? c.getText() : (c.getValue ? c.getValue() : "");
|
|
320
|
+
if (c.asCdata()) return new FakeCdata(text);
|
|
321
|
+
if (c.asComment()) return new FakeComment(text);
|
|
322
|
+
if (c.asText()) return new FakeText(text);
|
|
323
|
+
}
|
|
324
|
+
return c;
|
|
325
|
+
});
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
getAllContent() {
|
|
329
|
+
this._ensureContent();
|
|
330
|
+
return [...this._content];
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
getContent(index) {
|
|
334
|
+
this._ensureContent();
|
|
335
|
+
return this._content[index] || null;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
getContentSize() {
|
|
339
|
+
this._ensureContent();
|
|
340
|
+
return this._content.length;
|
|
126
341
|
}
|
|
127
342
|
|
|
128
343
|
toString() {
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { FakeContent } from './fakecontent.js';
|
|
2
|
+
import * as Enums from '../enums/xmlenums.js';
|
|
3
|
+
|
|
4
|
+
export class FakeEntityRef extends FakeContent {
|
|
5
|
+
constructor(name = '', publicId = null, systemId = null) {
|
|
6
|
+
super(Enums.ContentTypes.ENTITYREF);
|
|
7
|
+
this._name = name;
|
|
8
|
+
this._publicId = publicId;
|
|
9
|
+
this._systemId = systemId;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
getName() {
|
|
13
|
+
return this._name;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
setName(name) {
|
|
17
|
+
this._name = name;
|
|
18
|
+
return this;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
getPublicId() {
|
|
22
|
+
return this._publicId;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
setPublicId(id) {
|
|
26
|
+
this._publicId = id;
|
|
27
|
+
return this;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
getSystemId() {
|
|
31
|
+
return this._systemId;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
setSystemId(id) {
|
|
35
|
+
this._systemId = id;
|
|
36
|
+
return this;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
getValue() {
|
|
40
|
+
return '';
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
detach() {
|
|
44
|
+
return super.detach();
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
getParentElement() {
|
|
48
|
+
return super.getParentElement();
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
toString() {
|
|
52
|
+
return `[EntityRef: &${this._name};]`;
|
|
53
|
+
}
|
|
54
|
+
}
|