1 | "use strict";
|
2 |
|
3 | var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
4 |
|
5 | var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
|
6 |
|
7 | const Asset = require('../Asset');
|
8 |
|
9 | const api = require('posthtml/lib/api');
|
10 |
|
11 | const urlJoin = require('../utils/urlJoin');
|
12 |
|
13 | const render = require('posthtml-render');
|
14 |
|
15 | const posthtmlTransform = require('../transforms/posthtml');
|
16 |
|
17 | const htmlnanoTransform = require('../transforms/htmlnano');
|
18 |
|
19 | const isURL = require('../utils/is-url');
|
20 |
|
21 |
|
22 |
|
23 | const ATTRS = {
|
24 | src: ['script', 'img', 'audio', 'video', 'source', 'track', 'iframe', 'embed'],
|
25 | href: ['link', 'a', 'use'],
|
26 | srcset: ['img', 'source'],
|
27 | poster: ['video'],
|
28 | 'xlink:href': ['use', 'image'],
|
29 | content: ['meta'],
|
30 | data: ['object']
|
31 | };
|
32 |
|
33 |
|
34 |
|
35 |
|
36 |
|
37 |
|
38 | const META = {
|
39 | property: ['og:image', 'og:image:url', 'og:image:secure_url', 'og:audio', 'og:audio:secure_url', 'og:video', 'og:video:secure_url'],
|
40 | name: ['twitter:image', 'msapplication-square150x150logo', 'msapplication-square310x310logo', 'msapplication-square70x70logo', 'msapplication-wide310x150logo', 'msapplication-TileImage', 'msapplication-config'],
|
41 | itemprop: ['image', 'logo', 'screenshot', 'thumbnailUrl', 'contentUrl', 'downloadUrl']
|
42 | };
|
43 | const SCRIPT_TYPES = {
|
44 | 'application/javascript': 'js',
|
45 | 'text/javascript': 'js',
|
46 | 'application/json': false,
|
47 | 'application/ld+json': 'jsonld',
|
48 | 'text/html': false
|
49 | };
|
50 |
|
51 | const OPTIONS = {
|
52 | a: {
|
53 | href: {
|
54 | entry: true
|
55 | }
|
56 | },
|
57 | iframe: {
|
58 | src: {
|
59 | entry: true
|
60 | }
|
61 | }
|
62 | };
|
63 |
|
64 | class HTMLAsset extends Asset {
|
65 | constructor(name, options) {
|
66 | super(name, options);
|
67 | this.type = 'html';
|
68 | this.isAstDirty = false;
|
69 | this.hmrPageReload = true;
|
70 | }
|
71 |
|
72 | parse(code) {
|
73 | var _this = this;
|
74 |
|
75 | return (0, _asyncToGenerator2.default)(function* () {
|
76 | let res = yield posthtmlTransform.parse(code, _this);
|
77 | res.walk = api.walk;
|
78 | res.match = api.match;
|
79 | return res;
|
80 | })();
|
81 | }
|
82 |
|
83 | processSingleDependency(path, opts) {
|
84 | let assetPath = this.addURLDependency(path, opts);
|
85 |
|
86 | if (!isURL(assetPath)) {
|
87 | assetPath = urlJoin(this.options.publicURL, assetPath);
|
88 | }
|
89 |
|
90 | return assetPath;
|
91 | }
|
92 |
|
93 | collectSrcSetDependencies(srcset, opts) {
|
94 | const newSources = [];
|
95 | var _iteratorNormalCompletion = true;
|
96 | var _didIteratorError = false;
|
97 | var _iteratorError = undefined;
|
98 |
|
99 | try {
|
100 | for (var _iterator = srcset.split(',')[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
|
101 | const source = _step.value;
|
102 | const pair = source.trim().split(' ');
|
103 | if (pair.length === 0) continue;
|
104 | pair[0] = this.processSingleDependency(pair[0], opts);
|
105 | newSources.push(pair.join(' '));
|
106 | }
|
107 | } catch (err) {
|
108 | _didIteratorError = true;
|
109 | _iteratorError = err;
|
110 | } finally {
|
111 | try {
|
112 | if (!_iteratorNormalCompletion && _iterator.return != null) {
|
113 | _iterator.return();
|
114 | }
|
115 | } finally {
|
116 | if (_didIteratorError) {
|
117 | throw _iteratorError;
|
118 | }
|
119 | }
|
120 | }
|
121 |
|
122 | return newSources.join(',');
|
123 | }
|
124 |
|
125 | getAttrDepHandler(attr) {
|
126 | if (attr === 'srcset') {
|
127 | return this.collectSrcSetDependencies;
|
128 | }
|
129 |
|
130 | return this.processSingleDependency;
|
131 | }
|
132 |
|
133 | collectDependencies() {
|
134 | let ast = this.ast;
|
135 |
|
136 | if (ast.messages) {
|
137 | ast.messages.forEach(message => {
|
138 | if (message.type === 'dependency') {
|
139 | this.addDependency(message.file, {
|
140 | includedInParent: true
|
141 | });
|
142 | }
|
143 | });
|
144 | }
|
145 |
|
146 | ast.walk(node => {
|
147 | if (node.attrs) {
|
148 | if (node.tag === 'meta') {
|
149 | if (!Object.keys(node.attrs).some(attr => {
|
150 | let values = META[attr];
|
151 | return values && values.includes(node.attrs[attr]) && node.attrs.content !== '';
|
152 | })) {
|
153 | return node;
|
154 | }
|
155 | }
|
156 |
|
157 | if (node.tag === 'link' && node.attrs.rel === 'manifest' && node.attrs.href) {
|
158 | node.attrs.href = this.getAttrDepHandler('href').call(this, node.attrs.href, {
|
159 | entry: true
|
160 | });
|
161 | this.isAstDirty = true;
|
162 | return node;
|
163 | }
|
164 |
|
165 | for (let attr in node.attrs) {
|
166 | const attrVal = node.attrs[attr];
|
167 |
|
168 | if (!attrVal) {
|
169 | continue;
|
170 | }
|
171 |
|
172 |
|
173 | if (node.tag === 'a' && attrVal.lastIndexOf('.') < 1) {
|
174 | continue;
|
175 | }
|
176 |
|
177 | let elements = ATTRS[attr];
|
178 |
|
179 | if (elements && elements.includes(node.tag)) {
|
180 | let depHandler = this.getAttrDepHandler(attr);
|
181 | let options = OPTIONS[node.tag];
|
182 | node.attrs[attr] = depHandler.call(this, attrVal, options && options[attr]);
|
183 | this.isAstDirty = true;
|
184 | }
|
185 | }
|
186 | }
|
187 |
|
188 | return node;
|
189 | });
|
190 | }
|
191 |
|
192 | pretransform() {
|
193 | var _this2 = this;
|
194 |
|
195 | return (0, _asyncToGenerator2.default)(function* () {
|
196 | yield posthtmlTransform.transform(_this2);
|
197 | })();
|
198 | }
|
199 |
|
200 | transform() {
|
201 | var _this3 = this;
|
202 |
|
203 | return (0, _asyncToGenerator2.default)(function* () {
|
204 | if (_this3.options.minify) {
|
205 | yield htmlnanoTransform(_this3);
|
206 | }
|
207 | })();
|
208 | }
|
209 |
|
210 | generate() {
|
211 | var _this4 = this;
|
212 |
|
213 | return (0, _asyncToGenerator2.default)(function* () {
|
214 |
|
215 | let parts = [];
|
216 |
|
217 | if (_this4.ast) {
|
218 | _this4.ast.walk(node => {
|
219 | if (node.tag === 'script' || node.tag === 'style') {
|
220 | let value = node.content && node.content.join('').trim();
|
221 |
|
222 | if (value) {
|
223 | let type;
|
224 |
|
225 | if (node.tag === 'style') {
|
226 | if (node.attrs && node.attrs.type) {
|
227 | type = node.attrs.type.split('/')[1];
|
228 | } else {
|
229 | type = 'css';
|
230 | }
|
231 | } else if (node.attrs && node.attrs.type) {
|
232 |
|
233 | if (SCRIPT_TYPES[node.attrs.type] === false) {
|
234 | return node;
|
235 | }
|
236 |
|
237 | if (SCRIPT_TYPES[node.attrs.type]) {
|
238 | type = SCRIPT_TYPES[node.attrs.type];
|
239 | } else {
|
240 | type = node.attrs.type.split('/')[1];
|
241 | }
|
242 | } else {
|
243 | type = 'js';
|
244 | }
|
245 |
|
246 | parts.push({
|
247 | type,
|
248 | value,
|
249 | inlineHTML: true,
|
250 | meta: {
|
251 | type: 'tag',
|
252 | node
|
253 | }
|
254 | });
|
255 | }
|
256 | }
|
257 |
|
258 |
|
259 | if (node.attrs && node.attrs.style) {
|
260 | parts.push({
|
261 | type: 'css',
|
262 | value: node.attrs.style,
|
263 | meta: {
|
264 | type: 'attr',
|
265 | node
|
266 | }
|
267 | });
|
268 | }
|
269 |
|
270 | return node;
|
271 | });
|
272 | }
|
273 |
|
274 | return parts;
|
275 | })();
|
276 | }
|
277 |
|
278 | postProcess(generated) {
|
279 | var _this5 = this;
|
280 |
|
281 | return (0, _asyncToGenerator2.default)(function* () {
|
282 |
|
283 | var _iteratorNormalCompletion2 = true;
|
284 | var _didIteratorError2 = false;
|
285 | var _iteratorError2 = undefined;
|
286 |
|
287 | try {
|
288 | for (var _iterator2 = generated[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
|
289 | let rendition = _step2.value;
|
290 | let _rendition$meta = rendition.meta,
|
291 | type = _rendition$meta.type,
|
292 | node = _rendition$meta.node;
|
293 |
|
294 | if (type === 'attr' && rendition.type === 'css') {
|
295 | node.attrs.style = rendition.value;
|
296 | } else if (type === 'tag') {
|
297 | if (rendition.isMain) {
|
298 | node.content = rendition.value;
|
299 | }
|
300 |
|
301 |
|
302 |
|
303 | if (node.attrs && (node.tag === 'style' || node.attrs.type && SCRIPT_TYPES[node.attrs.type] === 'js')) {
|
304 | delete node.attrs.type;
|
305 | }
|
306 | }
|
307 | }
|
308 | } catch (err) {
|
309 | _didIteratorError2 = true;
|
310 | _iteratorError2 = err;
|
311 | } finally {
|
312 | try {
|
313 | if (!_iteratorNormalCompletion2 && _iterator2.return != null) {
|
314 | _iterator2.return();
|
315 | }
|
316 | } finally {
|
317 | if (_didIteratorError2) {
|
318 | throw _iteratorError2;
|
319 | }
|
320 | }
|
321 | }
|
322 |
|
323 | return [{
|
324 | type: 'html',
|
325 | value: render(_this5.ast)
|
326 | }];
|
327 | })();
|
328 | }
|
329 |
|
330 | }
|
331 |
|
332 | module.exports = HTMLAsset; |
\ | No newline at end of file |