Skip to content

Commit 4cad2d5

Browse files
committed
reformat
1 parent 9c11adf commit 4cad2d5

16 files changed

+219
-137
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,11 @@ Typescript XML parser that 100% retains all formatting for creating identical XM
55
If you have an XML file that you want to read, modify, and write back, this library will ensure that the output XML is formatted identical to the input XML.
66

77
## Features
8+
89
- Retains all whitespace and line endings
910
- Retains all comments
1011
- Retains whether an element is self-closing or not
1112
- Retains attributes in the order they were defined
1213
- Retains attribute quotes (single or double) and whitespace before and after the attribute name
1314
- Retains XML processing instructions (including the XML declaration)
14-
- Retains CDATA sections
15+
- Retains CDATA sections

model/xmlAttribute.spec.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ describe('XmlAttribute', () => {
99
});
1010
it('should return "\'" unescaped', () => {
1111
const attribute = new XmlAttribute('test', 'a ' b');
12-
expect(attribute.unescapeValue()).toBe('a \' b');
12+
expect(attribute.unescapeValue()).toBe("a ' b");
1313
});
1414
it('should return """ unescaped', () => {
1515
const attribute = new XmlAttribute('test', 'a " b');
@@ -36,7 +36,7 @@ describe('XmlAttribute', () => {
3636
});
3737
it('should escape "\'"', () => {
3838
const attribute = new XmlAttribute('test', '');
39-
attribute.setValue('a \' b');
39+
attribute.setValue("a ' b");
4040
expect(attribute.value).toBe('a ' b');
4141
});
4242
it('should escape """', () => {
@@ -59,6 +59,5 @@ describe('XmlAttribute', () => {
5959
attribute.setValue('a & b');
6060
expect(attribute.value).toBe('a & b');
6161
});
62-
6362
});
6463
});

model/xmlAttribute.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,8 @@ export class XmlAttribute {
1212
public leadingWs: string = ' ',
1313
public wsBeforeEqual: string = '',
1414
public wsAfterEqual: string = '',
15-
public quote: '"' | '\'' = '"'
16-
) {
17-
}
15+
public quote: '"' | "'" = '"',
16+
) {}
1817

1918
unescapeValue(): string {
2019
return unescapeXml(this.value);

model/xmlCData.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// CDATA section.
2-
import { XmlNode } from "./xmlNode";
2+
import { XmlNode } from './xmlNode';
33

44
export class XmlCData extends XmlNode {
55
constructor(public cdata: string) {

model/xmlComment.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// XML comment node.
2-
import { XmlNode } from "./xmlNode";
2+
import { XmlNode } from './xmlNode';
33

44
export class XmlComment extends XmlNode {
55
constructor(public comment: string) {

model/xmlDoctype.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
// DOCTYPE declaration.
2-
import { XmlNode } from "./xmlNode";
1+
import { XmlNode } from './xmlNode';
32

43
export class XmlDoctype extends XmlNode {
54
constructor(public content: string) {

model/xmlDocument.ts

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,12 @@
1-
// The document node is simply a container for a sequence of XML nodes.
2-
import { XmlNode } from "./xmlNode";
1+
import { XmlNode } from './xmlNode';
32

3+
/// The document node is simply a container for a sequence of XML nodes.
44
export class XmlDocument extends XmlNode {
55
constructor(public children: XmlNode[]) {
66
super();
77
}
88

9-
addChild(child: XmlNode) {
10-
this.children.push(child);
11-
}
12-
139
toString(): string {
14-
return this.children.map((child) => child.toString()).join("");
10+
return this.children.map((child) => child.toString()).join('');
1511
}
1612
}

model/xmlElement.spec.ts

Lines changed: 49 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,29 @@ describe('XmlElement', () => {
1515
it('should add child after the given child', () => {
1616
const existingChild1 = new XmlElement('child1', [], []);
1717
const existingChild2 = new XmlElement('child2', [], []);
18-
const element = new XmlElement('test', [], [existingChild1, existingChild2]);
18+
const element = new XmlElement(
19+
'test',
20+
[],
21+
[existingChild1, existingChild2],
22+
);
1923
const child = new XmlElement('child');
2024
element.addElement(child, { after: existingChild1 });
2125
expect(element.children).toEqual([existingChild1, child, existingChild2]);
2226
});
27+
28+
it('should add child before the given child', () => {
29+
const existingChild1 = new XmlElement('child1', [], []);
30+
const existingChild2 = new XmlElement('child2', [], []);
31+
const element = new XmlElement(
32+
'test',
33+
[],
34+
[existingChild1, existingChild2],
35+
);
36+
const child = new XmlElement('child');
37+
element.addElement(child, { before: existingChild2 });
38+
expect(element.children).toEqual([existingChild1, child, existingChild2]);
39+
});
40+
2341
it('should update self closing', () => {
2442
const element = new XmlElement('test', [], [], ' ', true);
2543
const child = new XmlElement('child');
@@ -28,18 +46,38 @@ describe('XmlElement', () => {
2846
});
2947

3048
describe('guessFormatting', () => {
31-
it('should add whitespace according previous node', () => {
49+
it('should add whitespace according previous node with after', () => {
3250
const existingChild = new XmlElement('child');
33-
const element = new XmlElement('test', [], [
34-
new XmlText('\n '),
35-
existingChild,
36-
new XmlText('\n'),
37-
]);
51+
const element = new XmlElement(
52+
'test',
53+
[],
54+
[new XmlText('\n '), existingChild, new XmlText('\n')],
55+
);
3856
const child = new XmlElement('new-child');
39-
element.addElement(child, { after: existingChild, guessFormatting: true});
40-
expect(element.toString()).toEqual(`<test>\n <child></child>\n <new-child></new-child>\n</test>`);
57+
element.addElement(child, {
58+
after: existingChild,
59+
guessFormatting: true,
60+
});
61+
expect(element.toString()).toEqual(
62+
`<test>\n <child></child>\n <new-child></new-child>\n</test>`,
63+
);
64+
});
65+
it('should add whitespace according previous node with before', () => {
66+
const existingChild = new XmlElement('child');
67+
const element = new XmlElement(
68+
'test',
69+
[],
70+
[new XmlText('\n '), existingChild, new XmlText('\n')],
71+
);
72+
const child = new XmlElement('new-child');
73+
element.addElement(child, {
74+
before: existingChild,
75+
guessFormatting: true,
76+
});
77+
expect(element.toString()).toEqual(
78+
`<test>\n <new-child></new-child>\n <child></child>\n</test>`,
79+
);
4180
});
4281
});
4382
});
44-
45-
});
83+
});

model/xmlElement.ts

Lines changed: 30 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -24,28 +24,45 @@ export class XmlElement extends XmlNode {
2424
public attrTrailingWs = '',
2525
public selfClosing = false,
2626
/** whitespace inside the closing tag before '>' */
27-
public closeTagWs: string = ''
27+
public closeTagWs: string = '',
2828
) {
2929
super();
3030
}
3131

32-
addElement(child: XmlElement, options?: {
33-
after?: XmlElement,
34-
/** if `true` or not set, add leading whitespace analogous to sister node, to match formatting. */
35-
guessFormatting?: boolean
36-
}): void {
37-
const index = options?.after ? this.children.indexOf(options.after) + 1 : this.children.length;
32+
addElement(
33+
child: XmlElement,
34+
options?: {
35+
after?: XmlElement;
36+
before?: XmlElement;
37+
/** if `true` or not set, add leading whitespace analogous to sister node, to match formatting. */
38+
guessFormatting?: boolean;
39+
},
40+
): void {
41+
let index: number;
42+
if (options?.after) {
43+
index = this.children.indexOf(options.after) + 1;
44+
} else if (options?.before) {
45+
index = this.children.indexOf(options.before);
46+
while (index > 0 && this.children[index - 1] instanceof XmlText) {
47+
index--;
48+
}
49+
} else {
50+
index = this.children.length;
51+
}
52+
3853
if (options?.guessFormatting ?? true) {
39-
const sibling = this.children
54+
const sibling =
55+
this.children
4056
.slice(0, index)
4157
.reverse()
42-
.find((c) => c instanceof XmlElement)
43-
?? this.children
44-
.slice(index)
45-
.find((c) => c instanceof XmlElement);
58+
.find((c) => c instanceof XmlElement) ??
59+
this.children.slice(index).find((c) => c instanceof XmlElement);
4660
if (sibling) {
4761
const siblingIndex = this.children.indexOf(sibling);
48-
const textBefore: XmlText | undefined = siblingIndex > 0 && this.children[siblingIndex - 1] instanceof XmlText ? this.children[siblingIndex - 1] as XmlText : undefined;
62+
const textBefore: XmlText | undefined =
63+
siblingIndex > 0 && this.children[siblingIndex - 1] instanceof XmlText
64+
? (this.children[siblingIndex - 1] as XmlText)
65+
: undefined;
4966
const leadingWs = textBefore?.text ?? '';
5067
this.addChild(index, new XmlText(leadingWs), child);
5168
} else {

model/xmlProcessing.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// Processing instruction node.
22
// Captures the target, any whitespace after it, and the instruction data.
3-
import { XmlNode } from "./xmlNode";
3+
import { XmlNode } from './xmlNode';
44

55
export class XmlProcessing extends XmlNode {
66
constructor(

0 commit comments

Comments
 (0)