Alternate way of handling the concatenation.

This commit is contained in:
ccd0 2016-04-13 06:54:10 -07:00
parent 2ab00be0b5
commit 5ec7a559be
15 changed files with 163 additions and 164 deletions

View File

@ -20,19 +20,17 @@ template := node tools/template.js
template_deps := package.json tools/template.js node_modules/lodash/package.json
cat := node tools/cat.js
cat_deps := tools/cat.js
jshint_deps := .jshintrc node_modules/jshint/package.json
parts := top API classes General Filtering Quotelinks Posting Images Linkification Menu Monitoring Archive Miscellaneous bottom
parts := Config API classes General Filtering Quotelinks Posting Images Linkification Menu Monitoring Archive Miscellaneous bottom
js_parts := $(foreach p,$(subst API,API_crx API_userscript,$(parts)),tmp/parts/$(p).js)
intermediate := LICENSE src/meta/fbegin.js tmp/declaration.js tmp/globals.js $(foreach p,$(parts),tmp/$(p).js) src/meta/fend.js
define sorted_dir
sources_$1 := $$(sort $$(wildcard src/$1/*.coffee))
endef
sources_top := \
src/General/Config.coffee \
src/General/Globals.coffee
sources_Config := \
src/General/Config.coffee
sources_API := \
src/General/$$.coffee \
@ -46,7 +44,7 @@ sources_classes := \
sources_General := \
$(foreach n, \
Polyfill Header Index Build Get UI BuildTest \
Polyfill Header Index Build Get UI Build.Test \
,src/General/$(n).coffee)
$(foreach d, \
@ -72,10 +70,9 @@ sources_bottom := \
src/General/Settings.coffee \
src/General/Main.coffee
imports_top := \
imports_Config := \
src/Archive/archives.json \
src/css/custom.css \
version.json
src/css/custom.css
imports_Monitoring := \
src/meta/icon128.png
imports_Miscellaneous := \
@ -106,15 +103,13 @@ testbds := $(foreach f,$(filter-out %.crx %.zip,$(bds)),test$(f)) $(foreach t,cr
testcrx := $(foreach f,$(filter %.crx %.zip,$(bds)),test$(f))
jshint := $(foreach f,script-crx eventPage script-userscript,.events/jshint.$(f))
jshint := $(foreach f,globals $(subst API,API_crx API_userscript,$(parts)),.events/jshint.$(f))
jshint_parts := $(foreach p,$(subst API,API_crx API_userscript,$(parts)),.events/jshint_p.$(p))
default : jshint_parts install
default : jshint install
all : jshint bds install
.events tmp tmp/parts testbuilds builds :
.events tmp testbuilds builds :
$(MKDIR)
.events/npm : npm-shrinkwrap.json | .events
@ -133,32 +128,34 @@ tmp/font-awesome.css : src/css/font-awesome.css $(imports_font_awesome) $(templa
tmp/style.css : src/css/style.css $(imports_style) $(template_deps) | tmp
$(template) $< $@
tmp/declaration.js : $(wildcard src/*/*.coffee) tools/declare.js | tmp
node tools/declare.js
tmp/globals.js : src/General/globals.js version.json $(template_deps) | tmp
$(template) $< $@
define rules_part
tmp/parts/$1.jst : $$(sources_$1) $(cat_deps) | tmp/parts
tmp/$1.jst : $$(sources_$1) $(cat_deps) | tmp
$(cat) $$(sources_$1) $$@
tmp/parts/$1.coffee : tmp/parts/$1.jst $$(filter-out %.coffee,$$(wildcard src/$1/*.* src/$1/*/*.* src/$1/*/*/*.*)) $$(imports_$1) .tests_enabled $(template_deps)
tmp/$1.coffee : tmp/$1.jst $$(filter-out %.coffee,$$(wildcard src/$1/*.* src/$1/*/*.* src/$1/*/*/*.*)) $$(imports_$1) .tests_enabled $(template_deps)
$(template) $$< $$@
tmp/parts/$1.js : tmp/parts/$1.coffee $(coffee_deps)
tmp/$1.js : tmp/$1.coffee $(coffee_deps) tools/globalize.js
$(coffee) $$<
node tools/globalize.js $$@ $$(sources_$1)
endef
$(foreach i,$(parts),$(eval $(call rules_part,$(i))))
tmp/parts/API_%.coffee : tmp/parts/API.jst $(template_deps)
tmp/API_%.coffee : tmp/API.jst $(template_deps)
$(template) $< $@ type=$*
tmp/parts/API_%.js : tmp/parts/API_%.coffee $(coffee_deps)
tmp/API_%.js : tmp/API_%.coffee $(coffee_deps)
$(coffee) $<
tmp/script-crx.js : $(filter-out tmp/parts/API_userscript.js,$(js_parts)) tools/cat-coffee.js
node tools/cat-coffee.js $(filter-out tmp/parts/API_userscript.js,$(js_parts)) $@
tmp/script-userscript.js : $(filter-out tmp/parts/API_crx.js,$(js_parts)) tools/cat-coffee.js
node tools/cat-coffee.js $(filter-out tmp/parts/API_crx.js,$(js_parts)) $@
node tools/globalize.js $@ $(sources_API)
tmp/eventPage.js : src/General/eventPage.coffee $(coffee_deps) | tmp
$(coffee) -o tmp src/General/eventPage.coffee
@ -168,8 +165,8 @@ define rules_channel
testbuilds/crx$1 :
$$(MKDIR)
testbuilds/crx$1/script.js : src/meta/botproc.js LICENSE src/meta/usestrict.js tmp/script-crx.js $(cat_deps) | testbuilds/crx$1
$(cat) src/meta/botproc.js LICENSE src/meta/usestrict.js tmp/script-crx.js $$@
testbuilds/crx$1/script.js : src/meta/botproc.js $(subst API,API_crx,$(intermediate)) $(cat_deps) | testbuilds/crx$1
$(cat) src/meta/botproc.js $(subst API,API_crx,$(intermediate)) $$@
testbuilds/crx$1/eventPage.js : tmp/eventPage.js | testbuilds/crx$1
$$(CP)
@ -194,8 +191,8 @@ testbuilds/$(name)$1.crx : testbuilds/$(name)$1.crx.zip package.json tools/sign.
testbuilds/$(name)$1.meta.js : src/meta/metadata.js src/meta/icon48.png version.json $(template_deps) | testbuilds
$(template) $$< $$@ type=userscript channel=$1
testbuilds/$(name)$1.user.js : src/meta/botproc.js testbuilds/$(name)$1.meta.js LICENSE src/meta/usestrict.js tmp/script-userscript.js $(cat_deps)
$(cat) src/meta/botproc.js testbuilds/$(name)$1.meta.js LICENSE src/meta/usestrict.js tmp/script-userscript.js $$@
testbuilds/$(name)$1.user.js : src/meta/botproc.js testbuilds/$(name)$1.meta.js $(subst API,API_userscript,$(intermediate)) $(cat_deps)
$(cat) src/meta/botproc.js testbuilds/$(name)$1.meta.js $(subst API,API_userscript,$(intermediate)) $$@
endef
@ -212,17 +209,10 @@ builds/% : testbuilds/% $(jshint) | builds
test.html : README.md template.jst tools/markdown.js node_modules/marked/package.json node_modules/lodash/package.json
node tools/markdown.js
tmp/parts/.jshintrc : src/meta/jshint.json $(template_deps) | tmp/parts
$(template) $< $@ stage=parts
tmp/.jshintrc : src/meta/jshint.json tmp/declaration.js tmp/globals.js $(template_deps) | tmp
$(template) $< $@
.jshintrc : src/meta/jshint.json $(template_deps)
$(template) $< $@ stage=full
.events/jshint.% : tmp/%.js .jshintrc node_modules/jshint/package.json | .events
$(BIN)jshint $<
echo -> $@
.events/jshint_p.% : tmp/parts/%.js tmp/parts/.jshintrc node_modules/jshint/package.json | .events
.events/jshint.% : tmp/%.js tmp/.jshintrc node_modules/jshint/package.json | .events
$(BIN)jshint $<
echo -> $@
@ -235,11 +225,11 @@ install.json :
.SECONDARY :
.PHONY: default all clean cleanall testbds bds jshint jshint_parts install
.PHONY: default all clean cleanall testbds bds jshint install
clean :
$(RMDIR) tmp testbuilds .events
$(RM) .jshintrc .tests_enabled
$(RM) .tests_enabled
cleanall : clean
$(RMDIR) builds
@ -252,6 +242,4 @@ bds : $(bds)
jshint : $(jshint)
jshint_parts : $(jshint_parts)
install : .events/install

View File

@ -40,15 +40,6 @@
"GM_openInTab",
"GM_xmlhttpRequest"
],
"globals": [
"$$",
"c",
"Conf",
"d",
"doc",
"E",
"g"
],
"min": {
"chrome": "33",
"firefox": "26",

View File

@ -593,6 +593,3 @@ $.clear = (cb) ->
$.delete $.listValues().map (key) -> key.replace g.NAMESPACE, ''
cb?()
<% } %>
$$ = (selector, root=d.body) ->
[root.querySelectorAll(selector)...]

