Move CSS generation code into src/css.

This commit is contained in:
ccd0 2016-04-20 05:54:14 -07:00
parent d782a29138
commit e363f8a5a1
7 changed files with 85 additions and 66 deletions

4
.jshintrc Normal file
View File

@ -0,0 +1,4 @@
{
"undef": true,
"unused": true
}

View File

@ -62,7 +62,6 @@ imports_src/globals/globals.js := \
imports_src/config/Config.coffee := \
src/Archive/archives.json
imports_src/css/CSS.js := \
tools/style.js \
node_modules/font-awesome/package.json
imports_src/Monitoring/Favicon.coffee := \
src/meta/icon128.png

View File

@ -1,7 +1,16 @@
CSS = {
<%
var inc = require['style'];
var faCSS = read('/node_modules/font-awesome/css/font-awesome.css');
var faWebFont = readBase64('/node_modules/font-awesome/fonts/fontawesome-webfont.woff');
var mainCSS = ['font-awesome', 'style', 'yotsuba', 'yotsuba-b', 'futaba', 'burichan', 'tomorrow', 'photon'].map(x => read(`${x}.css`)).join('');
var iconNames = files.filter(f => /^linkify\.[^.]+\.png$/.test(f));
var icons = iconNames.map(readBase64);
%>CSS = {
boards:
<%= multiline(require['style']()()) %>,
<%= multiline(
inc.fa(faCSS, faWebFont) + mainCSS + inc.icons(iconNames, icons) + read('supports.css')
) %>,
report:
<%= multiline(read('report.css')) %>,

40
src/css/style.inc Normal file
View File

@ -0,0 +1,40 @@
/* jshint esnext: true */
// == Reprocess Font Awesome CSS == //
var fa = (css, font) => (
// Font Awesome CSS attribution and license
css.match(/\/\*\![^]*?\*\//)[0] + '\n' +
// Font Awesome web font
`@font-face {
font-family: FontAwesome;
src: url('data:application/font-woff;base64,${font}') format('woff');
font-weight: 400;
font-style: normal;
}
` +
// fa-[icon name] classes
css
.match(/(\.fa-[^{]*{\s*content:[^}]*}\s*)+/)[0]
.replace(/([,{;])\s+/g, '$1')
.replace(/,/g, ', ')
);
// == Create CSS for Link Title Favicons == //
var icons = (names, data) => (
'/* Link Title Favicons */\n' +
names.map((file, i) =>
`.linkify.${file.split('.')[1]} {
background: transparent url('data:image/png;base64,${data[i]}') center left no-repeat!important;
padding-left: 18px;
}
`
).join('')
);
return {fa, icons};

View File

@ -2,6 +2,5 @@
"esnext": true,
"undef": true,
"unused": true,
"node": true,
"-W083": true
"node": true
}

View File

@ -1,48 +0,0 @@
var fs = require('fs');
var read = filename => fs.readFileSync(filename, 'utf8').replace(/\r\n/g, '\n');
var readBase64 = filename => fs.readFileSync(filename).toString('base64');
module.exports = () => (
// Font Awesome CSS attribution and license
read('node_modules/font-awesome/css/font-awesome.css').match(/\/\*\![^]*?\*\//)[0] + '\n' +
// Font Awesome web font
`@font-face {
font-family: FontAwesome;
src: url('data:application/font-woff;base64,${readBase64('node_modules/font-awesome/fonts/fontawesome-webfont.woff')}') format('woff');
font-weight: 400;
font-style: normal;
}
` +
// fa-[icon name] classes
read('node_modules/font-awesome/css/font-awesome.css')
.match(/(\.fa-[^{]*{\s*content:[^}]*}\s*)+/)[0]
.replace(/([,{;])\s+/g, '$1')
.replace(/,/g, ', ') +
[
'font-awesome',
'style',
'yotsuba', 'yotsuba-b', 'futaba', 'burichan', 'tomorrow', 'photon'
].map(
name => read(`src/css/${name}.css`)
).join('') +
'/* Link Title Favicons */\n' +
fs.readdirSync('src/css').filter(file =>
/^linkify\.[^.]+\.png$/.test(file)
).map(file =>
`.linkify.${file.split('.')[1]} {
background: transparent url('data:image/png;base64,${readBase64(`src/css/${file}`)}') center left no-repeat!important;
padding-left: 18px;
}
`
).join('') +
// XXX Moved to end of stylesheet to avoid breaking whole stylesheet in Maxthon.
read('src/css/supports.css')
);

View File

@ -1,3 +1,4 @@
/* jshint evil: true */
var fs = require('fs');
var path = require('path');
var _template = require('lodash.template');
@ -9,11 +10,6 @@ var _templateSettings = {interpolate: /<%=([\s\S]+?)%>/g};
// Functions used in templates.
var tools = {};
tools.require = {};
for (var m of ['style']) {
tools.require[m] = () => require(`./${m}`);
}
var read = tools.read = filename => fs.readFileSync(filename, 'utf8').replace(/\r\n/g, '\n');
var readJSON = tools.readJSON = filename => JSON.parse(read(filename));
tools.readBase64 = filename => fs.readFileSync(filename).toString('base64');
@ -179,25 +175,43 @@ tools.assert = function(statement) {
return `throw new Error 'Assertion failed: ' + ${constExpression(statement)} unless ${statement}`;
};
function resolvePath(filename, templateName) {
if (filename[0] === '/') {
return path.join(process.cwd(), filename);
}
function includesDir(templateName) {
var dir = path.dirname(templateName);
var subdir = path.basename(templateName).replace(/\.[^.]+$/, '');
if (fs.readdirSync(dir).indexOf(subdir) >= 0) {
return path.join(dir, subdir, filename);
return path.join(dir, subdir);
} else {
return path.join(dir, filename);
return dir;
}
}
function resolvePath(includeName, templateName) {
var dir;
if (includeName[0] === '/') {
dir = process.cwd();
} else {
dir = includesDir(templateName);
}
return path.join(dir, includeName);
}
function wrapTool(tool, templateName) {
return function(filename) {
return tool(resolvePath(filename, templateName));
return function(includeName) {
return tool(resolvePath(includeName, templateName));
};
}
function loadModules(templateName) {
var dir = includesDir(templateName);
var moduleNames = fs.readdirSync(dir).filter(f => /\.inc$/.test(f));
var modules = {};
for (var name of moduleNames) {
var code = read(path.join(dir, name));
modules[name.replace(/\.inc$/, '')] = new Function(code)();
}
return modules;
}
// Import variables from package.json.
var pkg = readJSON('package.json');
@ -214,6 +228,8 @@ function interpolate(text, data, filename) {
context[key] = data[key];
}
}
context.files = fs.readdirSync(includesDir(filename));
context.require = loadModules(filename);
return _template(text, _templateSettings)(context);
}