Fixes #288 - Provide API for discovering custom tags and attributes for autocomplete/tooling purposes

This commit is contained in:
Patrick Steele-Idem 2016-05-05 22:39:30 -07:00
parent 0a972d2d10
commit 33a6aaff98
22 changed files with 222 additions and 17 deletions

View File

@ -175,6 +175,12 @@ exports.taglibLookup = taglibLookup;
exports.taglibLoader = require('./taglib-loader');
exports.taglibFinder = require('./taglib-finder');
function buildTaglibLookup(dirname) {
return taglibLookup.buildLookup(dirname);
}
exports.buildTaglibLookup = buildTaglibLookup;
taglibLookup.registerTaglib(require.resolve('../taglibs/core/marko.json'));
taglibLookup.registerTaglib(require.resolve('../taglibs/layout/marko.json'));
taglibLookup.registerTaglib(require.resolve('../taglibs/html/marko.json'));

View File

@ -141,6 +141,53 @@ class TaglibLookup {
this._mergeNestedTags(taglib);
}
forEachTag(callback) {
var tags = this.merged.tags;
if (tags) {
for (var tagName in tags) {
if (tags.hasOwnProperty(tagName)) {
var tag = tags[tagName];
var result = callback(tag);
if (result === false) {
break;
}
}
}
}
}
forEachAttribute(tagName, callback) {
var tags = this.merged.tags;
if (!tags) {
return;
}
function findAttributesForTagName(tagName) {
var tag = tags[tagName];
if (!tag) {
return;
}
var attributes = tag.attributes;
if (!attributes) {
return;
}
for (var attrName in attributes) {
if (attributes.hasOwnProperty(attrName)) {
callback(attributes[attrName], tag);
}
}
if (tag.patternAttributes) {
tag.patternAttributes.forEach(callback);
}
}
findAttributesForTagName(tagName); // Look for an exact match at the tag level
findAttributesForTagName('*'); // Including attributes that apply to all tags
}
getTag(element) {
if (typeof element === 'string') {
element = {
@ -157,7 +204,6 @@ class TaglibLookup {
}
getAttribute(element, attr) {
if (typeof element === 'string') {
element = {
tagName: element

View File

@ -1,6 +1,60 @@
The Compiler API
================
# require('marko/compiler')
## Methods
### buildTaglibLookup(dirname)
Returns a [TaglibLookup](#TaglibLookup) for discovering custom tags available to a template in the given directory.
Example usage:
```javascript
var taglibLookup =
require('marko/compiler').buildTaglibLookup('some/dir');
taglibLookup.forEachTag((tag) => {
console.log(tag.name);
});
taglibLookup.forEachAttribute('div', (attr) => {
console.log(attr.name);
});
```
### compile(src, filename, options, callback)
### compileFile(filename, options, callback)
### createBuilder(options)
### createWalker(options)
### parseRaw(templateSrc, filename)
## Properties
### taglibLookup
Returns a reference to the [taglib-lookup](#taglib-lookup) module.
### taglibLoader
### taglibFinder
<a name="taglib-lookup"></a>
# taglib-lookup
## Methods
### registerTaglib = registerTaglib;
### buildLookup(dirname)
### clearCache();
# AST
## Node

View File

@ -1,6 +1,7 @@
var nodePath = require('path');
exports.check = function(taglibLookup, expect) {
exports.check = function(markoCompiler, expect) {
var taglibLookup = markoCompiler.taglibLookup;
var lookup1 = taglibLookup.buildLookup(nodePath.join(__dirname, 'foo'));
var lookup2 = taglibLookup.buildLookup(nodePath.join(__dirname, 'foo'));
var lookup3 = taglibLookup.buildLookup(nodePath.join(__dirname, 'foo/empty'));

View File

@ -1,4 +1,5 @@
exports.check = function(taglibLookup, expect) {
exports.check = function(markoCompiler, expect) {
var taglibLookup = markoCompiler.taglibLookup;
var lookup = taglibLookup.buildLookup(__dirname);
// console.log('LOOKUP: ', Object.keys(lookup.attributes));
var ifAttr = lookup.getAttribute('div', 'if');

View File

@ -1,4 +1,5 @@
exports.check = function(taglibLookup, expect) {
exports.check = function(markoCompiler, expect) {
var taglibLookup = markoCompiler.taglibLookup;
var lookup = taglibLookup.buildLookup(__dirname);
var ifTag = lookup.getTag('if');
expect(ifTag != null).to.equal(true);

View File

@ -1,4 +1,5 @@
exports.check = function(taglibLookup, expect) {
exports.check = function(markoCompiler, expect) {
var taglibLookup = markoCompiler.taglibLookup;
var lookup = taglibLookup.buildLookup(__dirname);
var tag = lookup.getTag('test-hello');
// console.log(Object.keys(lookup.tags));

View File

@ -1,6 +1,7 @@
var nodePath = require('path');
exports.check = function(taglibLookup, expect) {
exports.check = function(markoCompiler, expect) {
var taglibLookup = markoCompiler.taglibLookup;
var lookup = taglibLookup.buildLookup(nodePath.join(__dirname, 'taglib-duplicate'));
// The "duplicate-bar" tag was declared in the lower

View File

@ -1,4 +1,5 @@
exports.check = function(taglibLookup, expect) {
exports.check = function(markoCompiler, expect) {
var taglibLookup = markoCompiler.taglibLookup;
var lookup = taglibLookup.buildLookup(__dirname);
// console.log(Object.keys(lookup.attributes));
var attr = lookup.getAttribute('test-dynamic-attribute', 'DYNAMIC');

View File

@ -0,0 +1,10 @@
[
"name",
"age",
"foo-on-*",
"if",
"else-if",
"else",
"for",
"while"
]

View File

@ -0,0 +1,12 @@
{
"<foo>": {
"@name": "string",
"@age": "integer",
"@foo-on-*": {
"pattern": true
}
},
"<bar>": {
"@baz": "string"
}
}

View File

@ -0,0 +1,12 @@
exports.check = function(markoCompiler, expect, helpers) {
var taglibLookup = markoCompiler.taglibLookup;
var lookup = taglibLookup.buildLookup(__dirname);
var attrNames = [];
lookup.forEachAttribute('foo', (attr) => {
attrNames.push(attr.name);
});
helpers.compare(attrNames, '.json');
};

View File

@ -0,0 +1,33 @@
[
"*",
"foo",
"bar",
"assign",
"else",
"else-if",
"for",
"if",
"include",
"include-text",
"invoke",
"macro",
"macro-body",
"marko-preserve-whitespace",
"pre",
"script",
"style",
"textarea",
"unless",
"var",
"while",
"layout-use",
"layout-put",
"layout-placeholder",
"html-comment",
"async-fragment",
"async-fragments",
"async-fragment-placeholder",
"async-fragment-timeout",
"async-fragment-error",
"cached-fragment"
]

View File

@ -0,0 +1,11 @@
{
"<*>": {
"@global-attribute": "boolean"
},
"<foo>": {
"@name": "string"
},
"<bar>": {
"@name": "string"
}
}

View File

@ -0,0 +1,11 @@
exports.check = function(markoCompiler, expect, helpers) {
var lookup = markoCompiler.buildTaglibLookup(__dirname);
var tagNames = [];
lookup.forEachTag((tag) => {
tagNames.push(tag.name);
});
helpers.compare(tagNames, '.json');
};

View File

@ -1,4 +1,5 @@
exports.check = function(taglibLookup, expect) {
exports.check = function(markoCompiler, expect) {
var taglibLookup = markoCompiler.taglibLookup;
var lookup = taglibLookup.buildLookup(__dirname);
// console.log('LOOKUP: ', Object.keys(lookup.attributes));
var attrDef = lookup.getAttribute('test-dynamic-attributes', 'global-attribute');

View File

@ -1,4 +1,5 @@
exports.check = function(taglibLookup, expect) {
exports.check = function(markoCompiler, expect) {
var taglibLookup = markoCompiler.taglibLookup;
var lookup = taglibLookup.buildLookup(__dirname);
// console.log(Object.keys(lookup.attributes));
var attr = lookup.getAttribute('nested-foo', 'attr1');

View File

@ -1,4 +1,5 @@
exports.check = function(taglibLookup, expect) {
exports.check = function(markoCompiler, expect) {
var taglibLookup = markoCompiler.taglibLookup;
var lookup = taglibLookup.buildLookup(__dirname);
var tag = lookup.getTag('nested-foo');

View File

@ -1,7 +1,6 @@
exports.check = function(taglibLookup, expect) {
exports.check = function(markoCompiler, expect) {
var taglibLookup = markoCompiler.taglibLookup;
var transformers = [];
var lookup = taglibLookup.buildLookup(__dirname);
lookup.forEachTagTransformer('div', function(transformer) {

View File

@ -1,4 +1,5 @@
exports.check = function(taglibLookup, expect) {
exports.check = function(markoCompiler, expect) {
var taglibLookup = markoCompiler.taglibLookup;
var transformers = [];
var lookup = taglibLookup.buildLookup(__dirname);

View File

@ -1,4 +1,5 @@
exports.check = function(taglibLookup, expect) {
exports.check = function(markoCompiler, expect) {
var taglibLookup = markoCompiler.taglibLookup;
var transformers;
var lookup;
// lookup = taglibLookup.buildLookup(nodePath.join(__dirname, 'fixtures/nested'));

View File

@ -8,14 +8,14 @@ var expect = require('chai').expect;
var nodePath = require('path');
require('../compiler');
var autotest = require('./autotest');
var taglibLookup = require('../compiler').taglibLookup;
var markoCompiler = require('../compiler');
describe('taglib-lookup' , function() {
var autoTestDir = nodePath.join(__dirname, 'autotests/taglib-lookup');
autotest.scanDir(autoTestDir, function run(dir, helpers, done) {
var test = require(nodePath.join(dir, 'test.js'));
test.check(taglibLookup, expect);
test.check(markoCompiler, expect, helpers);
done();
});
});