View File

@ -1,5 +1,5 @@
<% if (readJSON('.tests_enabled')) { %>
BuildTest =
Build.Test =
init: ->
return if !Conf['Menu'] or g.VIEW not in ['index', 'thread']
@ -27,11 +27,11 @@ BuildTest =
x2 = x.childNodes[i]
y2 = y.childNodes[i]
return [x2, y2] unless x2 and y2
return BuildTest.firstDiff(x2, y2) unless x2.isEqualNode y2
return Build.Test.firstDiff(x2, y2) unless x2.isEqualNode y2
i++
testOne: (post) ->
BuildTest.postsRemaining++
Build.Test.postsRemaining++
$.cache "//a.4cdn.org/#{post.board.ID}/thread/#{post.thread.ID}.json", ->
{posts} = @response
Build.spoilerRange[post.board.ID] = posts[0].custom_spoiler
@ -41,7 +41,7 @@ BuildTest =
obj = Build.parseJSON postData, post.board.ID
root = Build.post obj
t2 = new Date().getTime()
BuildTest.time += t2 - t1
Build.Test.time += t2 - t1
post2 = new Post root, post.thread, post.board
fail = false
@ -50,7 +50,7 @@ BuildTest =
unless x.isEqualNode y
fail = true
c.log "#{post.fullID} differs"
[x2, y2] = BuildTest.firstDiff x, y
[x2, y2] = Build.Test.firstDiff x, y
c.log x2
c.log y2
c.log x.outerHTML
@ -66,11 +66,11 @@ BuildTest =
c.log val2
if fail
BuildTest.postsFailed++
Build.Test.postsFailed++
else
c.log "#{post.fullID} correct"
BuildTest.postsRemaining--
BuildTest.report() if BuildTest.postsRemaining is 0
Build.Test.postsRemaining--
Build.Test.report() if Build.Test.postsRemaining is 0
post2.isFetchedQuote = true
Main.callbackNodes Post, [post2]
@ -78,7 +78,7 @@ BuildTest =
g.posts.forEach (post) ->
unless post.isClone or post.isFetchedQuote
unless (abbr = $ '.abbr', post.nodes.comment) and /Comment too long\./.test(abbr.textContent)
BuildTest.testOne post
Build.Test.testOne post
return
postsRemaining: 0
@ -86,18 +86,18 @@ BuildTest =
time: 0
report: ->
if BuildTest.postsFailed
new Notice 'warning', "#{BuildTest.postsFailed} post(s) differ (#{BuildTest.time} ms)", 30
if Build.Test.postsFailed
new Notice 'warning', "#{Build.Test.postsFailed} post(s) differ (#{Build.Test.time} ms)", 30
else
new Notice 'success', "All correct (#{BuildTest.time} ms)", 5
BuildTest.postsFailed = BuildTest.time = 0
new Notice 'success', "All correct (#{Build.Test.time} ms)", 5
Build.Test.postsFailed = Build.Test.time = 0
cb:
testOne: ->
BuildTest.testOne g.posts[@dataset.fullID]
Build.Test.testOne g.posts[@dataset.fullID]
Menu.menu.close()
testAll: ->
BuildTest.testAll()
Build.Test.testAll()
Header.menu.close()
<% } %>

