Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
mlrawlings committed Dec 8, 2016
0 parents commit d00911b
Show file tree
Hide file tree
Showing 13 changed files with 280 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
node_modules
4 changes: 4 additions & 0 deletions components/asset-var/marko-tag.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"transformer":"./transformer.js",
"renderer":"./renderer.js"
}
5 changes: 5 additions & 0 deletions components/asset-var/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"browser": {
"./renderer.js": "./renderer.browser.js"
}
}
10 changes: 10 additions & 0 deletions components/asset-var/renderer.browser.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
module.exports = function(input, out) {
var renderBody = input.renderBody;
var values = input.values;

if (!renderBody) {
return;
}

renderBody.apply(null, [out].concat(values.map(val => require(val))));
}
43 changes: 43 additions & 0 deletions components/asset-var/renderer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
var getLassoRenderContext = require('lasso/taglib/getLassoRenderContext');

module.exports = function(input, out) {
var renderBody = input.renderBody;
var values = input.values;

if (!renderBody) {
return;
}

var lassoRenderContext = getLassoRenderContext(out);
var theLasso = input.lasso || lassoRenderContext.lasso;

if (!theLasso) {
throw new Error('Page lasso not configured for application. Use require("lasso").configureDefault(config) to configure the default page lasso or provide an lasso as input using the "lasso" attribute.');
}

var lassoContext = lassoRenderContext.data.lassoContext;

if (!lassoContext) {
lassoContext = lassoRenderContext.data.lassoContext = theLasso.createLassoContext({});
lassoContext.renderContext = out;
}

var asyncOut = out.beginAsync();

Promise.all(
values.map(val => lassoResource(theLasso, lassoContext, val))
).then(resources => {
renderBody.apply(null, [asyncOut].concat(resources));
asyncOut.end();
});
}

function lassoResource(lasso, context, path) {
return new Promise(function(resolve, reject) {
lasso.lassoResource(path, context, function(err, result) {
if(err) return reject(err);
else resolve(result);
});
});
}

20 changes: 20 additions & 0 deletions components/asset-var/transformer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
module.exports = function(el, context) {
var builder = context.builder;
var identifier = builder.identifier;
var arrayExpression = builder.arrayExpression;
var functionDeclaration = builder.functionDeclaration;
var requireResolve = builder.requireResolve;

var body = el.body;
var attrs = el.attributes;
var out = identifier('out');
var params = [out].concat(attrs.map(attr => identifier(attr.name)));
var renderBody = functionDeclaration('renderBody', params, body);
var values = arrayExpression(attrs.map(attr => requireResolve(attr.value)));

el.removeAllAttributes();
delete el.body;

el.setAttributeValue('values', values);
el.setAttributeValue('renderBody', renderBody);
}
8 changes: 8 additions & 0 deletions components/body/transformer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
module.exports = function(el, context) {
var refresh = context.createNodeForEl('browser-refresh');
var lasso = context.createNodeForEl('lasso-inject', {
name: context.builder.literal('body')
});
el.appendChild(refresh);
el.appendChild(lasso);
}
6 changes: 6 additions & 0 deletions components/head/transformer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module.exports = function(el, context) {
var lasso = context.createNodeForEl('lasso-inject', {
name: context.builder.literal('head')
});
el.appendChild(lasso);
}
21 changes: 21 additions & 0 deletions components/lasso-inject/renderer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
var path = require('path');
var lassoPageTag = require('lasso/taglib/page-tag');
var lassoSlotTag = require('lasso/taglib/slot-tag');
var lassoBodyTag = require('lasso/taglib/body-tag');
var getLassoRenderContext = require('lasso/taglib/getLassoRenderContext');

module.exports = function(input, out) {
var lassoRenderContext = getLassoRenderContext(out);
var lassoPageResultAsyncValue = lassoRenderContext.data.lassoPageResult;
var template = out.global.template;

if (!lassoPageResultAsyncValue) {
lassoPageTag({
dependencies: template.getDependencies(),
filename: template.path,
dirname: path.dirname(template.path)
}, out);
}

lassoSlotTag(input, out);
}
43 changes: 43 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
var path = require('path');
var isProduction = (process.env.NODE_ENV === 'production');

/*
Allow requiring *.marko files
*/
require('marko/node-require').install();
require('marko/compiler/config').meta = true;

