babel-plugin-htmlbars-inline-precompile
Advanced tools
Comparing version 1.0.0 to 2.0.0
module.exports = { | ||
root: true, | ||
parserOptions: { | ||
ecmaVersion: 2016, | ||
ecmaVersion: 2017, | ||
}, | ||
plugins: ['node'], | ||
plugins: ['node', 'prettier'], | ||
extends: [ | ||
'eslint:recommended', | ||
'plugin:node/recommended', | ||
'plugin:prettier/recommended', | ||
], | ||
@@ -14,5 +15,3 @@ env: { | ||
}, | ||
rules: { | ||
'ember/new-module-imports': 'off', | ||
}, | ||
rules: { }, | ||
overrides: [ | ||
@@ -22,3 +21,3 @@ // test files | ||
files: [ | ||
'tests/**/*.js', | ||
'__tests__/**/*.js', | ||
], | ||
@@ -25,0 +24,0 @@ env: { |
@@ -1,3 +0,33 @@ | ||
# Change Log | ||
## v2.0.0 (2019-08-30) | ||
#### :boom: Breaking Change | ||
* [#77](https://github.com/ember-cli/babel-plugin-htmlbars-inline-precompile/pull/77) Drop Node 6 and 11 support. ([@rwjblue](https://github.com/rwjblue)) | ||
* [#50](https://github.com/ember-cli/babel-plugin-htmlbars-inline-precompile/pull/50) Drop support for Node 4 ([@Turbo87](https://github.com/Turbo87)) | ||
#### :rocket: Enhancement | ||
* [#89](https://github.com/ember-cli/babel-plugin-htmlbars-inline-precompile/pull/89) Add an inline comment with the original template. ([@rwjblue](https://github.com/rwjblue)) | ||
* [#75](https://github.com/ember-cli/babel-plugin-htmlbars-inline-precompile/pull/75) Add ability to pass static options to transpilation. ([@rwjblue](https://github.com/rwjblue)) | ||
* [#42](https://github.com/ember-cli/babel-plugin-htmlbars-inline-precompile/pull/42) Test templates from MU co-located tests ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) | ||
#### :memo: Documentation | ||
* [#86](https://github.com/ember-cli/babel-plugin-htmlbars-inline-precompile/pull/86) Add requirements section to README. ([@rwjblue](https://github.com/rwjblue)) | ||
* [#83](https://github.com/ember-cli/babel-plugin-htmlbars-inline-precompile/pull/83) Revamp README. ([@rwjblue](https://github.com/rwjblue)) | ||
#### :house: Internal | ||
* [#87](https://github.com/ember-cli/babel-plugin-htmlbars-inline-precompile/pull/87) Update the test harness to use Babel 7. ([@rwjblue](https://github.com/rwjblue)) | ||
* [#85](https://github.com/ember-cli/babel-plugin-htmlbars-inline-precompile/pull/85) Migrate to building AST nodes instead of replacing with source. ([@rwjblue](https://github.com/rwjblue)) | ||
* [#84](https://github.com/ember-cli/babel-plugin-htmlbars-inline-precompile/pull/84) Add release-it setup. ([@rwjblue](https://github.com/rwjblue)) | ||
* [#79](https://github.com/ember-cli/babel-plugin-htmlbars-inline-precompile/pull/79) Remove unused code for support MU. ([@rwjblue](https://github.com/rwjblue)) | ||
* [#76](https://github.com/ember-cli/babel-plugin-htmlbars-inline-precompile/pull/76) Migrate to GH Actions. ([@rwjblue](https://github.com/rwjblue)) | ||
* [#57](https://github.com/ember-cli/babel-plugin-htmlbars-inline-precompile/pull/57) TravisCI: Remove deprecated `sudo: false` option ([@Turbo87](https://github.com/Turbo87)) | ||
* [#40](https://github.com/ember-cli/babel-plugin-htmlbars-inline-precompile/pull/40) nit: ensure concise functions are used consistently ([@stefanpenner](https://github.com/stefanpenner)) | ||
#### Committers: 5 | ||
- L. Preston Sego III ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) | ||
- Robert Jackson ([@rwjblue](https://github.com/rwjblue)) | ||
- Stefan Penner ([@stefanpenner](https://github.com/stefanpenner)) | ||
- Tobias Bieniek ([@Turbo87](https://github.com/Turbo87)) | ||
- [@dependabot-preview[bot]](https://github.com/apps/dependabot-preview) | ||
## [v0.2.5](https://github.com/ember-cli/babel-plugin-htmlbars-inline-precompile/tree/v0.2.5) (2018-06-02) | ||
@@ -127,2 +157,2 @@ [Full Changelog](https://github.com/ember-cli/babel-plugin-htmlbars-inline-precompile/compare/v0.2.4...v0.2.5) | ||
\* *This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)* | ||
\* *This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)* |
163
index.js
@@ -6,18 +6,106 @@ 'use strict'; | ||
function compileTemplate(precompile, template) { | ||
let options = { | ||
contents: template | ||
function buildExpression(value) { | ||
switch (typeof value) { | ||
case 'string': | ||
return t.stringLiteral(value); | ||
case 'number': | ||
return t.numberLiteral(value); | ||
case 'boolean': | ||
return t.booleanLiteral(value); | ||
case 'object': { | ||
if (Array.isArray(value)) { | ||
return buildArrayExpression(value); | ||
} else { | ||
return buildObjectExpression(value); | ||
} | ||
} | ||
default: | ||
throw new Error( | ||
`hbs compilation error; unexpected type from precompiler: ${typeof value} for ${JSON.stringify( | ||
value | ||
)}` | ||
); | ||
} | ||
} | ||
let compiledTemplateString = `Ember.HTMLBars.template(${precompile(template, options)})`; | ||
function buildObjectExpression(object) { | ||
let properties = []; | ||
for (let key in object) { | ||
let value = object[key]; | ||
return compiledTemplateString; | ||
properties.push(t.objectProperty(t.identifier(key), buildExpression(value))); | ||
} | ||
return t.objectExpression(properties); | ||
} | ||
function buildArrayExpression(array) { | ||
return t.arrayExpression(array.map(i => buildExpression(i))); | ||
} | ||
function parseExpression(buildError, node) { | ||
switch (node.type) { | ||
case 'ObjectExpression': | ||
return parseObjectExpression(buildError, node); | ||
case 'ArrayExpression': { | ||
return parseArrayExpression(buildError, node); | ||
} | ||
case 'StringLiteral': | ||
case 'BooleanLiteral': | ||
case 'NumericLiteral': | ||
return node.value; | ||
default: | ||
throw buildError( | ||
`hbs can only accept static options but you passed ${JSON.stringify(node)}` | ||
); | ||
} | ||
} | ||
function parseArrayExpression(buildError, node) { | ||
let result = node.elements.map(element => parseExpression(buildError, element)); | ||
return result; | ||
} | ||
function parseObjectExpression(buildError, node) { | ||
let result = {}; | ||
node.properties.forEach(property => { | ||
if (property.computed || property.key.type !== 'Identifier') { | ||
throw buildError('hbs can only accept static options'); | ||
} | ||
let value = parseExpression(buildError, property.value); | ||
result[property.key.name] = value; | ||
}); | ||
return result; | ||
} | ||
function compileTemplate(precompile, template, _options) { | ||
let options = Object.assign({ contents: template }, _options); | ||
let precompileResult = precompile(template, options); | ||
let precompiled = JSON.parse(precompileResult); | ||
let templateExpression = buildExpression(precompiled); | ||
t.addComment(templateExpression, 'leading', `\n ${template}\n`, /* line comment? */ false); | ||
return t.callExpression( | ||
t.memberExpression( | ||
t.memberExpression(t.identifier('Ember'), t.identifier('HTMLBars')), | ||
t.identifier('template') | ||
), | ||
[templateExpression] | ||
); | ||
} | ||
return { | ||
visitor: { | ||
ImportDeclaration: function(path, state) { | ||
ImportDeclaration(path, state) { | ||
let node = path.node; | ||
let modulePaths = state.opts.modulePaths || ["htmlbars-inline-precompile"]; | ||
let modulePaths = state.opts.modulePaths || ['htmlbars-inline-precompile']; | ||
let matchingModulePath = modulePaths.find(value => t.isLiteral(node.source, { value })); | ||
@@ -34,3 +122,4 @@ | ||
state.importId = state.importId || path.scope.generateUidIdentifierBasedOnNode(path.node.id); | ||
state.importId = | ||
state.importId || path.scope.generateUidIdentifierBasedOnNode(path.node.id); | ||
path.scope.rename(first.local.name, state.importId.name); | ||
@@ -42,3 +131,5 @@ path.remove(); | ||
TaggedTemplateExpression(path, state) { | ||
if (!state.importId) { return; } | ||
if (!state.importId) { | ||
return; | ||
} | ||
@@ -51,3 +142,5 @@ let tagPath = path.get('tag'); | ||
if (path.node.quasi.expressions.length) { | ||
throw path.buildCodeFrameError("placeholders inside a tagged template string are not supported"); | ||
throw path.buildCodeFrameError( | ||
'placeholders inside a tagged template string are not supported' | ||
); | ||
} | ||
@@ -57,7 +150,9 @@ | ||
path.replaceWithSourceString(compileTemplate(state.opts.precompile, template, state.file.opts.filename)); | ||
path.replaceWith(compileTemplate(state.opts.precompile, template)); | ||
}, | ||
CallExpression(path, state) { | ||
if (!state.importId) { return; } | ||
if (!state.importId) { | ||
return; | ||
} | ||
@@ -69,15 +164,41 @@ let calleePath = path.get('callee'); | ||
let argumentErrorMsg = "hbs should be invoked with a single argument: the template string"; | ||
if (path.node.arguments.length !== 1) { | ||
throw path.buildCodeFrameError(argumentErrorMsg); | ||
let options; | ||
let template = path.node.arguments[0]; | ||
if (template === undefined || typeof template.value !== 'string') { | ||
throw path.buildCodeFrameError( | ||
'hbs should be invoked with at least a single argument: the template string' | ||
); | ||
} | ||
let template = path.node.arguments[0].value; | ||
if (typeof template !== "string") { | ||
throw path.buildCodeFrameError(argumentErrorMsg); | ||
switch (path.node.arguments.length) { | ||
case 0: | ||
throw path.buildCodeFrameError( | ||
'hbs should be invoked with at least a single argument: the template string' | ||
); | ||
case 1: | ||
break; | ||
case 2: { | ||
let astOptions = path.node.arguments[1]; | ||
if (astOptions.type !== 'ObjectExpression') { | ||
throw path.buildCodeFrameError( | ||
'hbs can only be invoked with 2 arguments: the template string, and any static options' | ||
); | ||
} | ||
options = parseObjectExpression(path.buildCodeFrameError.bind(path), astOptions); | ||
break; | ||
} | ||
default: | ||
throw path.buildCodeFrameError( | ||
'hbs can only be invoked with 2 arguments: the template string, and any static options' | ||
); | ||
} | ||
path.replaceWithSourceString(compileTemplate(state.opts.precompile, template, state.file.opts.filename)); | ||
let { precompile } = state.opts; | ||
path.replaceWith(compileTemplate(precompile, template.value, options)); | ||
}, | ||
} | ||
}, | ||
}; | ||
@@ -87,3 +208,3 @@ }; | ||
module.exports._parallelBabel = { | ||
requireFile: __filename | ||
requireFile: __filename, | ||
}; | ||
@@ -90,0 +211,0 @@ |
{ | ||
"name": "babel-plugin-htmlbars-inline-precompile", | ||
"version": "1.0.0", | ||
"version": "2.0.0", | ||
"description": "Babel plugin to replace tagged template strings with precompiled HTMLBars templates", | ||
"repository": "https://github.com/ember-cli/babel-plugin-htmlbars-inline-precompile", | ||
"license": "MIT", | ||
"author": "Clemens Müller <cmueller.418@gmail.com>", | ||
"scripts": { | ||
"lint": "eslint --cache .", | ||
"test": "jest" | ||
}, | ||
"repository": "https://github.com/ember-cli/babel-plugin-htmlbars-inline-precompile", | ||
"author": "Clemens Müller <cmueller.418@gmail.com>", | ||
"license": "MIT", | ||
"engines": { | ||
"node": ">= 4" | ||
"jest": { | ||
"projects": [ | ||
"<rootDir>/jest-test.config.js" | ||
] | ||
}, | ||
"devDependencies": { | ||
"babel-core": "^6.7.4", | ||
"babel-plugin-transform-es2015-modules-amd": "^6.24.0", | ||
"babel-plugin-transform-es2015-template-literals": "^6.22.0", | ||
"eslint-plugin-node": "^6.0.1", | ||
"jest": "^21.0.0", | ||
"jest-runner-eslint": "^0.6.0" | ||
"@babel/core": "^7.5.5", | ||
"@babel/plugin-transform-modules-amd": "^7.5.0", | ||
"@babel/plugin-transform-template-literals": "^7.4.4", | ||
"common-tags": "^1.8.0", | ||
"ember-source": "^3.12.0", | ||
"eslint": "^6.3.0", | ||
"eslint-config-prettier": "^6.1.0", | ||
"eslint-plugin-node": "^9.2.0", | ||
"eslint-plugin-prettier": "^3.1.0", | ||
"jest": "^24.9.0", | ||
"prettier": "^1.18.2", | ||
"release-it": "^12.2.1", | ||
"release-it-lerna-changelog": "^1.0.3" | ||
}, | ||
"jest": { | ||
"projects": [ | ||
"<rootDir>/jest-test.config.js", | ||
"<rootDir>/jest-eslint.config.js" | ||
] | ||
"engines": { | ||
"node": "8.* || 10.* || >= 12.*" | ||
}, | ||
"publishConfig": { | ||
"registry": "https://registry.npmjs.org" | ||
}, | ||
"release-it": { | ||
"plugins": { | ||
"release-it-lerna-changelog": { | ||
"infile": "CHANGELOG.md" | ||
} | ||
}, | ||
"git": { | ||
"tagName": "v${version}" | ||
}, | ||
"github": { | ||
"release": true | ||
} | ||
} | ||
} |
@@ -1,74 +0,83 @@ | ||
# babel-plugin-htmlbars-inline-precompile [![Build Status](https://travis-ci.org/ember-cli/babel-plugin-htmlbars-inline-precompile.svg?branch=master)](https://travis-ci.org/ember-cli/babel-plugin-htmlbars-inline-precompile) | ||
# babel-plugin-htmlbars-inline-precompile | ||
Babel plugin to replace ES6 tagged template strings with the `HTMLBars.precompile`d version of it: | ||
<a href="https://github.com/ember-cli/babel-plugin-htmlbars-inline-precompile"><img alt="Build Status" src="https://github.com/ember-cli/babel-plugin-htmlbars-inline-precompile/workflows/CI/badge.svg"></a> | ||
``` js | ||
Babel plugin to replace tagged `.hbs` formatted strings with a precompiled version. | ||
## Requirements | ||
* Node 8+ | ||
* Ember 2.10+ | ||
* Babel 7 | ||
## Usage | ||
Can be used as either a normal function invocation or a tagged template string: | ||
```js | ||
import hbs from 'htmlbars-inline-precompile'; | ||
module("my view"); | ||
hbs`some {{handlebarsthingy}}`; | ||
hbs('some {{handlebarsthingy}}'); | ||
``` | ||
test("inline templates ftw", function(assert) { | ||
var view = Ember.View.create({ | ||
greeting: "inline template world", | ||
template: hbs` | ||
<span>hello {{view.greeting}}</span> | ||
` | ||
}); | ||
When used as a normal function invocation, you can pass additional options (e.g. to configure the resulting template's `moduleName` metadata): | ||
view.appendTo('#testing'); | ||
```js | ||
import hbs from 'htmlbars-inline-precompile'; | ||
assert.equal(view.$().html().trim(), "<span>hello inline template world</span>"); | ||
}); | ||
hbs('some {{handlebarsthingy}}', { moduleName: 'some/path/to/file.hbs' }); | ||
``` | ||
results in | ||
## Babel Plugin Usage | ||
``` js | ||
module("my view"); | ||
var HTMLBarsCompiler = require('./bower_components/ember/ember-template-compiler'); | ||
var HTMLBarsInlinePrecompile = require('babel-plugin-htmlbars-inline-precompile'); | ||
test("inline templates ftw", function(assert) { | ||
var view = Ember.View.create({ | ||
greeting: "inline template world", | ||
template: Ember.HTMLBars.template(function() { | ||
/* crazy HTMLBars template function stuff */ | ||
}) | ||
}); | ||
view.appendTo('#testing'); | ||
assert.equal(view.$().html().trim(), "<span>hello inline template world</span>"); | ||
require('babel').transform("code", { | ||
plugins: [ | ||
[HTMLBarsInlinePrecompile, {precompile: HTMLBarsCompiler.precompile}], | ||
], | ||
}); | ||
``` | ||
If the template is compact, a normal string can be passed as argument as well: | ||
### Example | ||
``` js | ||
import { module, test } from 'qunit'; | ||
import { setupRenderingTest } from 'ember-qunit'; | ||
import { render } from '@ember/test-helpers'; | ||
import hbs from 'htmlbars-inline-precompile'; | ||
module("my view"); | ||
module("my component", function(hooks) { | ||
setupRenderingTest(hooks); | ||
test("inline templates ftw", function(assert) { | ||
var view = Ember.View.create({ | ||
greeting: "inline template world", | ||
template: hbs('<h1>{{view.greeting}}</h1>') | ||
test('inline templates ftw', async function(assert) { | ||
await render(hbs`hello!`); | ||
assert.dom().hasText('hello!'); | ||
}); | ||
view.appendTo('#testing'); | ||
assert.equal(view.$().html().trim(), "<h1>inline template world</h1>"); | ||
}); | ||
``` | ||
results in | ||
## Usage | ||
``` js | ||
var HTMLBarsCompiler = require('./bower_components/ember/ember-template-compiler'); | ||
var HTMLBarsInlinePrecompile = require('babel-plugin-htmlbars-inline-precompile'); | ||
import { module, test } from 'qunit'; | ||
import { setupRenderingTest } from 'ember-qunit'; | ||
import { render } from '@ember/test-helpers'; | ||
import hbs from 'htmlbars-inline-precompile'; | ||
require('babel').transform("code", { | ||
plugins: [ | ||
[HTMLBarsInlinePrecompile, {precompile: HTMLBarsCompiler.precompile}], | ||
], | ||
module("my component", function(hooks) { | ||
setupRenderingTest(hooks); | ||
test('inline templates ftw', async function(assert) { | ||
await render(Ember.HTMLBars.template(function() { | ||
/* crazy HTMLBars template function stuff */ | ||
})); | ||
assert.dom().hasText('hello!'); | ||
}); | ||
}); | ||
``` |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
421
84
33454
13
9
1