View File

@ -1,24 +0,0 @@
Conf = {}
c = console
d = document
doc = d.documentElement
g =
VERSION: '<%= readJSON('version.json').version %>'
NAMESPACE: '<%= meta.name %>.'
boards: {}
E = do ->
str = {'&': '&amp;', "'": '&#039;', '"': '&quot;', '<': '&lt;', '>': '&gt;'}
r = String::replace
regex = /[&"'<>]/g
fn = (x) ->
str[x]
(text) -> r.call text, regex, fn
E.cat = (templates) ->
html = ''
html += x.innerHTML for x in templates
html
E.url = (content) ->
"data:text/html;charset=utf-8,<!doctype html>#{encodeURIComponent content.innerHTML}"

View File

@ -470,7 +470,7 @@ Main =
['Flash Features', Flash]
['Reply Pruning', ReplyPruning]
<% if (readJSON('.tests_enabled')) { %>
['Build Test', BuildTest]
['Build Test', Build.Test]
<% } %>
]

42
src/General/globals.js Normal file
View File

@ -0,0 +1,42 @@
var Conf, c, d, doc, g, E, $$;
Conf = {};
c = console;
d = document;
doc = d.documentElement;
g = {
VERSION: '<%= readJSON('version.json').version %>',
NAMESPACE: '<%= meta.name %>.',
boards: {}
};
E = (function() {
var str = {'&': '&amp;', "'": '&#039;', '"': '&quot;', '<': '&lt;', '>': '&gt;'};
var r = String.prototype.replace;
var regex = /[&"'<>]/g;
var fn = function (x) {
return str[x];
};
return function(text) {
return r.call(text, regex, fn);
};
})();
E.cat = function(templates) {
var html = '';
for (var i = 0, len = templates.length; i < len; i++) {
html += templates[i].innerHTML;
}
return html;
};
E.url = function (content) {
return 'data:text/html;charset=utf-8,<!doctype html>' + encodeURIComponent(content.innerHTML);
};
$$ = function(selector, root) {
if (root == null) {
root = d.body;
}
return [].slice.call(root.querySelectorAll(selector));
};

View File

@ -195,7 +195,7 @@ Keybinds =
<% if (readJSON('.tests_enabled')) { %>
when 't'
return unless threadRoot
BuildTest.testAll()
Build.Test.testAll()
<% } %>
else
return

3
src/meta/fbegin.js Normal file
View File

@ -0,0 +1,3 @@
'use strict';
(function() {

1
src/meta/fend.js Normal file
View File

@ -0,0 +1 @@
}).call(this);

View File

@ -20,16 +20,10 @@
"unsafeWindow": true,
"chrome": true<%=
meta.grants.map(x => `,\n "${x}": true`).join('')
%><% if (stage === 'parts') { %><%=
meta.globals.map(x => `,\n "${x}": true`).join('')
%><%=
(ls('src')
.map(x => ls(`src/${x}`))
.reduce((x,y) => x.concat(y))
.filter(x => /^[$A-Z]\w*\.coffee/.test(x))
.map(x => x.split('.')[0])
.map(x => `,\n "${x}": true`).join('')
)
%><% } %>
read('tmp/declaration.js').match(/^var (.*);/)[1].split(', ').map(x => `,\n "${x}": true`).join('')
%><%=
read('tmp/globals.js').match(/^var (.*);/)[1].split(', ').map(x => `,\n "${x}": true`).join('')
%>
}
}

