diff --git a/compiler/taglib-loader/scanTagsDir.js b/compiler/taglib-loader/scanTagsDir.js index 3982ec2d5..9de986217 100644 --- a/compiler/taglib-loader/scanTagsDir.js +++ b/compiler/taglib-loader/scanTagsDir.js @@ -23,38 +23,90 @@ var loader = require('./loader'); var fsReadOptions = { encoding: 'utf8' }; var extend = require('raptor-util/extend'); +var tagFileTypes = [ + 'template', + 'renderer', + 'transformer', + 'code-generator', + 'node-factory', +]; + +var searchFiles = [ + { name:'renderer', type:'renderer' }, + { name:'index.marko', type:'template' }, + { name:'index', type:'renderer' }, + { name:'template.marko', type:'template' }, + { name:'template.html', type:'template' }, + { name:'code-generator', type:'code-generator' }, + { name:'node-factory', type:'node-factory' }, + { name:'transformer', type:'transformer' }, +]; + function createDefaultTagDef() { return { - attributes: { - '*': { - type: 'string', - targetProperty: null, - preserveName: false - } + attributes: { + '*': { + type: 'string', + targetProperty: null, + preserveName: false } - }; + } + }; } -function scanRequireExtensions(baseFilename) { - // .js is the most common case so check that first - var path = baseFilename + '.js'; +function getFileMap(dirname) { + var fileMap = {}; + var files = fs.readdirSync(dirname); - if (fs.existsSync(path)) { - return path; + files.forEach(file => { + var extName = nodePath.extname(file); + var baseName = file.slice(0, -1*extName.length); + var fullPath = nodePath.join(dirname, file); + fileMap[baseName] = fileMap[baseName] || {}; + fileMap[baseName][extName] = fullPath; + fileMap[file] = fileMap[file] || {}; + fileMap[file].__path = fullPath; + }); + + return fileMap; +} + +function getPath(filename, fileMap) { + var file = fileMap[filename]; + + if(!file) return; + if(file.__path) return file.__path; + if(file.js) return file['.js']; + + return file[Object.keys(file)[0]]; +} + +function findAndSetFile(tagDef, tagDirname) { + if(!fs.statSync(tagDirname).isDirectory()) { + return; } - for (var extension in require.extensions) { - if (extension === '.js') { - // We already checked .js above - continue; - } - path = baseFilename + extension; - if (fs.existsSync(path)) { - return path; // short circuit loop + var fileMap = getFileMap(tagDirname); + + for(var i = 0; i < searchFiles.length; i++) { + var name = searchFiles[i].name; + var type = searchFiles[i].type; + var path = getPath(name, fileMap); + + if(path) { + tagDef[type] = path; + return true; } } } +function hasFile(tagDef) { + for(var i = 0; i < tagFileTypes.length; i++) { + if(tagDef[tagFileTypes[i]]) return true; + } + return false; +} + /** * @param {String} tagsConfigPath path to tag definition file * @param {String} tagsConfigDirname path to directory of tags config file (should be path.dirname(tagsConfigPath)) @@ -87,50 +139,29 @@ module.exports = function scanTagsDir(tagsConfigPath, tagsConfigDirname, dir, ta var tagName = prefix + childFilename; var tagDirname = nodePath.join(dir, childFilename); - var tagFilePath = nodePath.join(tagDirname, 'marko-tag.json'); + var tagJsonPath = nodePath.join(tagDirname, 'marko-tag.json'); var tag = null; - - var rendererFile = scanRequireExtensions(nodePath.join(tagDirname, 'renderer')); - var indexFile = scanRequireExtensions(nodePath.join(tagDirname, 'index')); - var templateFile = nodePath.join(tagDirname, 'template.marko'); - var templateFileAlt = nodePath.join(tagDirname, 'template.html'); - var templateFileAlt2 = nodePath.join(tagDirname, 'template.marko.html'); - var codeGeneratorFile = scanRequireExtensions(nodePath.join(tagDirname, 'code-generator')); - var nodeFactoryFile = scanRequireExtensions(nodePath.join(tagDirname, 'node-factory')); var tagDef = null; - var hasTagFile = false; - if (fs.existsSync(tagFilePath)) { - hasTagFile = true; + var hasTagJson = false; + if (fs.existsSync(tagJsonPath)) { + hasTagJson = true; // marko-tag.json exists in the directory, use that as the tag definition try { - tagDef = JSON.parse(stripJsonComments(fs.readFileSync(tagFilePath, fsReadOptions))); + tagDef = JSON.parse(stripJsonComments(fs.readFileSync(tagJsonPath, fsReadOptions))); } catch(e) { - throw new Error('Unable to parse JSON file at path "' + tagFilePath + '". Error: ' + e); + throw new Error('Unable to parse JSON file at path "' + tagJsonPath + '". Error: ' + e); } } else { - tagFilePath = null; + tagJsonPath = null; tagDef = createDefaultTagDef(); } - if (!tagDef.renderer && !tagDef.template && !tagDef['code-generator'] && !tagDef['node-factory'] && !tagDef.transformer) { - if (rendererFile) { - tagDef.renderer = rendererFile; - } else if (indexFile) { - tagDef.renderer = indexFile; - } else if (fs.existsSync(templateFile)) { - tagDef.template = templateFile; - } else if (fs.existsSync(templateFileAlt)) { - tagDef.template = templateFileAlt; - } else if (fs.existsSync(templateFileAlt2)) { - tagDef.template = templateFileAlt2; - } else if (fs.existsSync(codeGeneratorFile)) { - tagDef['code-generator'] = codeGeneratorFile; - } else if (fs.existsSync(nodeFactoryFile)) { - tagDef['node-factory'] = nodeFactoryFile; - } else { - if (hasTagFile) { - throw new Error('Invalid tag file: ' + tagFilePath + '. Neither a renderer or a template was found for tag. ' + JSON.stringify(tagDef, null, 2)); + if (!hasFile(tagDef)) { + var fileWasSet = findAndSetFile(tagDef, tagDirname); + if(!fileWasSet) { + if (hasTagJson) { + throw new Error('Invalid tag file: ' + tagJsonPath + '. Neither a renderer or a template was found for tag. ' + JSON.stringify(tagDef, null, 2)); } else { // Skip this directory... there doesn't appear to be anything in it continue; @@ -138,7 +169,7 @@ module.exports = function scanTagsDir(tagsConfigPath, tagsConfigDirname, dir, ta } } - if (!hasTagFile && (tagDef.renderer || tagDef.template)) { + if (!hasTagJson && (tagDef.renderer || tagDef.template)) { let templateCode = fs.readFileSync(tagDef.renderer || tagDef.template, fsReadOptions); let extractedTagDef = tagDefFromCode.extractTagDef(templateCode); if (extractedTagDef) { @@ -148,14 +179,14 @@ module.exports = function scanTagsDir(tagsConfigPath, tagsConfigDirname, dir, ta let tagDependencyChain; - if (tagFilePath) { - tagDependencyChain = dependencyChain.append(tagFilePath); + if (tagJsonPath) { + tagDependencyChain = dependencyChain.append(tagJsonPath); } else { tagDependencyChain = dependencyChain.append(tagDirname); } - tag = loader.tagLoader.loadTag(tagDef, tagFilePath || tagDirname, tagDependencyChain); + tag = loader.tagLoader.loadTag(tagDef, tagJsonPath || tagDirname, tagDependencyChain); tag.name = tag.name || tagName; taglib.addTag(tag); } -}; +}; \ No newline at end of file diff --git a/test/autotests/render/custom-tag-template-index/expected.html b/test/autotests/render/custom-tag-template-index/expected.html new file mode 100644 index 000000000..fa172694a --- /dev/null +++ b/test/autotests/render/custom-tag-template-index/expected.html @@ -0,0 +1 @@ +Hello Frank! \ No newline at end of file diff --git a/test/autotests/render/custom-tag-template-index/marko.json b/test/autotests/render/custom-tag-template-index/marko.json new file mode 100644 index 000000000..e85a78200 --- /dev/null +++ b/test/autotests/render/custom-tag-template-index/marko.json @@ -0,0 +1,3 @@ +{ + "tags-dir": "./tags" +} \ No newline at end of file diff --git a/test/autotests/render/custom-tag-template-index/tags/test-tag/index.marko b/test/autotests/render/custom-tag-template-index/tags/test-tag/index.marko new file mode 100644 index 000000000..4a37c01d7 --- /dev/null +++ b/test/autotests/render/custom-tag-template-index/tags/test-tag/index.marko @@ -0,0 +1,3 @@ +--- +Hello ${data.name}! +--- \ No newline at end of file diff --git a/test/autotests/render/custom-tag-template-index/template.marko b/test/autotests/render/custom-tag-template-index/template.marko new file mode 100644 index 000000000..1c56b02aa --- /dev/null +++ b/test/autotests/render/custom-tag-template-index/template.marko @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/test/autotests/render/custom-tag-template-index/test.js b/test/autotests/render/custom-tag-template-index/test.js new file mode 100644 index 000000000..c4013b344 --- /dev/null +++ b/test/autotests/render/custom-tag-template-index/test.js @@ -0,0 +1 @@ +exports.templateData = {};