mirror of
https://github.com/meteor/meteor.git
synced 2026-05-02 03:01:46 -04:00
Merge pull request #12203 from meteor/feature/static-html-tools
Move needed files for static-html into static-html-tools
This commit is contained in:
@@ -7,7 +7,7 @@ Package.describe({
|
||||
|
||||
Npm.depends({
|
||||
'lru-cache': '6.0.0'
|
||||
})
|
||||
});
|
||||
|
||||
Package.onUse(function(api) {
|
||||
api.use(['ecmascript', 'random']);
|
||||
|
||||
Submodule packages/non-core/blaze updated: c4e523d7d3...0856ca8bf7
148
packages/static-html-tools/caching-html-compiler.js
Normal file
148
packages/static-html-tools/caching-html-compiler.js
Normal file
@@ -0,0 +1,148 @@
|
||||
import { CompileError } from './throw-compile-error';
|
||||
import isEmpty from 'lodash.isempty';
|
||||
import { CachingCompiler } from 'meteor/caching-compiler';
|
||||
|
||||
const path = Plugin.path;
|
||||
|
||||
// The CompileResult type for this CachingCompiler is the return value of
|
||||
// htmlScanner.scan: a {js, head, body, bodyAttrs} object.
|
||||
export class CachingHtmlCompiler extends CachingCompiler {
|
||||
/**
|
||||
* Constructor for CachingHtmlCompiler
|
||||
* @param {String} name The name of the compiler, printed in errors -
|
||||
* should probably always be the same as the name of the build
|
||||
* plugin/package
|
||||
* @param {Function} tagScannerFunc Transforms a template file (commonly
|
||||
* .html) into an array of Tags
|
||||
* @param {Function} tagHandlerFunc Transforms an array of tags into a
|
||||
* results object with js, body, head, and bodyAttrs properties
|
||||
*/
|
||||
constructor(name, tagScannerFunc, tagHandlerFunc) {
|
||||
super({
|
||||
compilerName: name,
|
||||
defaultCacheSize: 1024 * 1024 * 10,
|
||||
});
|
||||
|
||||
this._bodyAttrInfo = null;
|
||||
|
||||
this.tagScannerFunc = tagScannerFunc;
|
||||
this.tagHandlerFunc = tagHandlerFunc;
|
||||
}
|
||||
|
||||
// Implements method from CachingCompilerBase
|
||||
// eslint-disable-next-line class-methods-use-this
|
||||
compileResultSize(compileResult) {
|
||||
const lengthOrZero = (field) => field ? field.length : 0;
|
||||
const headSize = lengthOrZero(compileResult.head);
|
||||
const bodySize = lengthOrZero(compileResult.body);
|
||||
const jsSize = lengthOrZero(compileResult.js);
|
||||
return headSize + bodySize + jsSize;
|
||||
}
|
||||
|
||||
// Overrides method from CachingCompiler
|
||||
processFilesForTarget(inputFiles) {
|
||||
this._bodyAttrInfo = {};
|
||||
return super.processFilesForTarget(inputFiles);
|
||||
}
|
||||
|
||||
// Implements method from CachingCompilerBase
|
||||
// eslint-disable-next-line class-methods-use-this
|
||||
getCacheKey(inputFile) {
|
||||
// Note: the path is only used for errors, so it doesn't have to be part
|
||||
// of the cache key.
|
||||
return [
|
||||
inputFile.getArch(),
|
||||
inputFile.getSourceHash(),
|
||||
inputFile.hmrAvailable && inputFile.hmrAvailable(),
|
||||
];
|
||||
}
|
||||
|
||||
// Implements method from CachingCompiler
|
||||
compileOneFile(inputFile) {
|
||||
const contents = inputFile.getContentsAsString();
|
||||
const inputPath = inputFile.getPathInPackage();
|
||||
try {
|
||||
const tags = this.tagScannerFunc({
|
||||
sourceName: inputPath,
|
||||
contents,
|
||||
tagNames: ['body', 'head', 'template'],
|
||||
});
|
||||
|
||||
return this.tagHandlerFunc(tags, inputFile.hmrAvailable && inputFile.hmrAvailable());
|
||||
} catch (e) {
|
||||
if (e instanceof CompileError) {
|
||||
inputFile.error({
|
||||
message: e.message,
|
||||
line: e.line,
|
||||
});
|
||||
return null;
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
// Implements method from CachingCompilerBase
|
||||
addCompileResult(inputFile, compileResult) {
|
||||
let allJavaScript = '';
|
||||
|
||||
if (compileResult.head) {
|
||||
inputFile.addHtml({ section: 'head', data: compileResult.head });
|
||||
}
|
||||
|
||||
if (compileResult.body) {
|
||||
inputFile.addHtml({ section: 'body', data: compileResult.body });
|
||||
}
|
||||
|
||||
if (compileResult.js) {
|
||||
allJavaScript += compileResult.js;
|
||||
}
|
||||
|
||||
if (!isEmpty(compileResult.bodyAttrs)) {
|
||||
Object.keys(compileResult.bodyAttrs).forEach((attr) => {
|
||||
const value = compileResult.bodyAttrs[attr];
|
||||
if (Object.prototype.hasOwnProperty.call(this._bodyAttrInfo, attr) &&
|
||||
this._bodyAttrInfo[attr].value !== value) {
|
||||
// two conflicting attributes on <body> tags in two different template
|
||||
// files
|
||||
inputFile.error({
|
||||
message:
|
||||
`${`<body> declarations have conflicting values for the '${attr}' ` +
|
||||
'attribute in the following files: '}${
|
||||
this._bodyAttrInfo[attr].inputFile.getPathInPackage()
|
||||
}, ${inputFile.getPathInPackage()}`,
|
||||
});
|
||||
} else {
|
||||
this._bodyAttrInfo[attr] = { inputFile, value };
|
||||
}
|
||||
});
|
||||
|
||||
// Add JavaScript code to set attributes on body
|
||||
allJavaScript +=
|
||||
`Meteor.startup(function() {
|
||||
var attrs = ${JSON.stringify(compileResult.bodyAttrs)};
|
||||
for (var prop in attrs) {
|
||||
document.body.setAttribute(prop, attrs[prop]);
|
||||
}
|
||||
});
|
||||
`;
|
||||
}
|
||||
|
||||
|
||||
if (allJavaScript) {
|
||||
const filePath = inputFile.getPathInPackage();
|
||||
// XXX this path manipulation may be unnecessarily complex
|
||||
let pathPart = path.dirname(filePath);
|
||||
if (pathPart === '.') pathPart = '';
|
||||
if (pathPart.length && pathPart !== path.sep) pathPart += path.sep;
|
||||
const ext = path.extname(filePath);
|
||||
const basename = path.basename(filePath, ext);
|
||||
|
||||
// XXX generate a source map
|
||||
|
||||
inputFile.addJavaScript({
|
||||
path: path.join(pathPart, `template.${basename}.js`),
|
||||
data: allJavaScript,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
191
packages/static-html-tools/html-scanner-tests.js
Normal file
191
packages/static-html-tools/html-scanner-tests.js
Normal file
@@ -0,0 +1,191 @@
|
||||
import { TemplatingTools } from 'meteor/templating-tools';
|
||||
|
||||
Tinytest.add("static-html-tools - html scanner", function (test) {
|
||||
var testInString = function(actualStr, wantedContents) {
|
||||
if (actualStr.indexOf(wantedContents) >= 0)
|
||||
test.ok();
|
||||
else
|
||||
test.fail("Expected "+JSON.stringify(wantedContents)+
|
||||
" in "+JSON.stringify(actualStr));
|
||||
};
|
||||
|
||||
var checkError = function(f, msgText, lineNum) {
|
||||
try {
|
||||
f();
|
||||
} catch (e) {
|
||||
if (! e instanceof TemplatingTools.CompileError) {
|
||||
throw e;
|
||||
}
|
||||
|
||||
if (e.line === lineNum)
|
||||
test.ok();
|
||||
else
|
||||
test.fail("Error should have been on line " + lineNum + ", not " +
|
||||
e.line);
|
||||
testInString(e.message, msgText);
|
||||
return;
|
||||
}
|
||||
test.fail("Parse error didn't throw exception");
|
||||
};
|
||||
|
||||
// returns the appropriate code to put content in the body,
|
||||
// where content is something simple like the string "Hello"
|
||||
// (passed in as a source string including the quotes).
|
||||
var simpleBody = function (content) {
|
||||
return "\nTemplate.body.addContent((function() {\n var view = this;\n return " + content + ";\n}));\nMeteor.startup(Template.body.renderToDocument);\n";
|
||||
};
|
||||
|
||||
// arguments are quoted strings like '"hello"'
|
||||
var simpleTemplate = function (templateName, content) {
|
||||
// '"hello"' into '"Template.hello"'
|
||||
var viewName = templateName.slice(0, 1) + 'Template.' + templateName.slice(1);
|
||||
|
||||
return '\nTemplate.__checkName(' + templateName + ');\nTemplate[' + templateName +
|
||||
'] = new Template(' + viewName +
|
||||
', (function() {\n var view = this;\n return ' + content + ';\n}));\n';
|
||||
};
|
||||
|
||||
var checkResults = function(results, expectJs, expectHead, expectBodyAttrs) {
|
||||
test.equal(results.body, '');
|
||||
test.equal(results.js, expectJs || '');
|
||||
test.equal(results.head, expectHead || '');
|
||||
test.equal(results.bodyAttrs, expectBodyAttrs || {});
|
||||
};
|
||||
|
||||
function scanForTest(contents) {
|
||||
const tags = TemplatingTools.scanHtmlForTags({
|
||||
sourceName: "",
|
||||
contents: contents,
|
||||
tagNames: ["body", "head", "template"]
|
||||
});
|
||||
|
||||
return TemplatingTools.compileTagsWithSpacebars(tags);
|
||||
}
|
||||
|
||||
checkError(function() {
|
||||
return scanForTest("asdf");
|
||||
}, "Expected one of: <body>, <head>, <template>", 1);
|
||||
|
||||
// body all on one line
|
||||
checkResults(
|
||||
scanForTest("<body>Hello</body>"),
|
||||
simpleBody('"Hello"'));
|
||||
|
||||
// multi-line body, contents trimmed
|
||||
checkResults(
|
||||
scanForTest("\n\n\n<body>\n\nHello\n\n</body>\n\n\n"),
|
||||
simpleBody('"Hello"'));
|
||||
|
||||
// same as previous, but with various HTML comments
|
||||
checkResults(
|
||||
scanForTest("\n<!--\n\nfoo\n-->\n<!-- -->\n"+
|
||||
"<body>\n\nHello\n\n</body>\n\n<!----\n>\n\n"),
|
||||
simpleBody('"Hello"'));
|
||||
|
||||
// head and body
|
||||
checkResults(
|
||||
scanForTest("<head>\n<title>Hello</title>\n</head>\n\n<body>World</body>\n\n"),
|
||||
simpleBody('"World"'),
|
||||
"<title>Hello</title>");
|
||||
|
||||
// head and body with tag whitespace
|
||||
checkResults(
|
||||
scanForTest("<head\n>\n<title>Hello</title>\n</head >\n\n<body>World</body\n\n>\n\n"),
|
||||
simpleBody('"World"'),
|
||||
"<title>Hello</title>");
|
||||
|
||||
// head, body, and template
|
||||
checkResults(
|
||||
scanForTest("<head>\n<title>Hello</title>\n</head>\n\n<body>World</body>\n\n"+
|
||||
'<template name="favoritefood">\n pizza\n</template>\n'),
|
||||
simpleBody('"World"') + simpleTemplate('"favoritefood"', '"pizza"'),
|
||||
"<title>Hello</title>");
|
||||
|
||||
// one-line template
|
||||
checkResults(
|
||||
scanForTest('<template name="favoritefood">pizza</template>'),
|
||||
simpleTemplate('"favoritefood"', '"pizza"'));
|
||||
|
||||
// template with other attributes
|
||||
checkResults(
|
||||
scanForTest('<template foo="bar" name="favoritefood" baz="qux">'+
|
||||
'pizza</template>'),
|
||||
simpleTemplate('"favoritefood"', '"pizza"'));
|
||||
|
||||
// whitespace around '=' in attributes and at end of tag
|
||||
checkResults(
|
||||
scanForTest('<template foo = "bar" name ="favoritefood" baz= "qux" >'+
|
||||
'pizza</template\n\n>'),
|
||||
simpleTemplate('"favoritefood"', '"pizza"'));
|
||||
|
||||
// whitespace around template name
|
||||
checkResults(
|
||||
scanForTest('<template name=" favoritefood ">pizza</template>'),
|
||||
simpleTemplate('"favoritefood"', '"pizza"'));
|
||||
|
||||
// single quotes around template name
|
||||
checkResults(
|
||||
scanForTest('<template name=\'the "cool" template\'>'+
|
||||
'pizza</template>'),
|
||||
simpleTemplate('"the \\"cool\\" template"', '"pizza"'));
|
||||
|
||||
checkResults(scanForTest('<body foo="bar">\n Hello\n</body>'), simpleBody('"Hello"'), "", {foo: "bar"});
|
||||
|
||||
// error cases; exact line numbers are not critical, these just reflect
|
||||
// the current implementation
|
||||
|
||||
// unclosed body (error mentions body)
|
||||
checkError(function() {
|
||||
return scanForTest("\n\n<body>\n Hello\n</body");
|
||||
}, "body", 3);
|
||||
|
||||
// bad open tag
|
||||
checkError(function() {
|
||||
return scanForTest("\n\n\n<bodyd>\n Hello\n</body>");
|
||||
}, "Expected one of: <body>, <head>, <template>", 4);
|
||||
checkError(function() {
|
||||
return scanForTest("\n\n\n\n<body foo=>\n Hello\n</body>");
|
||||
}, "error in tag", 5);
|
||||
|
||||
// unclosed tag
|
||||
checkError(function() {
|
||||
return scanForTest("\n<body>Hello");
|
||||
}, "nclosed", 2);
|
||||
|
||||
// unnamed template
|
||||
checkError(function() {
|
||||
return scanForTest(
|
||||
"\n\n<template>Hi</template>\n\n<template>Hi</template>");
|
||||
}, "name", 3);
|
||||
|
||||
// helpful doctype message
|
||||
checkError(function() {
|
||||
return scanForTest(
|
||||
'<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" '+
|
||||
'"http://www.w3.org/TR/html4/strict.dtd">'+
|
||||
'\n\n<head>\n</head>');
|
||||
}, "DOCTYPE", 1);
|
||||
|
||||
// lowercase basic doctype
|
||||
checkError(function() {
|
||||
return scanForTest(
|
||||
'<!doctype html>');
|
||||
}, "DOCTYPE", 1);
|
||||
|
||||
// attributes on head not supported
|
||||
checkError(function() {
|
||||
return scanForTest('<head foo="bar">\n Hello\n</head>');
|
||||
}, "<head>", 1);
|
||||
|
||||
// can't mismatch quotes
|
||||
checkError(function() {
|
||||
return scanForTest('<template name="foo\'>'+
|
||||
'pizza</template>');
|
||||
}, "error in tag", 1);
|
||||
|
||||
// unexpected <html> at top level
|
||||
checkError(function() {
|
||||
return scanForTest('\n<html>\n</html>');
|
||||
}, "Expected one of: <body>, <head>, <template>", 2);
|
||||
|
||||
});
|
||||
174
packages/static-html-tools/html-scanner.js
Normal file
174
packages/static-html-tools/html-scanner.js
Normal file
@@ -0,0 +1,174 @@
|
||||
import { CompileError } from './throw-compile-error';
|
||||
|
||||
export function scanHtmlForTags(options) {
|
||||
const scan = new HtmlScan(options);
|
||||
return scan.getTags();
|
||||
}
|
||||
|
||||
/**
|
||||
* Scan an HTML file for top-level tags and extract their contents. Pass them to
|
||||
* a tag handler (an object with a handleTag method)
|
||||
*
|
||||
* This is a primitive, regex-based scanner. It scans
|
||||
* top-level tags, which are allowed to have attributes,
|
||||
* and ignores top-level HTML comments.
|
||||
*/
|
||||
class HtmlScan {
|
||||
/**
|
||||
* Initialize and run a scan of a single file
|
||||
* @param {String} sourceName The filename, used in errors only
|
||||
* @param {String} contents The contents of the file
|
||||
* @param {String[]} tagNames An array of tag names that are accepted at the
|
||||
* top level. If any other tag is encountered, an error is thrown.
|
||||
*/
|
||||
constructor({
|
||||
sourceName,
|
||||
contents,
|
||||
tagNames
|
||||
}) {
|
||||
this.sourceName = sourceName;
|
||||
this.contents = contents;
|
||||
this.tagNames = tagNames;
|
||||
|
||||
this.rest = contents;
|
||||
this.index = 0;
|
||||
|
||||
this.tags = [];
|
||||
|
||||
const tagNameRegex = this.tagNames.join("|");
|
||||
const openTagRegex = new RegExp(`^((<(${tagNameRegex})\\b)|(<!--)|(<!DOCTYPE|{{!)|$)`, "i");
|
||||
|
||||
while (this.rest) {
|
||||
// skip whitespace first (for better line numbers)
|
||||
this.advance(this.rest.match(/^\s*/)[0].length);
|
||||
|
||||
const match = openTagRegex.exec(this.rest);
|
||||
|
||||
if (! match) {
|
||||
this.throwCompileError(`Expected one of: <${this.tagNames.join('>, <')}>`);
|
||||
}
|
||||
|
||||
const matchToken = match[1];
|
||||
const matchTokenTagName = match[3];
|
||||
const matchTokenComment = match[4];
|
||||
const matchTokenUnsupported = match[5];
|
||||
|
||||
const tagStartIndex = this.index;
|
||||
this.advance(match.index + match[0].length);
|
||||
|
||||
if (! matchToken) {
|
||||
break; // matched $ (end of file)
|
||||
}
|
||||
|
||||
if (matchTokenComment === '<!--') {
|
||||
// top-level HTML comment
|
||||
const commentEnd = /--\s*>/.exec(this.rest);
|
||||
if (! commentEnd)
|
||||
this.throwCompileError("unclosed HTML comment in template file");
|
||||
this.advance(commentEnd.index + commentEnd[0].length);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (matchTokenUnsupported) {
|
||||
switch (matchTokenUnsupported.toLowerCase()) {
|
||||
case '<!doctype':
|
||||
this.throwCompileError(
|
||||
"Can't set DOCTYPE here. (Meteor sets <!DOCTYPE html> for you)");
|
||||
case '{{!':
|
||||
this.throwCompileError(
|
||||
"Can't use '{{! }}' outside a template. Use '<!-- -->'.");
|
||||
}
|
||||
|
||||
this.throwCompileError();
|
||||
}
|
||||
|
||||
// otherwise, a <tag>
|
||||
const tagName = matchTokenTagName.toLowerCase();
|
||||
const tagAttribs = {}; // bare name -> value dict
|
||||
const tagPartRegex = /^\s*((([a-zA-Z0-9:_-]+)\s*=\s*(["'])(.*?)\4)|(>))/;
|
||||
|
||||
// read attributes
|
||||
let attr;
|
||||
while ((attr = tagPartRegex.exec(this.rest))) {
|
||||
const attrToken = attr[1];
|
||||
const attrKey = attr[3];
|
||||
let attrValue = attr[5];
|
||||
this.advance(attr.index + attr[0].length);
|
||||
|
||||
if (attrToken === '>') {
|
||||
break;
|
||||
}
|
||||
|
||||
// XXX we don't HTML unescape the attribute value
|
||||
// (e.g. to allow "abcd"efg") or protect against
|
||||
// collisions with methods of tagAttribs (e.g. for
|
||||
// a property named toString)
|
||||
attrValue = attrValue.match(/^\s*([\s\S]*?)\s*$/)[1]; // trim
|
||||
tagAttribs[attrKey] = attrValue;
|
||||
}
|
||||
|
||||
if (! attr) { // didn't end on '>'
|
||||
this.throwCompileError("Parse error in tag");
|
||||
}
|
||||
|
||||
// find </tag>
|
||||
const end = (new RegExp('</'+tagName+'\\s*>', 'i')).exec(this.rest);
|
||||
if (! end) {
|
||||
this.throwCompileError("unclosed <"+tagName+">");
|
||||
}
|
||||
|
||||
const tagContents = this.rest.slice(0, end.index);
|
||||
const contentsStartIndex = this.index;
|
||||
|
||||
// trim the tag contents.
|
||||
// this is a courtesy and is also relied on by some unit tests.
|
||||
var m = tagContents.match(/^([ \t\r\n]*)([\s\S]*?)[ \t\r\n]*$/);
|
||||
const trimmedContentsStartIndex = contentsStartIndex + m[1].length;
|
||||
const trimmedTagContents = m[2];
|
||||
|
||||
const tag = {
|
||||
tagName: tagName,
|
||||
attribs: tagAttribs,
|
||||
contents: trimmedTagContents,
|
||||
contentsStartIndex: trimmedContentsStartIndex,
|
||||
tagStartIndex: tagStartIndex,
|
||||
fileContents: this.contents,
|
||||
sourceName: this.sourceName
|
||||
};
|
||||
|
||||
// save the tag
|
||||
this.tags.push(tag);
|
||||
|
||||
// advance afterwards, so that line numbers in errors are correct
|
||||
this.advance(end.index + end[0].length);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Advance the parser
|
||||
* @param {Number} amount The amount of characters to advance
|
||||
*/
|
||||
advance(amount) {
|
||||
this.rest = this.rest.substring(amount);
|
||||
this.index += amount;
|
||||
}
|
||||
|
||||
throwCompileError(msg, overrideIndex) {
|
||||
const finalIndex = (typeof overrideIndex === 'number' ? overrideIndex : this.index);
|
||||
|
||||
const err = new CompileError();
|
||||
err.message = msg || "bad formatting in template file";
|
||||
err.file = this.sourceName;
|
||||
err.line = this.contents.substring(0, finalIndex).split('\n').length;
|
||||
|
||||
throw err;
|
||||
}
|
||||
|
||||
throwBodyAttrsError(msg) {
|
||||
this.parseError(msg);
|
||||
}
|
||||
|
||||
getTags() {
|
||||
return this.tags;
|
||||
}
|
||||
}
|
||||
36
packages/static-html-tools/package.js
Normal file
36
packages/static-html-tools/package.js
Normal file
@@ -0,0 +1,36 @@
|
||||
Package.describe({
|
||||
name: 'static-html-tools',
|
||||
summary: "Tools for static-html",
|
||||
version: '1.0.0',
|
||||
git: 'https://github.com/meteor/meteor.git'
|
||||
});
|
||||
|
||||
Npm.depends({
|
||||
'lodash.isempty': '4.4.0'
|
||||
});
|
||||
|
||||
Package.onUse(function(api) {
|
||||
api.use([
|
||||
'ecmascript',
|
||||
'caching-compiler'
|
||||
]);
|
||||
|
||||
api.export('TemplatingTools');
|
||||
|
||||
api.mainModule('templating-tools.js');
|
||||
});
|
||||
|
||||
Package.onTest(function(api) {
|
||||
api.use([
|
||||
'tinytest',
|
||||
'ecmascript'
|
||||
]);
|
||||
|
||||
api.use([
|
||||
'templating-tools'
|
||||
]);
|
||||
|
||||
api.addFiles([
|
||||
'html-scanner-tests.js'
|
||||
], 'server');
|
||||
});
|
||||
3
packages/static-html-tools/templating-tools.js
Normal file
3
packages/static-html-tools/templating-tools.js
Normal file
@@ -0,0 +1,3 @@
|
||||
export { throwCompileError, CompileError } from './throw-compile-error';
|
||||
export { scanHtmlForTags } from './html-scanner';
|
||||
export { CachingHtmlCompiler } from './caching-html-compiler';
|
||||
12
packages/static-html-tools/throw-compile-error.js
Normal file
12
packages/static-html-tools/throw-compile-error.js
Normal file
@@ -0,0 +1,12 @@
|
||||
export class CompileError {}
|
||||
|
||||
export function throwCompileError(tag, message, overrideIndex) {
|
||||
const finalIndex = (typeof overrideIndex === 'number' ?
|
||||
overrideIndex : tag.tagStartIndex);
|
||||
|
||||
const err = new CompileError();
|
||||
err.message = message || "bad formatting in template file";
|
||||
err.file = tag.sourceName;
|
||||
err.line = tag.fileContents.substring(0, finalIndex).split('\n').length;
|
||||
throw err;
|
||||
}
|
||||
@@ -1,16 +1,16 @@
|
||||
Package.describe({
|
||||
name: 'static-html',
|
||||
summary: "Define static page content in .html files",
|
||||
version: '1.3.3',
|
||||
version: '1.4.0',
|
||||
git: 'https://github.com/meteor/meteor.git'
|
||||
});
|
||||
|
||||
Package.registerBuildPlugin({
|
||||
name: "compileStaticHtmlBatch",
|
||||
use: [
|
||||
'ecmascript@0.16.8-beta300.7',
|
||||
'caching-html-compiler@1.2.2 || 2.0.0-alpha300.16',
|
||||
'templating-tools@1.2.3 || 2.0.0-alpha300.16'
|
||||
'ecmascript@0.16.9',
|
||||
'static-html-tools@1.0.0',
|
||||
'caching-compiler@2.0.0',
|
||||
],
|
||||
sources: [
|
||||
'static-html.js'
|
||||
|
||||
@@ -1,22 +1,24 @@
|
||||
import { CachingHtmlCompiler, scanHtmlForTags, throwCompileError } from 'meteor/static-html-tools';
|
||||
|
||||
Plugin.registerCompiler({
|
||||
extensions: ['html'],
|
||||
archMatching: 'web',
|
||||
isTemplate: true
|
||||
}, () => new CachingHtmlCompiler("static-html", TemplatingTools.scanHtmlForTags, compileTagsToStaticHtml));
|
||||
}, () => new CachingHtmlCompiler("static-html", scanHtmlForTags, compileTagsToStaticHtml));
|
||||
|
||||
// Same API as TutorialTools.compileTagsWithSpacebars, but instead of compiling
|
||||
// with Spacebars, it just returns static HTML
|
||||
function compileTagsToStaticHtml(tags) {
|
||||
var handler = new StaticHtmlTagHandler();
|
||||
const handler = new StaticHtmlTagHandler();
|
||||
|
||||
tags.forEach((tag) => {
|
||||
handler.addTagToResults(tag);
|
||||
});
|
||||
|
||||
return handler.getResults();
|
||||
};
|
||||
}
|
||||
|
||||
var isEmpty = obj => [Object, Array].includes((obj || {}).constructor) && !Object.entries((obj || {})).length;
|
||||
const isEmpty = obj => [Object, Array].includes((obj || {}).constructor) && !Object.entries((obj || {})).length;
|
||||
|
||||
class StaticHtmlTagHandler {
|
||||
constructor() {
|
||||
@@ -86,7 +88,7 @@ class StaticHtmlTagHandler {
|
||||
}
|
||||
|
||||
throwCompileError(message, overrideIndex) {
|
||||
TemplatingTools.throwCompileError(this.tag, message, overrideIndex);
|
||||
throwCompileError(this.tag, message, overrideIndex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1133,9 +1133,9 @@
|
||||
}
|
||||
},
|
||||
"regenerator-runtime": {
|
||||
"version": "0.13.5",
|
||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz",
|
||||
"integrity": "sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA=="
|
||||
"version": "0.13.9",
|
||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz",
|
||||
"integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA=="
|
||||
},
|
||||
"rimraf": {
|
||||
"version": "2.7.1",
|
||||
|
||||
Reference in New Issue
Block a user