View File

@ -1 +0,0 @@
'use strict';

View File

@ -1,56 +0,0 @@
var fs = require('fs');
var inputFiles = process.argv.slice(2, -1);
var allVars = [];
var allHelperNames = [];
var allHelperValues = {};
var allBodies = [];
for (var file of inputFiles) {
var inputText = fs.readFileSync(file, 'utf8').replace(/\r\n/g, '\n');
var parts = inputText.match(/^\(function\(\) {\n var ([\w$]+(?:, [\w$]+)*)((?:,\n [\w$]+ = .*)*);\n\n([^]*)\n\n}\)\.call\(this\);\n$/);
if (!parts) throw new Error(`${file}: unexpected format`);
var vars = parts[1].split(', ');
for (var v of vars) {
if (allVars.indexOf(v) >= 0) {
throw new Error(`${file}: reused variable name ${v}`);
}
if (allHelperNames.indexOf(v) >= 0) {
throw new Error(`${file}: variable clashes with helper ${v}`);
}
allVars.push(v);
}
var helpers = parts[2].split(',\n ').slice(1);
for (var h of helpers) {
var hparts = h.match(/^([\w$]+) = (.*)$/);
var hn = hparts[1];
var hv = hparts[2];
if (allVars.indexOf(hn) >= 0) {
throw new Error(`${file}: helper clashes with variable ${v}`);
}
if (allHelperNames.indexOf(hn) >= 0) {
if (allHelperValues[hn] !== hv) {
throw new Error(`${file}: redefined helper ${hn}`);
}
} else {
allHelperNames.push(hn);
allHelperValues[hn] = hv;
}
}
var body = parts[3];
allBodies.push(body);
}
var varText = allVars.sort().join(', ');
var helperText = allHelperNames.map(hn => `,\n ${hn} = ${allHelperValues[hn]}`).join('');
var bodyText = allBodies.join('\n\n');
var outputText = `(function() {\n var ${varText}${helperText};\n\n${bodyText}\n\n}).call(this);\n`;
var outputName = process.argv[process.argv.length - 1];
fs.writeFileSync(outputName, outputText);

