@mcpher/gas-fakes 2.5.4 → 2.5.6

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.
Files changed (30) hide show
  1. package/.claspignore +1 -1
  2. package/README.md +27 -1
  3. package/exgcp.sh +63 -0
  4. package/package.json +1 -1
  5. package/src/services/advslides/fakeadvslides.js +20 -1
  6. package/src/services/documentapp/appenderhelpers.js +8 -3
  7. package/src/services/documentapp/elementhelpers.js +148 -7
  8. package/src/services/documentapp/elementoptions.js +40 -0
  9. package/src/services/documentapp/elements.js +7 -0
  10. package/src/services/documentapp/fakebookmark.js +1 -3
  11. package/src/services/documentapp/fakecontainerelement.js +188 -0
  12. package/src/services/documentapp/fakedate.js +92 -0
  13. package/src/services/documentapp/fakedocument.js +51 -0
  14. package/src/services/documentapp/fakedocumenttab.js +9 -25
  15. package/src/services/documentapp/fakeelement.js +453 -90
  16. package/src/services/documentapp/fakeequation.js +28 -0
  17. package/src/services/documentapp/fakeequationfunction.js +37 -0
  18. package/src/services/documentapp/fakeequationfunctionargumentseparator.js +28 -0
  19. package/src/services/documentapp/fakeequationsymbol.js +37 -0
  20. package/src/services/documentapp/fakefootersection.js +64 -1
  21. package/src/services/documentapp/fakeheadersection.js +64 -0
  22. package/src/services/documentapp/fakeperson.js +67 -0
  23. package/src/services/documentapp/fakerangeelement.js +27 -1
  24. package/src/services/documentapp/fakerichlink.js +79 -0
  25. package/src/services/documentapp/fakesectionelement.js +51 -12
  26. package/src/services/documentapp/faketablecell.js +98 -0
  27. package/src/services/documentapp/nrhelpers.js +2 -1
  28. package/src/services/documentapp/shadowdocument.js +19 -2
  29. package/src/services/spreadsheetapp/fakeembeddedchartbuilder.js +2 -7
  30. package/src/support/sxslides.js +5 -4