/*
Enable res.marko
*/
require('marko/express');

/*
Browser Refresh
*/
require('marko/browser-refresh').enable();
require('lasso/browser-refresh').enable('*.marko *.css *.less *.styl *.scss *.sass *.png *.jpeg *.jpg *.gif *.webp *.svg');

/*
Lasso
*/
require('lasso').configure({
plugins: [
require('lasso-marko') // Auto compile Marko template files
],

// Directory where generated JS and CSS bundles are written
outputDir: path.join(process.cwd(), './static'),

// URL prefix for static assets
urlPrefix: '/static',

// Only bundle up JS and CSS files in production builds
bundlingEnabled: isProduction,

// Only minify JS and CSS files in production builds
minify: isProduction,

// Only fingerprint JS and CSS files in production builds
fingerprintsEnabled: isProduction
});
94 changes: 94 additions & 0 deletions lasso-attribute-transformer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
"use strict";

const VAR_NODE_NAME = 'asset-var';
const resolve = require('lasso-resolve-from');

module.exports = function transform(el, context) {
var parentNode = el.parentNode;
var alreadyWrapped = parentNode.tagName === VAR_NODE_NAME;
var varNode = alreadyWrapped ? parentNode : context.createNodeForEl(VAR_NODE_NAME);

if(tagAttrs[el.tagName]) el.attributes.forEach(attr => {
if(!tagAttrs[el.tagName+':'+attr.name]) return;

var ids = 0;
var idGen = () => ids++;
var walker = context.createWalker({
enter:(node) => {
let nodeHandler = nodeHandlers[node.type];

if(!nodeHandler) return walker.skip();
if(nodeHandler === true) return;

var value = nodeHandler(node, walker, context, attr, varNode, idGen);
if(value) {
el.setAttributeValue(attr.name, value);
}
}
});

walker.walk(attr.value);
});

if(!alreadyWrapped && varNode.attributes.length) el.wrapWith(varNode);
}

const attrTags = {
src:[ 'audio', 'embed', 'iframe', 'img', 'input', 'script', 'source', 'track', 'video' ],
href:[ 'a', 'area', 'link' ],
data:[ 'object' ],
poster:[ 'video' ],
srcset:[ 'img' ], //something else needs to happen here
background:[ 'body' ]
};

const tagAttrs = Object.keys(attrTags).reduce((tagAttrs, attrName) => {
attrTags[attrName].forEach(tagName => {
tagAttrs[tagName] = true;
tagAttrs[tagName+':'+attrName] = true;
})
return tagAttrs;
}, {});

const nodeHandlers = {
ArrayExpression:true,
ObjectExpression:true,
Property:true,
LogicalExpression:true,
ConditionalExpression:(node, walker) => {
node.consequent = walker.walk(node.consequent);
node.alternate = walker.walk(node.alternate);
walker.skip()
},
Literal:(node, walker, context, attr, varNode, id) => {
var builder = context.builder;
var requireResolve = builder.requireResolve;
var literal = builder.literal;
var memberExpression = builder.memberExpression;

if(isFileSystemPath(node.value, context.dirname)) {
let varName = toVarName(attr.name, id());
varNode.setAttributeValue(varName, literal(node.value));
return memberExpression(varName, 'url');
}
}
}

const protocolPattern = /^[a-z]{2,}\:/i;

function isFileSystemPath(path, dirname) {
if(!path) return false;
if(typeof path !== 'string') return false;
if(protocolPattern.test(path)) return false;
return !!tryResolve(path, dirname);
}

function tryResolve(path, dirname) {
try {
return resolve(dirname, path).path;
} catch(error) {}
}

function toVarName(name, id) {
return '__'+name.replace(/-([a-z])/g, s => s[1].toUpperCase()).replace(/[^0-9a-z]/gi, '')+(id || '');
}
6 changes: 6 additions & 0 deletions marko.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"<*>": {
"transformer": "./lasso-attribute-transformer.js"
},
"tags-dir": "./components"
}
19 changes: 19 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"name": "marko-magic",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Michael Rawlings <[email protected]>",
"license": "ISC",
"dependencies": {
"lasso": "^2.8.3",
"lasso-marko": "^2.1.0",
"lasso-resolve-from": "^1.2.0"
},
"peerDependencies": {
"marko":"*"
}
}

0 comments on commit d00911b

Please sign in to comment.