10
tools/declare.js Normal file
View File

@ -0,0 +1,10 @@
var fs = require('fs');
var names = [];
for (var d of fs.readdirSync('src')) {
for (var f of fs.readdirSync(`src/${d}`)) {
var m = f.match(/^([$A-Z]\w*)\.coffee$/);
if (m) names.push(m[1]);
}
}
fs.writeFileSync('tmp/declaration.js', `var ${names.sort().join(', ')};\n`);

54
tools/globalize.js Normal file
View File

@ -0,0 +1,54 @@
var fs = require('fs');
var filename = process.argv[2];
var sources = process.argv.slice(3);
// Extract variables to be made global from source file list
// e.g. ImageExpand from src/Images/ImageExpand.coffee
// but not QR.post or eventPage
var names = [];
for (var f of sources) {
f = f.match(/[^/]*$/)[0];
var m = f.match(/^([$A-Z]\w*)\.coffee$/);
if (m) names.push(m[1]);
}
var script = fs.readFileSync(filename, 'utf8').replace(/\r\n/g, '\n');
var replaced = 0;
script = script.replace(
// matches declaration at the start of the function, not including helper function assignments
/ *\bvar\s+[\w$]+(,\s*[\w$]+)*(,\s*|;\n)/,
function(declaration) {
var parts = declaration.split(/([\w$]+)(?=[,;])/);
for (var name of names) {
var i = parts.indexOf(name);
if (i < 0) {
throw new Error(`${filename}: ${name} not found`);
} else if (i !== 1) {
// not first: remove variable and separator before it
parts.splice(i - 1, 2);
} else if (!(i === parts.length - 2 && parts[parts.length - 1][0] === ';')) {
// not last: remove variable and separator after it
parts.splice(i, 2);
} else {
// removing only variable: nuke whole declaration
parts = [];
}
}
replaced++;
return parts.join('');
}
);
if (replaced !== 1) {
throw new Error(`${filename}: no declaration found`);
}
fs.writeFileSync(filename, script);