@@ -0,0 +1,28 @@
1
+ /**
2
+ * @file Provides a fake implementation of the EquationFunctionArgumentSeparator class.
3
+ */
4
+
5
+ import { Proxies } from '../../support/proxies.js';
6
+ import { FakeElement } from './fakeelement.js';
7
+ import { registerElement } from './elementRegistry.js';
8
+
9
+ /**
10
+ * A fake implementation of the EquationFunctionArgumentSeparator class.
11
+ * @class
12
+ * @extends {FakeElement}
13
+ * @implements {GoogleAppsScript.Document.EquationFunctionArgumentSeparator}
14
+ * @see https://developers.google.com/apps-script/reference/document/equation-function-argument-separator
15
+ */
16
+ export class FakeEquationFunctionArgumentSeparator extends FakeElement {
17
+ constructor(shadowDocument, nameOrItem) {
18
+ super(shadowDocument, nameOrItem);
19
+ }
20
+ }
21
+
22
+ /**
23
+ * Creates a new fake EquationFunctionArgumentSeparator.
24
+ * @param {...any} args The arguments for the FakeEquationFunctionArgumentSeparator constructor.
25
+ * @returns {FakeEquationFunctionArgumentSeparator} A new proxied FakeEquationFunctionArgumentSeparator instance.
26
+ */
27
+ export const newFakeEquationFunctionArgumentSeparator = (...args) => Proxies.guard(new FakeEquationFunctionArgumentSeparator(...args));
28
+ registerElement('EQUATION_FUNCTION_ARGUMENT_SEPARATOR', newFakeEquationFunctionArgumentSeparator);
@@ -0,0 +1,37 @@
1
+ /**
2
+ * @file Provides a fake implementation of the EquationSymbol class.
3
+ */
4
+
5
+ import { Proxies } from '../../support/proxies.js';
6
+ import { FakeElement } from './fakeelement.js';
7
+ import { registerElement } from './elementRegistry.js';
8
+
9
+ /**
10
+ * A fake implementation of the EquationSymbol class.
11
+ * @class
12
+ * @extends {FakeElement}
13
+ * @implements {GoogleAppsScript.Document.EquationSymbol}
14
+ * @see https://developers.google.com/apps-script/reference/document/equation-symbol
15
+ */
16
+ export class FakeEquationSymbol extends FakeElement {
17
+ constructor(shadowDocument, nameOrItem) {
18
+ super(shadowDocument, nameOrItem);
19
+ }
20
+
21
+ /**
22
+ * Retrieves the code corresponding to the equation symbol.
23
+ * @returns {string} the symbol code
24
+ * @see https://developers.google.com/apps-script/reference/document/equation-symbol#getCode()
25
+ */
26
+ getCode() {
27
+ return this.__elementMapItem.equationSymbolStyle?.code || "";
28
+ }
29
+ }
30
+
31
+ /**
32
+ * Creates a new fake EquationSymbol.
33
+ * @param {...any} args The arguments for the FakeEquationSymbol constructor.
34
+ * @returns {FakeEquationSymbol} A new proxied FakeEquationSymbol instance.
35
+ */
36
+ export const newFakeEquationSymbol = (...args) => Proxies.guard(new FakeEquationSymbol(...args));
37
+ registerElement('EQUATION_SYMBOL', newFakeEquationSymbol);
@@ -17,7 +17,6 @@ export const newFakeFooterSection = (...args) => {
17
17
  /**
18
18
  * A fake implementation of the FooterSection class for DocumentApp.
19
19
  * @class FakeFooterSection
20
- * @extends {FakeContainerElement}
21
20
  * @extends {FakeSectionElement}
22
21
  * @implements {GoogleAppsScript.Document.FooterSection}
23
22
  * @see https://developers.google.com/apps-script/reference/document/footer-section
@@ -39,6 +38,70 @@ class FakeFooterSection extends FakeSectionElement {
39
38
  toString() {
40
39
  return 'FooterSection';
41
40
  }
41
+
42
+ appendHorizontalRule() {
43
+ return super.appendHorizontalRule();
44
+ }
45
+
46
+ appendImage(image) {
47
+ return super.appendImage(image);
48
+ }
49
+
50
+ appendListItem(listItemOrText) {
51
+ return super.appendListItem(listItemOrText);
52
+ }
53
+
54
+ appendParagraph(paragraphOrText) {
55
+ return super.appendParagraph(paragraphOrText);
56
+ }
57
+
58
+ appendTable(tableOrCells) {
59
+ return super.appendTable(tableOrCells);
60
+ }
61
+
62
+ clear() {
63
+ return super.clear();
64
+ }
65
+
66
+ editAsText() {
67
+ return super.editAsText();
68
+ }
69
+
70
+ getText() {
71
+ return super.getText();
72
+ }
73
+
74
+ insertHorizontalRule(childIndex) {
75
+ return super.insertHorizontalRule(childIndex);
76
+ }
77
+
78
+ insertImage(childIndex, image) {
79
+ return super.insertImage(childIndex, image);
80
+ }
81
+
82
+ insertListItem(childIndex, listItemOrText) {
83
+ return super.insertListItem(childIndex, listItemOrText);
84
+ }
85
+
86
+ insertParagraph(childIndex, paragraph) {
87
+ return super.insertParagraph(childIndex, paragraph);
88
+ }
89
+
90
+ insertTable(childIndex, table) {
91
+ return super.insertTable(childIndex, table);
92
+ }
93
+
94
+ removeChild(child) {
95
+ return super.removeChild(child);
96
+ }
97
+
98
+ setText(text) {
99
+ return super.setText(text);
100
+ }
101
+
102
+ removeFromParent() {
103
+ return super.removeFromParent();
104
+ }
42
105
  }
43
106
 
44
107
  registerElement('FOOTER_SECTION', newFakeFooterSection);
@@ -39,6 +39,70 @@ class FakeHeaderSection extends FakeSectionElement {
39
39
  toString() {
40
40
  return 'HeaderSection';
41
41
  }
42
+
43
+ appendHorizontalRule() {
44
+ return super.appendHorizontalRule();
45
+ }
46
+
47
+ appendImage(image) {
48
+ return super.appendImage(image);
49
+ }
50
+
51
+ appendListItem(listItemOrText) {
52
+ return super.appendListItem(listItemOrText);
53
+ }
54
+
55
+ appendParagraph(paragraphOrText) {
56
+ return super.appendParagraph(paragraphOrText);
57
+ }
58
+
59
+ appendTable(tableOrCells) {
60
+ return super.appendTable(tableOrCells);
61
+ }
62
+
63
+ clear() {
64
+ return super.clear();
65
+ }
66
+
67
+ editAsText() {
68
+ return super.editAsText();
69
+ }
70
+
71
+ getText() {
72
+ return super.getText();
73
+ }
74
+
75
+ insertHorizontalRule(childIndex) {
76
+ return super.insertHorizontalRule(childIndex);
77
+ }
78
+
79
+ insertImage(childIndex, image) {
80
+ return super.insertImage(childIndex, image);
81
+ }
82
+
83
+ insertListItem(childIndex, listItemOrText) {
84
+ return super.insertListItem(childIndex, listItemOrText);
85
+ }
86
+
87
+ insertParagraph(childIndex, paragraph) {
88
+ return super.insertParagraph(childIndex, paragraph);
89
+ }
90
+
91
+ insertTable(childIndex, table) {
92
+ return super.insertTable(childIndex, table);
93
+ }
94
+
95
+ removeChild(child) {
96
+ return super.removeChild(child);
97
+ }
98
+
99
+ setText(text) {
100
+ return super.setText(text);
101
+ }
102
+
103
+ removeFromParent() {
104
+ return super.removeFromParent();
105
+ }
42
106
  }
43
107
 
44
108
  registerElement('HEADER_SECTION', newFakeHeaderSection);
@@ -0,0 +1,67 @@
1
+ /**
2
+ * @file Provides a fake implementation of the Person class.
3
+ */
4
+ import { Proxies } from '../../support/proxies.js';
5
+ import { signatureArgs } from '../../support/helpers.js';
6
+ import { Utils } from '../../support/utils.js';
7
+ import { FakeElement } from './fakeelement.js';
8
+ import { registerElement } from './elementRegistry.js';
9
+
10
+ const { is } = Utils;
11
+
12
+ /**
13
+ * Creates a new proxied FakePerson instance.
14
+ * @param {...any} args The arguments for the FakePerson constructor.
15
+ * @returns {FakePerson} A new proxied FakePerson instance.
16
+ */
17
+ export const newFakePerson = (...args) => {
18
+ return Proxies.guard(new FakePerson(...args));
19
+ };
20
+
21
+ /**
22
+ * A fake implementation of the Person class for DocumentApp.
23
+ * @class FakePerson
24
+ * @extends {FakeElement}
25
+ * @implements {GoogleAppsScript.Document.Person}
26
+ * @see https://developers.google.com/apps-script/reference/document/person
27
+ */
28
+ export class FakePerson extends FakeElement {
29
+ /**
30
+ * @param {import('./shadowdocument.js').ShadowDocument} shadowDocument The shadow document manager.
31
+ * @param {string|object} nameOrItem The name of the element or the element's API resource.
32
+ * @private
33
+ */
34
+ constructor(shadowDocument, nameOrItem) {
35
+ super(shadowDocument, nameOrItem);
36
+ }
37
+
38
+ /**
39
+ * Returns the person's email address.
40
+ * @returns {string} The email address of the person.
41
+ */
42
+ getEmail() {
43
+ const { nargs, matchThrow } = signatureArgs(arguments, 'Person.getEmail');
44
+ if (nargs !== 0) matchThrow();
45
+
46
+ const person = this.__elementMapItem.person;
47
+ return person ? person.personId : null;
48
+ }
49
+
50
+ /**
51
+ * Returns the person's display name, if set.
52
+ * @returns {string} The display name of the person link.
53
+ */
54
+ getName() {
55
+ const { nargs, matchThrow } = signatureArgs(arguments, 'Person.getName');
56
+ if (nargs !== 0) matchThrow();
57
+
58
+ const person = this.__elementMapItem.person;
59
+ return person?.personProperties ? person.personProperties.name : null;
60
+ }
61
+
62
+ toString() {
63
+ return 'Person';
64
+ }
65
+ }
66
+
67
+ registerElement('PERSON', newFakePerson);
@@ -9,8 +9,10 @@
9
9
  * @see https://developers.google.com/apps-script/reference/document/range-element
10
10
  */
11
11
  export class FakeRangeElement {
12
- constructor({ element }) {
12
+ constructor({ element, startOffset = -1, endOffsetInclusive = -1 }) {
13
13
  this.element = element;
14
+ this.startOffset = startOffset;
15
+ this.endOffsetInclusive = endOffsetInclusive;
14
16
  }
15
17
 
16
18
  /**
@@ -21,6 +23,30 @@ export class FakeRangeElement {
21
23
  getElement() {
22
24
  return this.element;
23
25
  }
26
+
27
+ /**
28
+ * Gets the position of the start of a partial range within the range element.
29
+ * @returns {number} the index of the first character in the range, or -1
30
+ */
31
+ getStartOffset() {
32
+ return this.startOffset;
33
+ }
34
+
35
+ /**
36
+ * Gets the position of the end of a partial range within the range element.
37
+ * @returns {number} the index of the last character in the range, or -1
38
+ */
39
+ getEndOffsetInclusive() {
40
+ return this.endOffsetInclusive;
41
+ }
42
+
43
+ /**
44
+ * Determines whether this range element covers the entire element or a partial selection.
45
+ * @returns {boolean} true if the element is partially included
46
+ */
47
+ isPartial() {
48
+ return this.startOffset !== -1 || this.endOffsetInclusive !== -1;
49
+ }
24
50
  }
25
51
 
26
52
  /**
@@ -0,0 +1,79 @@
1
+ /**
2
+ * @file Provides a fake implementation of the RichLink class.
3
+ */
4
+ import { Proxies } from '../../support/proxies.js';
5
+ import { signatureArgs } from '../../support/helpers.js';
6
+ import { Utils } from '../../support/utils.js';
7
+ import { FakeElement } from './fakeelement.js';
8
+ import { registerElement } from './elementRegistry.js';
9
+
10
+ const { is } = Utils;
11
+
12
+ /**
13
+ * Creates a new proxied FakeRichLink instance.
14
+ * @param {...any} args The arguments for the FakeRichLink constructor.
15
+ * @returns {FakeRichLink} A new proxied FakeRichLink instance.
16
+ */
17
+ export const newFakeRichLink = (...args) => {
18
+ return Proxies.guard(new FakeRichLink(...args));
19
+ };
20
+
21
+ /**
22
+ * A fake implementation of the RichLink class for DocumentApp.
23
+ * @class FakeRichLink
24
+ * @extends {FakeElement}
25
+ * @implements {GoogleAppsScript.Document.RichLink}
26
+ * @see https://developers.google.com/apps-script/reference/document/rich-link
27
+ */
28
+ export class FakeRichLink extends FakeElement {
29
+ /**
30
+ * @param {import('./shadowdocument.js').ShadowDocument} shadowDocument The shadow document manager.
31
+ * @param {string|object} nameOrItem The name of the element or the element's API resource.
32
+ * @private
33
+ */
34
+ constructor(shadowDocument, nameOrItem) {
35
+ super(shadowDocument, nameOrItem);
36
+ }
37
+
38
+ /**
39
+ * Returns the MIME type of the link.
40
+ * @returns {string|null} The MIME type of the link.
41
+ */
42
+ getMimeType() {
43
+ const { nargs, matchThrow } = signatureArgs(arguments, 'RichLink.getMimeType');
44
+ if (nargs !== 0) matchThrow();
45
+
46
+ const richLink = this.__elementMapItem.richLink;
47
+ return richLink?.richLinkProperties ? richLink.richLinkProperties.mimeType : null;
48
+ }
49
+
50
+ /**
51
+ * Returns the link's displayed title.
52
+ * @returns {string} The display title of the link.
53
+ */
54
+ getTitle() {
55
+ const { nargs, matchThrow } = signatureArgs(arguments, 'RichLink.getTitle');
56
+ if (nargs !== 0) matchThrow();
57
+
58
+ const richLink = this.__elementMapItem.richLink;
59
+ return richLink?.richLinkProperties ? richLink.richLinkProperties.title : null;
60
+ }
61
+
62
+ /**
63
+ * Returns the URL of the resource.
64
+ * @returns {string} The URL of the resource.
65
+ */
66
+ getUrl() {
67
+ const { nargs, matchThrow } = signatureArgs(arguments, 'RichLink.getUrl');
68
+ if (nargs !== 0) matchThrow();
69
+
70
+ const richLink = this.__elementMapItem.richLink;
71
+ return richLink ? richLink.uri : null;
72
+ }
73
+
74
+ toString() {
75
+ return 'RichLink';
76
+ }
77
+ }
78
+
79
+ registerElement('RICH_LINK', newFakeRichLink);
@@ -1,8 +1,9 @@
1
1
  /**
2
2
  * @file Provides a base class for HeaderSection and FooterSection.
3
3
  */
4
+ import is from '@sindresorhus/is';
4
5
  import { FakeContainerElement } from './fakecontainerelement.js';
5
- import { notYetImplemented, signatureArgs } from '../../support/helpers.js';
6
+ import { signatureArgs } from '../../support/helpers.js';
6
7
  import { getText } from './elementhelpers.js';
7
8
  import {
8
9
  appendParagraph,
@@ -11,6 +12,10 @@ import {
11
12
  insertTable,
12
13
  appendListItem,
13
14
  insertListItem,
15
+ appendImage,
16
+ insertImage,
17
+ appendHorizontalRule,
18
+ insertHorizontalRule
14
19
  } from './appenderhelpers.js';
15
20
  import { ElementType } from '../enums/docsenums.js';
16
21
 
@@ -31,19 +36,19 @@ export class FakeSectionElement extends FakeContainerElement {
31
36
 
32
37
  /**
33
38
  * Appends a horizontal rule.
34
- * @returns {GoogleAppsScript.Document.HorizontalRule} The appended horizontal rule.
39
+ * @returns {GoogleAppsScript.Document.Paragraph} The appended paragraph acting as a horizontal rule.
35
40
  */
36
- appendHorizontalRule() {
37
- return notYetImplemented(`${this.toString()}.appendHorizontalRule`);
41
+ appendHorizontalRule(horizontalRule) {
42
+ return appendHorizontalRule(this, horizontalRule);
38
43
  }
39
44
 
40
45
  /**
41
46
  * Appends an image.
42
- * @param {GoogleAppsScript.Base.BlobSource} image The image data.
47
+ * @param {GoogleAppsScript.Base.BlobSource|GoogleAppsScript.Document.InlineImage} image The image data.
43
48
  * @returns {GoogleAppsScript.Document.InlineImage} The appended image.
44
49
  */
45
50
  appendImage(image) {
46
- return notYetImplemented(`${this.toString()}.appendImage`);
51
+ return appendImage(this, image);
47
52
  }
48
53
 
49
54
  /**
@@ -112,7 +117,7 @@ export class FakeSectionElement extends FakeContainerElement {
112
117
  * @returns {GoogleAppsScript.Document.Text} The contents as a Text element.
113
118
  */
114
119
  editAsText() {
115
- return notYetImplemented(`${this.toString()}.editAsText`);
120
+ return super.editAsText();
116
121
  }
117
122
 
118
123
  /**
@@ -126,20 +131,20 @@ export class FakeSectionElement extends FakeContainerElement {
126
131
  /**
127
132
  * Inserts a horizontal rule at a specific index.
128
133
  * @param {number} childIndex The index to insert at.
129
- * @returns {GoogleAppsScript.Document.HorizontalRule} The inserted horizontal rule.
134
+ * @returns {GoogleAppsScript.Document.Paragraph} The inserted horizontal rule (as a Paragraph).
130
135
  */
131
- insertHorizontalRule(childIndex) {
132
- return notYetImplemented(`${this.toString()}.insertHorizontalRule`);
136
+ insertHorizontalRule(childIndex, horizontalRule) {
137
+ return insertHorizontalRule(this, childIndex, horizontalRule);
133
138
  }
134
139
 
135
140
  /**
136
141
  * Inserts an image at a specific index.
137
142
  * @param {number} childIndex The index to insert at.
138
- * @param {GoogleAppsScript.Base.BlobSource} image The image data.
143
+ * @param {GoogleAppsScript.Base.BlobSource|GoogleAppsScript.Document.InlineImage} image The image data.
139
144
  * @returns {GoogleAppsScript.Document.InlineImage} The inserted image.
140
145
  */
141
146
  insertImage(childIndex, image) {
142
- return notYetImplemented(`${this.toString()}.insertImage`);
147
+ return insertImage(this, childIndex, image);
143
148
  }
144
149
 
145
150
  /**
@@ -181,6 +186,40 @@ export class FakeSectionElement extends FakeContainerElement {
181
186
  return insertTable(this, childIndex, table);
182
187
  }
183
188
 
189
+ /**
190
+ * Removes a child element from the section.
191
+ * @param {FakeElement} child The child element to remove.
192
+ * @returns {FakeSectionElement} The section.
193
+ */
194
+ removeChild(child) {
195
+ const { nargs, matchThrow } = signatureArgs(arguments, `${this.toString()}.removeChild`);
196
+ if (nargs !== 1) matchThrow();
197
+ child.removeFromParent();
198
+ return this;
199
+ }
200
+
201
+ /**
202
+ * Sets the text content of the section.
203
+ * @param {string} text The text to set.
204
+ * @returns {FakeSectionElement} The section.
205
+ */
206
+ setText(text) {
207
+ const { nargs, matchThrow } = signatureArgs(arguments, `${this.toString()}.setText`);
208
+ if (nargs !== 1 || !is.string(text)) matchThrow();
209
+
210
+ this.clear();
211
+
212
+ if (text) {
213
+ const shadow = this.shadowDocument;
214
+ const requests = [{
215
+ insertText: { location: { index: 0, segmentId: this.__segmentId, tabId: this.__tabId }, text }
216
+ }];
217
+ Docs.Documents.batchUpdate({ requests }, shadow.getId());
218
+ shadow.refresh();
219
+ }
220
+ return this;
221
+ }
222
+
184
223
  /**
185
224
  * Removes the element from its parent.
186
225
  * @returns {FakeSectionElement} The element, for chaining.
@@ -3,9 +3,20 @@
3
3
  */
4
4
 
5
5
  import { Proxies } from '../../support/proxies.js';
6
+ import { notYetImplemented, signatureArgs } from '../../support/helpers.js';
6
7
  import { FakeContainerElement } from './fakecontainerelement.js';
7
8
  import { getText } from './elementhelpers.js';
8
9
  import { registerElement } from './elementRegistry.js';
10
+ import {
11
+ appendParagraph,
12
+ insertParagraph,
13
+ appendTable,
14
+ insertTable,
15
+ appendListItem,
16
+ insertListItem,
17
+ appendImage,
18
+ insertImage
19
+ } from './appenderhelpers.js';
9
20
 
10
21
  /**
11
22
  * A fake implementation of the TableCell class.
@@ -27,6 +38,93 @@ export class FakeTableCell extends FakeContainerElement {
27
38
  getText() {
28
39
  return getText(this);
29
40
  }
41
+
42
+ /**
43
+ * Retrieves the TableRow containing the current TableCell.
44
+ * @returns {FakeTableRow|null} the table row containing the current cell
45
+ * @see https://developers.google.com/apps-script/reference/document/table-cell#getParentRow()
46
+ */
47
+ getParentRow() {
48
+ return this.getParent();
49
+ }
50
+
51
+ /**
52
+ * Retrieves the Table containing the current TableCell.
53
+ * @returns {FakeTable|null} the table containing the current cell
54
+ * @see https://developers.google.com/apps-script/reference/document/table-cell#getParentTable()
55
+ */
56
+ getParentTable() {
57
+ const row = this.getParentRow();
58
+ return row ? row.getParentTable() : null;
59
+ }
60
+
61
+ /**
62
+ * Retrieves the column span, which is the number of columns of table cells this cell spans.
63
+ * @returns {number} the column span
64
+ * @see https://developers.google.com/apps-script/reference/document/table-cell#getColSpan()
65
+ */
66
+ getColSpan() {
67
+ const style = this.__elementMapItem.tableCellStyle;
68
+ return style?.columnSpan || 1;
69
+ }
70
+
71
+ /**
72
+ * Retrieves the row span, which is the number of rows of table cells this cell spans.
73
+ * @returns {number} the row span
74
+ * @see https://developers.google.com/apps-script/reference/document/table-cell#getRowSpan()
75
+ */
76
+ getRowSpan() {
77
+ const style = this.__elementMapItem.tableCellStyle;
78
+ return style?.rowSpan || 1;
79
+ }
80
+
81
+ // --- Appender & Inserter Methods ---
82
+
83
+ appendHorizontalRule() {
84
+ return notYetImplemented(`${this.toString()}.appendHorizontalRule`);
85
+ }
86
+
87
+ appendImage(image) {
88
+ return appendImage(this, image);
89
+ }
90
+
91
+ appendListItem(listItemOrText) {
92
+ return appendListItem(this, listItemOrText);
93
+ }
94
+
95
+ appendParagraph(paragraphOrText) {
96
+ return appendParagraph(this, paragraphOrText);
97
+ }
98
+
99
+ appendTable(tableOrCells) {
100
+ return appendTable(this, tableOrCells);
101
+ }
102
+
103
+ insertHorizontalRule(childIndex) {
104
+ return notYetImplemented(`${this.toString()}.insertHorizontalRule`);
105
+ }
106
+
107
+ insertImage(childIndex, image) {
108
+ return insertImage(this, childIndex, image);
109
+ }
110
+
111
+ insertListItem(childIndex, listItemOrText) {
112
+ const { nargs } = signatureArgs(arguments, 'TableCell.insertListItem');
113
+ if (nargs === 1) return this.appendListItem(listItemOrText);
114
+ return insertListItem(this, childIndex, listItemOrText);
115
+ }
116
+
117
+ insertParagraph(childIndex, paragraphOrText) {
118
+ const { nargs } = signatureArgs(arguments, 'TableCell.insertParagraph');
119
+ if (nargs === 1) return this.appendParagraph(paragraphOrText);
120
+ return insertParagraph(this, childIndex, paragraphOrText);
121
+ }
122
+
123
+ insertTable(childIndex, tableOrCells) {
124
+ const { nargs } = signatureArgs(arguments, 'TableCell.insertTable');
125
+ if (nargs === 1) return this.appendTable(tableOrCells);
126
+ return insertTable(this, childIndex, tableOrCells);
127
+ }
30
128
  }
31
129
 
32
130
  /**
@@ -21,8 +21,9 @@ export const makeNrPrefix = (type = null, segmentId = null) => {
21
21
  // get all the relevant named ranges from the current document
22
22
  export const getCurrentNr = (data) => {
23
23
  // filter out unrelated namedranges, and add the rest for lookup later
24
+ // Include kix. for bookmarks.
24
25
  return Reflect.ownKeys(data.namedRanges || {})
25
- .filter(key => key.startsWith(shadowPrefix))
26
+ .filter(key => key.startsWith(shadowPrefix) || key.startsWith('kix.'))
26
27
  .reduce((p, c) => {
27
28
  // strangly there's another level of .namedRanges property
28
29
  const nrs = data.namedRanges[c].namedRanges;
@@ -202,6 +202,9 @@ class ShadowDocument {
202
202
  childElement.horizontalRule ||
203
203
  childElement.footnoteReference ||
204
204
  childElement.inlineObjectElement ||
205
+ childElement.person ||
206
+ childElement.richLink ||
207
+ childElement.date ||
205
208
  (childElement.textRun && childElement.textRun.content && childElement.textRun.content !== '\n');
206
209
  });
207
210
  } else {
@@ -282,10 +285,24 @@ class ShadowDocument {
282
285
  footnoteSectionTree.children = footnoteTwigs;
283
286
  };
284
287
  mapFootnotes(footnotes);
288
+
289
+ // Filter out kix. bookmarks from deletion and add them to elementMap
290
+ const bookmarkNrs = currentNr.filter(r => r.name.startsWith('kix.'));
291
+ const remainingUnused = currentNr.filter(r => !r.name.startsWith('kix.'));
292
+
293
+ bookmarkNrs.forEach(r => {
294
+ // Add to elementMap so FakeBookmark can find it
295
+ this.__elementMap.set(r.name, {
296
+ ...r,
297
+ __type: 'BOOKMARK',
298
+ __name: r.name,
299
+ __twig: { name: r.name, children: [], parent: null }
300
+ });
301
+ });
302
+
285
303
  // delete the named ranges that weren't used
286
304
  // findOrCreate... consumes the currentNr list, so what's left are unused ranges.
287
-
288
- const deleteRequests = currentNr.map(r => ({
305
+ const deleteRequests = remainingUnused.map(r => ({
289
306
  deleteNamedRange: {
290
307
  namedRangeId: r.namedRangeId
291
308
  }