allow finding index.marko, rework the tag scanning to hit the filesystem less

This commit is contained in:
Michael Rawlings 2016-10-26 18:15:46 -07:00
parent af990a04b3
commit 1d3d14d01e
6 changed files with 98 additions and 58 deletions

View File

@ -23,38 +23,90 @@ var loader = require('./loader');
var fsReadOptions = { encoding: 'utf8' }; var fsReadOptions = { encoding: 'utf8' };
var extend = require('raptor-util/extend'); 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() { function createDefaultTagDef() {
return { return {
attributes: { attributes: {
'*': { '*': {
type: 'string', type: 'string',
targetProperty: null, targetProperty: null,
preserveName: false preserveName: false
}
} }
}; }
};
} }
function scanRequireExtensions(baseFilename) { function getFileMap(dirname) {
// .js is the most common case so check that first var fileMap = {};
var path = baseFilename + '.js'; var files = fs.readdirSync(dirname);
if (fs.existsSync(path)) { files.forEach(file => {
return path; 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) { var fileMap = getFileMap(tagDirname);
if (extension === '.js') {
// We already checked .js above for(var i = 0; i < searchFiles.length; i++) {
continue; var name = searchFiles[i].name;
} var type = searchFiles[i].type;
path = baseFilename + extension; var path = getPath(name, fileMap);
if (fs.existsSync(path)) {
return path; // short circuit loop 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} tagsConfigPath path to tag definition file
* @param {String} tagsConfigDirname path to directory of tags config file (should be path.dirname(tagsConfigPath)) * @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 tagName = prefix + childFilename;
var tagDirname = nodePath.join(dir, 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 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 tagDef = null;
var hasTagFile = false; var hasTagJson = false;
if (fs.existsSync(tagFilePath)) { if (fs.existsSync(tagJsonPath)) {
hasTagFile = true; hasTagJson = true;
// marko-tag.json exists in the directory, use that as the tag definition // marko-tag.json exists in the directory, use that as the tag definition
try { try {
tagDef = JSON.parse(stripJsonComments(fs.readFileSync(tagFilePath, fsReadOptions))); tagDef = JSON.parse(stripJsonComments(fs.readFileSync(tagJsonPath, fsReadOptions)));
} catch(e) { } 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 { } else {
tagFilePath = null; tagJsonPath = null;
tagDef = createDefaultTagDef(); tagDef = createDefaultTagDef();
} }
if (!tagDef.renderer && !tagDef.template && !tagDef['code-generator'] && !tagDef['node-factory'] && !tagDef.transformer) { if (!hasFile(tagDef)) {
if (rendererFile) { var fileWasSet = findAndSetFile(tagDef, tagDirname);
tagDef.renderer = rendererFile; if(!fileWasSet) {
} else if (indexFile) { if (hasTagJson) {
tagDef.renderer = indexFile; throw new Error('Invalid tag file: ' + tagJsonPath + '. Neither a renderer or a template was found for tag. ' + JSON.stringify(tagDef, null, 2));
} 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));
} else { } else {
// Skip this directory... there doesn't appear to be anything in it // Skip this directory... there doesn't appear to be anything in it
continue; 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 templateCode = fs.readFileSync(tagDef.renderer || tagDef.template, fsReadOptions);
let extractedTagDef = tagDefFromCode.extractTagDef(templateCode); let extractedTagDef = tagDefFromCode.extractTagDef(templateCode);
if (extractedTagDef) { if (extractedTagDef) {
@ -148,14 +179,14 @@ module.exports = function scanTagsDir(tagsConfigPath, tagsConfigDirname, dir, ta
let tagDependencyChain; let tagDependencyChain;
if (tagFilePath) { if (tagJsonPath) {
tagDependencyChain = dependencyChain.append(tagFilePath); tagDependencyChain = dependencyChain.append(tagJsonPath);
} else { } else {
tagDependencyChain = dependencyChain.append(tagDirname); 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; tag.name = tag.name || tagName;
taglib.addTag(tag); taglib.addTag(tag);
} }
}; };

View File

@ -0,0 +1 @@
Hello Frank!

View File

@ -0,0 +1,3 @@
{
"tags-dir": "./tags"
}

View File

@ -0,0 +1,3 @@
---
Hello ${data.name}!
---

View File

@ -0,0 +1 @@
<test-tag name="Frank"/>

View File

@ -0,0 +1 @@
exports.templateData = {};