-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
static-pug.js
127 lines (118 loc) · 3.35 KB
/
static-pug.js
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
import { MultiFileCachingCompiler } from 'meteor/caching-compiler';
import { checkNpmVersions } from 'meteor/tmeasday:check-npm-versions';
checkNpmVersions({
'pug': '>=3.0.0'
}, 'static-pug');
let pug;
try {
pug = require('pug');
} catch {
}
class PugCompiler extends MultiFileCachingCompiler {
constructor() {
super({
compilerName: 'static-pug',
defaultCacheSize: 1024*1024*10,
});
}
getCacheKey(inputFile) {
return inputFile.getSourceHash();
}
// Treat files with names *.import.pug as imports, not root files that
// should get converted.
isRoot(inputFile) {
return !inputFile.getPathInPackage().endsWith('.import.pug');
}
compileOneFile(inputFile) {
if (!pug) {
console.warn(`WARNING: Unable to compile ${inputFile.getPathInPackage()}`+
` without NPM peer dependency: meteor npm install pug`);
return;
}
// Convert PUG to HTML and dependency list
const inputPackage = inputFile.getPackageName() || '';
const inputPath = inputFile.getPathInPackage();
const template = pug.compile(inputFile.getContentsAsString(), {
filename: inputPath,
});
const dependencies = template.dependencies.map((relative) =>
Plugin.path.join(`{${inputPackage}}`, relative)
);
const body = template({});
// Scan HTML for <body> and <head> tags and their attributes
const result = {
head: '',
body: '',
headAttrs: {},
bodyAttrs: {},
};
TemplatingTools.scanHtmlForTags({
sourceName: inputPath,
contents: body,
tagNames: ['body', 'head'],
}).forEach((tag) => {
result[tag.tagName] += tag.contents;
const tagAttrs = result[tag.tagName + 'Attrs'];
Object.keys(tag.attribs).forEach((attr) => {
const val = tag.attribs[attr];
if (tagAttrs.hasOwnProperty(attr) && tagAttrs[attr] !== val) {
TemplatingTools.throwCompileError(tag,
`Multiple <${tag.tagName}> declarations have conflicting values `+
`for the '${attr}' attribute`);
}
tagAttrs[attr] = val;
});
});
return {
compileResult: result,
referencedImportPaths: dependencies,
};
}
compileResultSize(compileResult) {
return compileResult.head.length + compileResult.body.length;
}
addCompileResult(inputFile, result) {
if (result.head) {
inputFile.addHtml({
section: 'head',
data: result.head,
});
}
if (result.body) {
inputFile.addHtml({
section: 'body',
data: result.body,
});
}
if (Object.keys(result.headAttrs).length ||
Object.keys(result.bodyAttrs).length) {
let js = `Meteor.startup(function() {`;
if (Object.keys(result.headAttrs).length) {
js += `
var headAttrs = ${JSON.stringify(result.headAttrs)};
for (var attr in headAttrs) {
document.head.setAttribute(attr, headAttrs[attr]);
}`;
}
if (Object.keys(result.bodyAttrs).length) {
js += `
var bodyAttrs = ${JSON.stringify(result.bodyAttrs)};
for (var attr in bodyAttrs) {
document.body.setAttribute(attr, bodyAttrs[attr]);
}`;
}
js += `
});
`;
inputFile.addJavaScript({
path: inputFile.getPathInPackage() + '.attrs.js',
data: js,
});
}
}
}
Plugin.registerCompiler({
extensions: ['pug'],
archMatching: 'web',
isTemplate: true
}, () => new PugCompiler());