-
Notifications
You must be signed in to change notification settings - Fork 667
/
html.ts
144 lines (123 loc) · 3.9 KB
/
html.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
import { SchematicsException, Tree } from '@angular-devkit/schematics';
import { InsertChange } from '@schematics/angular/utility/change';
import * as parse5 from 'parse5';
import { Project } from './project';
/** Gets the app index.html file */
export function getIndexHtmlPath(_host: Tree, project: Project): string {
const buildTarget = (project.targets || project.architect)!.build.options;
if (buildTarget.index && buildTarget.index.endsWith('index.html')) {
return buildTarget.index;
}
throw new SchematicsException('No index.html file was found.');
}
/**
* Parses the index.html file to get the HEAD tag position.
*/
export function getTag(host: Tree, src: string, tagName: string) {
if ((parse5 as any).treeAdapters) {
return getTagInV4(host, src, tagName);
}
const document = parse5.parse(src, {
sourceCodeLocationInfo: true,
} as any) as any;
let resNode: any;
const visit = (nodes: any[]) => {
nodes.forEach(node => {
const element = node as any;
if (element.nodeName === tagName) {
resNode = element;
} else {
if (element.childNodes) {
visit(element.childNodes);
}
}
});
};
visit(document.childNodes);
if (!resNode) {
throw new SchematicsException('Head element not found!');
}
return {
startOffset: resNode.sourceCodeLocation.startTag.endOffset,
endOffset: resNode.sourceCodeLocation.endTag.startOffset,
};
}
export function getTagInV4(_host: Tree, src: string, tagName: string) {
const document: any = parse5.parse(src, {
locationInfo: true,
} as any);
let resNode;
const visit = (nodes: any[]) => {
nodes.forEach(node => {
const element: any = node;
if (element.tagName === tagName) {
resNode = element;
} else {
if (element.childNodes) {
visit(element.childNodes);
}
}
});
};
visit(document.childNodes);
if (!resNode) {
throw new SchematicsException('Head element not found!');
}
return {
startOffset: resNode.__location.startTag.endOffset,
endOffset: resNode.__location.endTag.startOffset,
};
}
/**
* Get index.html content
*/
export function getIndexHtmlContent(host: Tree, project: Project) {
const indexPath = getIndexHtmlPath(host, project);
const buffer = host.read(indexPath);
if (!buffer) {
throw new SchematicsException(`Could not find file for path '${indexPath}'`);
}
return {
indexPath,
src: buffer.toString(),
};
}
/**
* Adds a link to the index.html head tag
*/
export function addHeadLink(host: Tree, project: Project, link: string) {
const { indexPath, src } = getIndexHtmlContent(host, project);
if (src.indexOf(link) === -1) {
const node = getTag(host, src, 'head');
const insertion = new InsertChange(indexPath, node.startOffset, link);
const recorder = host.beginUpdate(indexPath);
recorder.insertLeft(insertion.pos, insertion.toAdd);
host.commitUpdate(recorder);
}
}
/**
* Adds a style to the index.html head end tag
*/
export function addHeadStyle(host: Tree, project: Project, style: string) {
const { indexPath, src } = getIndexHtmlContent(host, project);
if (src.indexOf(style) === -1) {
const node = getTag(host, src, 'head');
const insertion = new InsertChange(indexPath, node.endOffset, style);
const recorder = host.beginUpdate(indexPath);
recorder.insertLeft(insertion.pos, insertion.toAdd);
host.commitUpdate(recorder);
}
}
/**
* Adds a html to the index.html body end tag
*/
export function addHtmlToBody(host: Tree, project: Project, html: string) {
const { indexPath, src } = getIndexHtmlContent(host, project);
if (src.indexOf(html) === -1) {
const node = getTag(host, src, 'body');
const insertion = new InsertChange(indexPath, node.endOffset, html);
const recorder = host.beginUpdate(indexPath);
recorder.insertLeft(insertion.pos, insertion.toAdd);
host.commitUpdate(recorder);
}
}