mirror of
https://github.com/marko-js/marko.git
synced 2025-12-08 19:26:05 +00:00
Fixes #224 and Fixes #216 - Marko v3: marko-taglib.json --> marko.json and improved taglib discovery
This commit is contained in:
parent
8a184dea2f
commit
e8e4ef332d
@ -141,10 +141,10 @@ var taglibLookup = require('./taglib-lookup');
|
||||
exports.taglibLookup = taglibLookup;
|
||||
exports.taglibLoader = require('./taglib-loader');
|
||||
|
||||
taglibLookup.registerTaglib(require.resolve('../taglibs/core/marko-taglib.json'));
|
||||
taglibLookup.registerTaglib(require.resolve('../taglibs/layout/marko-taglib.json'));
|
||||
taglibLookup.registerTaglib(require.resolve('../taglibs/html/marko-taglib.json'));
|
||||
taglibLookup.registerTaglib(require.resolve('../taglibs/async/marko-taglib.json'));
|
||||
taglibLookup.registerTaglib(require.resolve('../taglibs/core/marko.json'));
|
||||
taglibLookup.registerTaglib(require.resolve('../taglibs/layout/marko.json'));
|
||||
taglibLookup.registerTaglib(require.resolve('../taglibs/html/marko.json'));
|
||||
taglibLookup.registerTaglib(require.resolve('../taglibs/async/marko.json'));
|
||||
|
||||
|
||||
|
||||
|
||||
@ -13,17 +13,16 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
var taglibLoader = require('../taglib-loader');
|
||||
var trailingSlashRegExp = /[\\/]$/;
|
||||
'use strict';
|
||||
|
||||
var excludedDirs = {};
|
||||
var taglibLoader = require('../taglib-loader');
|
||||
var nodePath = require('path');
|
||||
var fs = require('fs');
|
||||
var existsCache = {};
|
||||
var findCache = {};
|
||||
var taglibsForNodeModulesDirCache = {};
|
||||
|
||||
var realpathCache = {};
|
||||
var raptorModulesUtil = require('raptor-modules/util');
|
||||
var resolveFrom = require('resolve-from');
|
||||
|
||||
function existsCached(path) {
|
||||
var exists = existsCache[path];
|
||||
@ -34,124 +33,36 @@ function existsCached(path) {
|
||||
return exists;
|
||||
}
|
||||
|
||||
function realpathCached(path) {
|
||||
var realPath = realpathCache[path];
|
||||
if (realPath === undefined) {
|
||||
try {
|
||||
realPath = fs.realpathSync(path);
|
||||
} catch(e) {
|
||||
realPath = null;
|
||||
}
|
||||
|
||||
realpathCache[path] = realPath;
|
||||
}
|
||||
return realPath;
|
||||
}
|
||||
|
||||
function tryDir(dirname, helper) {
|
||||
var taglibPath = nodePath.join(dirname, 'marko-taglib.json');
|
||||
if (existsCached(taglibPath)) {
|
||||
var taglib = taglibLoader.load(taglibPath);
|
||||
helper.addTaglib(taglib);
|
||||
function getModuleRootPackage(dirname) {
|
||||
try {
|
||||
return raptorModulesUtil.getModuleRootPackage(dirname);
|
||||
} catch(e) {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
function tryNodeModules(parent, helper) {
|
||||
if (nodePath.basename(parent) === 'node_modules') {
|
||||
return;
|
||||
function getAllDependencyNames(pkg) {
|
||||
var map = {};
|
||||
|
||||
if (pkg.dependencies) {
|
||||
Object.keys(pkg.dependencies).forEach((name) => {
|
||||
map[name] = true;
|
||||
});
|
||||
}
|
||||
|
||||
var nodeModulesDir = nodePath.join(parent, 'node_modules');
|
||||
|
||||
var taglibsForNodeModulesDir = taglibsForNodeModulesDirCache[nodeModulesDir];
|
||||
if (taglibsForNodeModulesDir !== undefined) {
|
||||
if (taglibsForNodeModulesDir !== null) {
|
||||
for (var i = 0, len = taglibsForNodeModulesDir.length; i < len; i++) {
|
||||
var taglib = taglibsForNodeModulesDir[i];
|
||||
|
||||
var moduleName = taglib.moduleName;
|
||||
if (moduleName && !helper.foundTaglibPackages[moduleName]) {
|
||||
// Fixes https://github.com/marko-js/marko/issues/140
|
||||
// If the same node_module is found multiple times then only load the first one.
|
||||
// Only the package name (that is: node_modules/<module_name>) matters and the
|
||||
// package version does not matter.
|
||||
helper.addTaglib(taglib);
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
if (pkg.peerDependencies) {
|
||||
Object.keys(pkg.peerDependencies).forEach((name) => {
|
||||
map[name] = true;
|
||||
});
|
||||
}
|
||||
|
||||
if ((nodeModulesDir = realpathCached(nodeModulesDir))) {
|
||||
taglibsForNodeModulesDir = [];
|
||||
|
||||
var handlePackageDir = function(packageName) {
|
||||
// Fixes https://github.com/marko-js/marko/issues/140
|
||||
// If the same node_module is found multiple times then only load the first one.
|
||||
// Only the package name (that is: node_modules/<module_name>) matters and the
|
||||
// package version does not matter.
|
||||
if (helper.foundTaglibPackages[packageName]) {
|
||||
return;
|
||||
}
|
||||
|
||||
helper.foundTaglibPackages[packageName] = true;
|
||||
|
||||
var moduleDir = nodePath.join(nodeModulesDir, packageName);
|
||||
var taglibPath = nodePath.join(moduleDir, 'marko-taglib.json');
|
||||
|
||||
if (existsCached(taglibPath)) {
|
||||
taglibPath = fs.realpathSync(taglibPath);
|
||||
|
||||
var taglib = taglibLoader.load(taglibPath);
|
||||
taglib.moduleName = packageName;
|
||||
taglibsForNodeModulesDir.push(taglib);
|
||||
helper.addTaglib(taglib);
|
||||
}
|
||||
};
|
||||
|
||||
fs.readdirSync(nodeModulesDir)
|
||||
.forEach(function(packageName) {
|
||||
if (packageName.charAt(0) === '@') {
|
||||
// Add support for npm scoped packages. Scoped packages
|
||||
// get instaled into subdirectories organized by user.
|
||||
// For example:
|
||||
// node_modules/@foo/my-package
|
||||
// node_modules/@foo/another-package
|
||||
|
||||
var scope = packageName; // e.g. scope = '@foo'
|
||||
|
||||
// We need to loop over the nested directory to automatically
|
||||
// discover taglibs exported by scoped packages.
|
||||
fs.readdirSync(nodePath.join(nodeModulesDir, scope))
|
||||
.forEach(function(packageName) {
|
||||
handlePackageDir(scope + '/' + packageName); // @foo/my-package
|
||||
});
|
||||
} else {
|
||||
handlePackageDir(packageName);
|
||||
}
|
||||
});
|
||||
|
||||
taglibsForNodeModulesDirCache[nodeModulesDir] = taglibsForNodeModulesDir.length ? taglibsForNodeModulesDir : null;
|
||||
} else {
|
||||
taglibsForNodeModulesDirCache[nodeModulesDir] = null;
|
||||
}
|
||||
}
|
||||
|
||||
function findHelper(dirname, helper) {
|
||||
if (dirname.length !== 1) {
|
||||
dirname = dirname.replace(trailingSlashRegExp, '');
|
||||
if (pkg.devDependencies) {
|
||||
Object.keys(pkg.devDependencies).forEach((name) => {
|
||||
map[name] = true;
|
||||
});
|
||||
}
|
||||
|
||||
if (!excludedDirs[dirname]) {
|
||||
tryDir(dirname, helper);
|
||||
tryNodeModules(dirname, helper);
|
||||
}
|
||||
|
||||
var parent = nodePath.dirname(dirname);
|
||||
if (parent && parent !== dirname) {
|
||||
// TODO: Don't use recursion (there's a simpler way)
|
||||
findHelper(parent, helper);
|
||||
}
|
||||
return Object.keys(map);
|
||||
}
|
||||
|
||||
function find(dirname, registeredTaglibs) {
|
||||
@ -179,7 +90,48 @@ function find(dirname, registeredTaglibs) {
|
||||
foundTaglibPackages: {}
|
||||
};
|
||||
|
||||
findHelper(dirname, helper);
|
||||
var rootDirname = process.cwd(); // Don't search up past this directory
|
||||
var rootPkg = getModuleRootPackage(dirname);
|
||||
if (rootPkg) {
|
||||
rootDirname = rootPkg.__dirname; // Use the package's root directory as the top-level directory
|
||||
}
|
||||
|
||||
|
||||
// First walk up the directory tree looking for marko.json files
|
||||
let curDirname = dirname;
|
||||
while(true) {
|
||||
let taglibPath = nodePath.join(curDirname, 'marko.json');
|
||||
if (existsCached(taglibPath)) {
|
||||
var taglib = taglibLoader.load(taglibPath);
|
||||
helper.addTaglib(taglib);
|
||||
}
|
||||
|
||||
if (curDirname === rootDirname) {
|
||||
break;
|
||||
}
|
||||
|
||||
let parentDirname = nodePath.dirname(curDirname);
|
||||
if (!parentDirname || parentDirname === curDirname) {
|
||||
break;
|
||||
}
|
||||
curDirname = parentDirname;
|
||||
}
|
||||
|
||||
if (rootPkg) {
|
||||
// Now look for `marko.json` from installed packages
|
||||
getAllDependencyNames(rootPkg).forEach((name) => {
|
||||
let taglibPath;
|
||||
try {
|
||||
taglibPath = resolveFrom(rootPkg.__dirname, name + '/marko.json');
|
||||
} catch(e) {
|
||||
// The installed dependency does not export a taglib... skip it
|
||||
return;
|
||||
}
|
||||
|
||||
var taglib = taglibLoader.load(taglibPath);
|
||||
helper.addTaglib(taglib);
|
||||
});
|
||||
}
|
||||
|
||||
found = found.concat(registeredTaglibs);
|
||||
|
||||
@ -188,12 +140,6 @@ function find(dirname, registeredTaglibs) {
|
||||
return found;
|
||||
}
|
||||
|
||||
function excludeDir(dirname) {
|
||||
|
||||
dirname = dirname.replace(trailingSlashRegExp, '');
|
||||
excludedDirs[dirname] = true;
|
||||
}
|
||||
|
||||
function clearCaches() {
|
||||
existsCache = {};
|
||||
findCache = {};
|
||||
@ -201,5 +147,4 @@ function clearCaches() {
|
||||
}
|
||||
|
||||
exports.find = find;
|
||||
exports.excludeDir = excludeDir;
|
||||
exports.clearCaches = clearCaches;
|
||||
|
||||
@ -183,7 +183,7 @@ TaglibHandlers.prototype = {
|
||||
var dependencyName = dependencyNames[j];
|
||||
|
||||
try {
|
||||
importPath = resolveFrom(dirname, dependencyName + '/marko-taglib.json');
|
||||
importPath = resolveFrom(dirname, dependencyName + '/marko.json');
|
||||
} catch(e) {}
|
||||
|
||||
if (importPath) {
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
/*
|
||||
* Copyright 2011 eBay Software Foundation
|
||||
*
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
||||
3
test/fixtures/taglib-finder/autotest/deeply-nested-gaps/a/b/c/marko.json
vendored
Normal file
3
test/fixtures/taglib-finder/autotest/deeply-nested-gaps/a/b/c/marko.json
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
|
||||
}
|
||||
3
test/fixtures/taglib-finder/autotest/deeply-nested-gaps/a/marko.json
vendored
Normal file
3
test/fixtures/taglib-finder/autotest/deeply-nested-gaps/a/marko.json
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
|
||||
}
|
||||
4
test/fixtures/taglib-finder/autotest/deeply-nested-gaps/expected.json
vendored
Normal file
4
test/fixtures/taglib-finder/autotest/deeply-nested-gaps/expected.json
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
[
|
||||
"/a/b/c/marko.json",
|
||||
"/a/marko.json"
|
||||
]
|
||||
4
test/fixtures/taglib-finder/autotest/deeply-nested-gaps/package.json
vendored
Normal file
4
test/fixtures/taglib-finder/autotest/deeply-nested-gaps/package.json
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"name": "taglib-finder-test",
|
||||
"version": "0.0.0"
|
||||
}
|
||||
1
test/fixtures/taglib-finder/autotest/deeply-nested-gaps/test.js
vendored
Normal file
1
test/fixtures/taglib-finder/autotest/deeply-nested-gaps/test.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
exports.dir = 'a/b/c';
|
||||
3
test/fixtures/taglib-finder/autotest/deeply-nested-plus-installed/a/b/c/marko.json
vendored
Normal file
3
test/fixtures/taglib-finder/autotest/deeply-nested-plus-installed/a/b/c/marko.json
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
|
||||
}
|
||||
3
test/fixtures/taglib-finder/autotest/deeply-nested-plus-installed/a/b/marko.json
vendored
Normal file
3
test/fixtures/taglib-finder/autotest/deeply-nested-plus-installed/a/b/marko.json
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
|
||||
}
|
||||
3
test/fixtures/taglib-finder/autotest/deeply-nested-plus-installed/a/marko.json
vendored
Normal file
3
test/fixtures/taglib-finder/autotest/deeply-nested-plus-installed/a/marko.json
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
|
||||
}
|
||||
8
test/fixtures/taglib-finder/autotest/deeply-nested-plus-installed/expected.json
vendored
Normal file
8
test/fixtures/taglib-finder/autotest/deeply-nested-plus-installed/expected.json
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
[
|
||||
"/a/b/c/marko.json",
|
||||
"/a/b/marko.json",
|
||||
"/a/marko.json",
|
||||
"/node_modules/dependency-with-taglib/marko.json",
|
||||
"/node_modules/peer-dependency-with-taglib/marko.json",
|
||||
"/node_modules/dev-dependency-with-taglib/marko.json"
|
||||
]
|
||||
3
test/fixtures/taglib-finder/autotest/deeply-nested-plus-installed/node_modules/dependency-with-taglib/marko.json
generated
vendored
Normal file
3
test/fixtures/taglib-finder/autotest/deeply-nested-plus-installed/node_modules/dependency-with-taglib/marko.json
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
|
||||
}
|
||||
4
test/fixtures/taglib-finder/autotest/deeply-nested-plus-installed/node_modules/dependency-with-taglib/package.json
generated
vendored
Normal file
4
test/fixtures/taglib-finder/autotest/deeply-nested-plus-installed/node_modules/dependency-with-taglib/package.json
generated
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"name": "dependency-with-taglib",
|
||||
"version": "0.0.1"
|
||||
}
|
||||
4
test/fixtures/taglib-finder/autotest/deeply-nested-plus-installed/node_modules/dependency-without-taglib/package.json
generated
vendored
Normal file
4
test/fixtures/taglib-finder/autotest/deeply-nested-plus-installed/node_modules/dependency-without-taglib/package.json
generated
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"name": "dependency-without-taglib",
|
||||
"version": "0.0.1"
|
||||
}
|
||||
3
test/fixtures/taglib-finder/autotest/deeply-nested-plus-installed/node_modules/dev-dependency-with-taglib/marko.json
generated
vendored
Normal file
3
test/fixtures/taglib-finder/autotest/deeply-nested-plus-installed/node_modules/dev-dependency-with-taglib/marko.json
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
|
||||
}
|
||||
4
test/fixtures/taglib-finder/autotest/deeply-nested-plus-installed/node_modules/dev-dependency-with-taglib/package.json
generated
vendored
Normal file
4
test/fixtures/taglib-finder/autotest/deeply-nested-plus-installed/node_modules/dev-dependency-with-taglib/package.json
generated
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"name": "dev-dependency-with-taglib",
|
||||
"version": "0.0.1"
|
||||
}
|
||||
4
test/fixtures/taglib-finder/autotest/deeply-nested-plus-installed/node_modules/dev-dependency-without-taglib/package.json
generated
vendored
Normal file
4
test/fixtures/taglib-finder/autotest/deeply-nested-plus-installed/node_modules/dev-dependency-without-taglib/package.json
generated
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"name": "dev-dependency-without-taglib",
|
||||
"version": "0.0.1"
|
||||
}
|
||||
3
test/fixtures/taglib-finder/autotest/deeply-nested-plus-installed/node_modules/peer-dependency-with-taglib/marko.json
generated
vendored
Normal file
3
test/fixtures/taglib-finder/autotest/deeply-nested-plus-installed/node_modules/peer-dependency-with-taglib/marko.json
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
|
||||
}
|
||||
4
test/fixtures/taglib-finder/autotest/deeply-nested-plus-installed/node_modules/peer-dependency-with-taglib/package.json
generated
vendored
Normal file
4
test/fixtures/taglib-finder/autotest/deeply-nested-plus-installed/node_modules/peer-dependency-with-taglib/package.json
generated
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"name": "peer-dependency-with-taglib",
|
||||
"version": "0.0.1"
|
||||
}
|
||||
4
test/fixtures/taglib-finder/autotest/deeply-nested-plus-installed/node_modules/peer-dependency-without-taglib/package.json
generated
vendored
Normal file
4
test/fixtures/taglib-finder/autotest/deeply-nested-plus-installed/node_modules/peer-dependency-without-taglib/package.json
generated
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"name": "peer-dependency-without-taglib",
|
||||
"version": "0.0.1"
|
||||
}
|
||||
17
test/fixtures/taglib-finder/autotest/deeply-nested-plus-installed/package.json
vendored
Normal file
17
test/fixtures/taglib-finder/autotest/deeply-nested-plus-installed/package.json
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
{
|
||||
"name": "taglib-finder-test",
|
||||
"version": "0.0.0",
|
||||
"dependencies": {
|
||||
"dependency-with-taglib": "0.0.1",
|
||||
"dependency-without-taglib": "0.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"dev-dependency-with-taglib": "0.0.1",
|
||||
"dev-dependency-without-taglib": "0.0.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"peer-dependency-with-taglib": "0.0.1",
|
||||
"peer-dependency-without-taglib": "0.0.1"
|
||||
}
|
||||
|
||||
}
|
||||
1
test/fixtures/taglib-finder/autotest/deeply-nested-plus-installed/test.js
vendored
Normal file
1
test/fixtures/taglib-finder/autotest/deeply-nested-plus-installed/test.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
exports.dir = 'a/b/c';
|
||||
3
test/fixtures/taglib-finder/autotest/deeply-nested/a/b/c/marko.json
vendored
Normal file
3
test/fixtures/taglib-finder/autotest/deeply-nested/a/b/c/marko.json
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
|
||||
}
|
||||
3
test/fixtures/taglib-finder/autotest/deeply-nested/a/b/marko.json
vendored
Normal file
3
test/fixtures/taglib-finder/autotest/deeply-nested/a/b/marko.json
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
|
||||
}
|
||||
3
test/fixtures/taglib-finder/autotest/deeply-nested/a/marko.json
vendored
Normal file
3
test/fixtures/taglib-finder/autotest/deeply-nested/a/marko.json
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
|
||||
}
|
||||
5
test/fixtures/taglib-finder/autotest/deeply-nested/expected.json
vendored
Normal file
5
test/fixtures/taglib-finder/autotest/deeply-nested/expected.json
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
[
|
||||
"/a/b/c/marko.json",
|
||||
"/a/b/marko.json",
|
||||
"/a/marko.json"
|
||||
]
|
||||
4
test/fixtures/taglib-finder/autotest/deeply-nested/package.json
vendored
Normal file
4
test/fixtures/taglib-finder/autotest/deeply-nested/package.json
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"name": "taglib-finder-test",
|
||||
"version": "0.0.0"
|
||||
}
|
||||
1
test/fixtures/taglib-finder/autotest/deeply-nested/test.js
vendored
Normal file
1
test/fixtures/taglib-finder/autotest/deeply-nested/test.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
exports.dir = 'a/b/c';
|
||||
33
test/taglib-finder-test.js
Normal file
33
test/taglib-finder-test.js
Normal file
@ -0,0 +1,33 @@
|
||||
'use strict';
|
||||
var chai = require('chai');
|
||||
chai.config.includeStack = true;
|
||||
require('chai').should();
|
||||
|
||||
var nodePath = require('path');
|
||||
require('../compiler');
|
||||
var autotest = require('./autotest');
|
||||
|
||||
var taglibFinder = require('../compiler/taglib-finder');
|
||||
|
||||
|
||||
describe('taglib-finder' , function() {
|
||||
var autoTestDir = nodePath.join(__dirname, 'fixtures/taglib-finder/autotest');
|
||||
|
||||
autotest.scanDir(autoTestDir, function run(dir) {
|
||||
var test = require(nodePath.join(dir, 'test.js'));
|
||||
var finderDir = nodePath.join(dir, test.dir);
|
||||
var found = taglibFinder.find(finderDir, [])
|
||||
.map((taglib) => {
|
||||
if (taglib.path.startsWith(dir)) {
|
||||
return taglib.path.substring(dir.length).replace(/[\\]/g, '/');
|
||||
} else {
|
||||
return 'BAD:' + taglib.path;
|
||||
}
|
||||
});
|
||||
return found;
|
||||
},
|
||||
{
|
||||
deepEqual: true,
|
||||
compareExtension: '.json'
|
||||
});
|
||||
});
|
||||
@ -19,7 +19,7 @@ describe('taglib-loader' , function() {
|
||||
|
||||
it('should load a taglib with shorthand attributes and tags', function() {
|
||||
var taglibLoader = require('../compiler').taglibLoader;
|
||||
var taglib = taglibLoader.load(nodePath.join(__dirname, 'fixtures/taglib-shorthand/marko-taglib.json'));
|
||||
var taglib = taglibLoader.load(nodePath.join(__dirname, 'fixtures/taglib-shorthand/marko.json'));
|
||||
expect(taglib != null).to.equal(true);
|
||||
|
||||
var shorthandCheckbox = taglib.tags['shorthand-checkbox'];
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user