summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore9
-rw-r--r--Makefile50
-rw-r--r--elm/ImageFlagging.js6
-rw-r--r--elm/UList/LabelEdit.js5
-rw-r--r--elm/UList/ManageLabels.js5
-rw-r--r--elm/UList/Opt.js12
-rw-r--r--elm/UList/VoteEdit.js5
-rw-r--r--elm/elm-init.js2
-rw-r--r--elm/lib.js15
-rw-r--r--elm/pagevars.js5
-rw-r--r--lib/VNDB/Util/LayoutHTML.pm1
-rw-r--r--lib/VNWeb/HTML.pm17
-rw-r--r--lib/VNWeb/User/Lists.pm2
-rw-r--r--lib/VNWeb/User/Notifications.pm2
-rw-r--r--lib/VNWeb/VN/Page.pm2
15 files changed, 78 insertions, 60 deletions
diff --git a/.gitignore b/.gitignore
index eda3cee9..584a6483 100644
--- a/.gitignore
+++ b/.gitignore
@@ -12,9 +12,12 @@
/static/f/vndb.js
/static/f/vndb.min.js
/static/f/vndb.min.js.gz
-/static/f/v2rw.js
-/static/f/v2rw.min.js
-/static/f/v2rw.min.js.gz
+/static/f/elm.js
+/static/f/elm.min.js
+/static/f/elm.min.js.gz
+/static/f/plain.js
+/static/f/plain.min.js
+/static/f/plain.min.js.gz
/static/feeds/
/static/s/*/style.css
/static/s/*/style.min.css
diff --git a/Makefile b/Makefile
index 953cd1c2..35151029 100644
--- a/Makefile
+++ b/Makefile
@@ -30,14 +30,16 @@ ALL_KEEP=\
ALL_CLEAN=\
static/f/vndb.js \
- static/f/v2rw.js \
+ static/f/plain.js \
+ static/f/elm.js \
data/icons/icons.css \
sql/editfunc.sql \
$(shell ls static/s | sed -e 's/\(.\+\)/static\/s\/\1\/style.css/g')
PROD=\
static/f/vndb.min.js static/f/vndb.min.js.gz \
- static/f/v2rw.min.js static/f/v2rw.min.js.gz \
+ static/f/plain.min.js static/f/plain.min.js.gz \
+ static/f/elm.min.js static/f/elm.min.js.gz \
static/f/icons.opt.png \
$(shell ls static/s | sed -e 's/\(.\+\)/static\/s\/\1\/style.min.css/g') \
$(shell ls static/s | sed -e 's/\(.\+\)/static\/s\/\1\/style.min.css.gz/g')
@@ -115,43 +117,57 @@ static/f/vndb.min.js: static/f/vndb.js
# Files without that comment are assumed to have '//order:4'.
# (This trick will not work if we ever add JS files generated by this Makefile)
JS_FILES=$(shell find elm \! -path 'elm/elm-stuff/*' -name '*.js' -exec sh -c "echo \`grep -Eo '^// *order: *[0-9]+' \"{}\" || echo 4\` \"{}\"" \; | sed -E 's/\/\/ *order: *//' | sort | sed 's/..//')
+
+static/f/plain.js: ${JS_FILES} | static/f
+ echo '// @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-3.0-only' > $@~
+ echo '// @source: https://code.blicky.net/yorhel/vndb/src/branch/master/elm' >>$@~
+ echo '// SPDX-License-Identifier: AGPL-3.0-only' >>$@~
+ for fn in ${JS_FILES}; do \
+ echo; \
+ echo "(function(){'use strict'; /* $$fn */"; \
+ cat $$fn; \
+ echo "})();"; \
+ done >>$@~
+ echo '// @license-end' >>$@~
+ mv $@~ $@
+
+static/f/plain.min.js: static/f/plain.js
+ uglifyjs $< --comments '/(@license|@source|SPDX-)/' --compress \
+ 'pure_getters,keep_fargs=false,unsafe_comps,unsafe'\
+ | uglifyjs --mangle --comments all -o $@
+
+
ELM_FILES=elm/*.elm elm/*/*.elm
ELM_MODULES=$(shell grep -l '^main =' ${ELM_FILES} | sed 's/^elm\///')
-# Patch the Javascript generated by Elm and append the $JS_FILES to it.
-# Patches include:
+# Patch the Javascript generated by Elm:
# - Add @license and @source comments
# - Redirect calls from Lib.Ffi.* to window.elmFfi_*
# - Patch the virtualdom diffing algorithm to always apply the 'selected' attribute
-define fix-js
+define fix-elm
( echo '// @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-3.0-only'; \
echo '// @license magnet:?xt=urn:btih:c80d50af7d3db9be66a4d0a86db0286e4fd33292&dn=bsd-3-clause.txt BSD-3-Clause'; \
echo '// @source: https://code.blicky.net/yorhel/vndb/src/branch/master/elm'; \
echo '// SPDX-License-Identifier: AGPL-3.0-only and BSD-3-Clause'; \
- cat $@ \
+ cat $@; \
+ echo; \
+ echo '// @license-end' \
) | sed 's/var \$$author\$$project\$$Lib\$$Ffi\$$/var __unused__/g' \
| sed -E 's/\$$author\$$project\$$Lib\$$Ffi\$$([a-zA-Z0-9_]+)/window.elmFfi_\1(_Json_wrap,_Browser_call)/g' \
| sed -E "s/([^ ]+) !== 'checked'/\\1 !== 'checked' \&\& \\1 !== 'selected'/g" >$@~
- for fn in ${JS_FILES}; do \
- echo; \
- echo "(function(){'use strict'; /* $$fn */"; \
- cat $$fn; \
- echo "})();"; \
- done >>$@~
- echo '// @license-end' >>$@~
mv $@~ $@
endef
elm/Gen/.generated: lib/VNWeb/*.pm lib/VNWeb/*/*.pm lib/VNDB/Types.pm lib/VNDB/ExtLinks.pm lib/VNDB/Config.pm data/conf.pl
util/vndb.pl elmgen
-static/f/v2rw.js: ${ELM_FILES} ${JS_FILES} elm/Gen/.generated | static/f
+static/f/elm.js: ${ELM_FILES} elm/Gen/.generated | static/f
cd elm && ELM_HOME=elm-stuff elm make ${ELM_MODULES} --output ../$@
- ${fix-js}
+ ${fix-elm}
-static/f/v2rw.min.js: ${ELM_FILES} ${JS_FILES} elm/Gen/.generated | static/f
+static/f/elm.min.js: ${ELM_FILES} elm/Gen/.generated | static/f
cd elm && ELM_HOME=elm-stuff elm make --optimize ${ELM_MODULES} --output ../$@
- ${fix-js}
+ ${fix-elm}
uglifyjs $@ --comments '/(@license|@source|SPDX-)/' --compress \
'pure_funcs="F2,F3,F4,F5,F6,F7,F8,F9,A2,A3,A4,A5,A6,A7,A8,A9",pure_getters,keep_fargs=false,unsafe_comps,unsafe'\
| uglifyjs --mangle --comments all -o $@~
diff --git a/elm/ImageFlagging.js b/elm/ImageFlagging.js
index 87ced23a..d460bd10 100644
--- a/elm/ImageFlagging.js
+++ b/elm/ImageFlagging.js
@@ -1,6 +1,4 @@
-var init = Elm.ImageFlagging.init;
-
-Elm.ImageFlagging.init = function(opt) {
+wrap_elm_init('ImageFlagging', function(init, opt) {
opt.flags.pWidth = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
opt.flags.pHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
var app = init(opt);
@@ -15,4 +13,4 @@ Elm.ImageFlagging.init = function(opt) {
preload[url].src = url;
}
});
-};
+});
diff --git a/elm/UList/LabelEdit.js b/elm/UList/LabelEdit.js
index 6617bf11..156ae08f 100644
--- a/elm/UList/LabelEdit.js
+++ b/elm/UList/LabelEdit.js
@@ -1,5 +1,4 @@
-var init = Elm.UList.LabelEdit.init;
-Elm.UList.LabelEdit.init = function(opt) {
+wrap_elm_init('UList.LabelEdit', function(init, opt) {
opt.flags.uid = pageVars.uid;
opt.flags.labels = pageVars.labels;
var app = init(opt);
@@ -8,4 +7,4 @@ Elm.UList.LabelEdit.init = function(opt) {
l.setAttribute('data-publabel', pub?1:'');
l.classList.toggle('invisible', !((l.getAttribute('data-voted') && !pageVars.voteprivate) || l.getAttribute('data-publabel')))
});
-};
+});
diff --git a/elm/UList/ManageLabels.js b/elm/UList/ManageLabels.js
index 6f762bd8..f9f8c68b 100644
--- a/elm/UList/ManageLabels.js
+++ b/elm/UList/ManageLabels.js
@@ -6,8 +6,7 @@ document.querySelectorAll('#managelabels').forEach(function(b) {
return false;
});
-var init = Elm.UList.ManageLabels.init;
-Elm.UList.ManageLabels.init = function(opt) {
+wrap_elm_init('UList.ManageLabels', function(init, opt) {
opt.flags = { uid: pageVars.uid, labels: pageVars.labels };
init(opt);
-};
+});
diff --git a/elm/UList/Opt.js b/elm/UList/Opt.js
index 75a302b9..7a80884a 100644
--- a/elm/UList/Opt.js
+++ b/elm/UList/Opt.js
@@ -1,6 +1,4 @@
-var init = Elm.UList.Opt.init;
-
-var actualInit = function(opt) {
+var actualInit = function(init, opt) {
var app = init(opt);
app.ports.ulistVNDeleted.subscribe(function(b) {
@@ -27,10 +25,10 @@ var actualInit = function(opt) {
};
// This module is typically hidden, lazily load it only when the module is visible to speed up page load time.
-Elm.UList.Opt.init = function(opt) {
+wrap_elm_init('UList.Opt', function(init, opt) {
var e = document.getElementById('collapse_vid'+opt.flags.vid);
if(e.checked)
- actualInit(opt);
+ actualInit(init, opt);
else
- e.addEventListener('click', function() { actualInit(opt) }, { once: true });
-};
+ e.addEventListener('click', function() { actualInit(init, opt) }, { once: true });
+});
diff --git a/elm/UList/VoteEdit.js b/elm/UList/VoteEdit.js
index 99d5b31b..a7ebfb74 100644
--- a/elm/UList/VoteEdit.js
+++ b/elm/UList/VoteEdit.js
@@ -1,9 +1,8 @@
-var init = Elm.UList.VoteEdit.init;
-Elm.UList.VoteEdit.init = function(opt) {
+wrap_elm_init('UList.VoteEdit', function(init, opt) {
var app = init(opt);
app.ports.ulistVoteChanged.subscribe(function(voted) {
var l = document.getElementById('ulist_public_'+opt.flags.vid);
l.setAttribute('data-voted', voted?1:'');
l.classList.toggle('invisible', !((l.getAttribute('data-voted') && !pageVars.voteprivate) || l.getAttribute('data-publabel')))
});
-};
+});
diff --git a/elm/elm-init.js b/elm/elm-init.js
index e48a94f3..d9978111 100644
--- a/elm/elm-init.js
+++ b/elm/elm-init.js
@@ -23,7 +23,7 @@ if(pageVars.elm) {
for(var i=0; i<pageVars.elm.length; i++) {
var e = pageVars.elm[i];
//if(e[0] != 'UList.DateEdit') continue;
- var mod = e[0].split('.').reduce(function(p, c) { return p[c] }, Elm);
+ var mod = e[0].split('.').reduce(function(p, c) { return p[c] }, window.Elm);
var node = document.getElementById('elm'+i);
if(e.length > 1)
mod.init({ node: node, flags: e[1] });
diff --git a/elm/lib.js b/elm/lib.js
new file mode 100644
index 00000000..859cfc22
--- /dev/null
+++ b/elm/lib.js
@@ -0,0 +1,15 @@
+//order:0 - Before anything else that may use these functions.
+
+/* Load global page-wide variables from <script id="pagevars">...</script> and store them into window.pageVars */
+var e = document.getElementById('pagevars');
+window.pageVars = e ? JSON.parse(e.innerHTML) : {};
+
+
+// Utlity function to wrap the init() function of an Elm module.
+window.wrap_elm_init = function(mod, newinit) {
+ mod = mod.split('.').reduce(function(p, c) { return p ? p[c] : null }, window.Elm);
+ if(mod) {
+ var oldinit = mod.init;
+ mod.init = function(opt) { newinit(oldinit, opt) };
+ }
+};
diff --git a/elm/pagevars.js b/elm/pagevars.js
deleted file mode 100644
index e36ed7da..00000000
--- a/elm/pagevars.js
+++ /dev/null
@@ -1,5 +0,0 @@
-//order:0 - Before anything else that may use window.pageVars
-
-/* Load global page-wide variables from <script id="pagevars">...</script> and store them into window.pageVars */
-var e = document.getElementById('pagevars');
-window.pageVars = e ? JSON.parse(e.innerHTML) : {};
diff --git a/lib/VNDB/Util/LayoutHTML.pm b/lib/VNDB/Util/LayoutHTML.pm
index 6bafbeda..a18542f8 100644
--- a/lib/VNDB/Util/LayoutHTML.pm
+++ b/lib/VNDB/Util/LayoutHTML.pm
@@ -35,7 +35,6 @@ sub htmlFooter { # %options => { pref_code => 1 }
noscript id => 'pref_code', title => $self->authGetCode('/xml/prefs.xml'), ''
if $o{pref_code} && $self->authInfo->{id};
script type => 'text/javascript', src => $self->{url_static}.'/f/vndb.js?'.$self->{version}, '';
- VNWeb::HTML::v2rwjs_() if $o{v2rwjs};
end 'body';
end 'html';
}
diff --git a/lib/VNWeb/HTML.pm b/lib/VNWeb/HTML.pm
index 4231b3c1..25df6152 100644
--- a/lib/VNWeb/HTML.pm
+++ b/lib/VNWeb/HTML.pm
@@ -403,19 +403,11 @@ sub _hidden_msg_ {
}
-sub v2rwjs_ { # Also used by VNDB::Util::LayoutHTML.
- script_ type => 'application/json', id => 'pagevars', sub {
- # Escaping rules for a JSON <script> context are kinda weird, but more efficient than regular xml_escape().
- lit_(JSON::XS->new->canonical->encode(tuwf->req->{pagevars}) =~ s{</}{<\\/}rg =~ s/<!--/<\\u0021--/rg);
- } if keys tuwf->req->{pagevars}->%*;
- script_ type => 'application/javascript', src => config->{url_static}.'/f/v2rw.js?'.config->{version}, '';
-}
-
-
# Options:
# title => $title
# index => 1/0, default 0
# feeds => 1/0
+# js => 1/0, set to 1 to ensure 'plain.js' is included on the page even if no elm_() modules are loaded.
# search => $query
# og => { opengraph metadata }
# type => Database entry type (used for the main tabs & hidden message)
@@ -441,7 +433,12 @@ sub framework_ {
$cont->() unless $o{hiddenmsg} && _hidden_msg_ \%o;
div_ id => 'footer', \&_footer_;
};
- v2rwjs_;
+ script_ type => 'application/json', id => 'pagevars', sub {
+ # Escaping rules for a JSON <script> context are kinda weird, but more efficient than regular xml_escape().
+ lit_(JSON::XS->new->canonical->encode(tuwf->req->{pagevars}) =~ s{</}{<\\/}rg =~ s/<!--/<\\u0021--/rg);
+ } if keys tuwf->req->{pagevars}->%*;
+ script_ type => 'application/javascript', src => config->{url_static}.'/f/elm.js?'.config->{version}, '' if tuwf->req->{pagevars}{elm};
+ script_ type => 'application/javascript', src => config->{url_static}.'/f/plain.js?'.config->{version}, '' if $o{js} || tuwf->req->{pagevars}{elm};
}
}
}
diff --git a/lib/VNWeb/User/Lists.pm b/lib/VNWeb/User/Lists.pm
index dbfd0aea..bbc986d2 100644
--- a/lib/VNWeb/User/Lists.pm
+++ b/lib/VNWeb/User/Lists.pm
@@ -567,7 +567,7 @@ TUWF::get qr{/$RE{uid}/ulist}, sub {
: $num_core_labels == 1 && $opt_labels->{5} ? 'wish' : 'list';
my $title = $own ? 'My list' : user_displayname($u)."'s list";
- framework_ title => $title, type => 'u', dbobj => $u, tab => $tab,
+ framework_ title => $title, type => 'u', dbobj => $u, tab => $tab, js => 1,
$own ? ( pagevars => {
uid => $u->{id}*1,
labels => $LABELS->analyze->{keys}{labels}->coerce_for_json($labels),
diff --git a/lib/VNWeb/User/Notifications.pm b/lib/VNWeb/User/Notifications.pm
index 618328a4..59512f05 100644
--- a/lib/VNWeb/User/Notifications.pm
+++ b/lib/VNWeb/User/Notifications.pm
@@ -111,7 +111,7 @@ TUWF::get qr{/$RE{uid}/notifies}, sub {
'ORDER BY n.id', $opt->{r} ? 'DESC' : 'ASC'
);
- framework_ title => 'My notifications',
+ framework_ title => 'My notifications', js => 1,
sub {
div_ class => 'mainbox', sub {
h1_ 'My notifications';
diff --git a/lib/VNWeb/VN/Page.pm b/lib/VNWeb/VN/Page.pm
index c3feac4a..d5c4b202 100644
--- a/lib/VNWeb/VN/Page.pm
+++ b/lib/VNWeb/VN/Page.pm
@@ -772,7 +772,7 @@ TUWF::get qr{/$RE{vrev}}, sub {
enrich_item $v;
- framework_ title => $v->{title}, index => !tuwf->capture('rev'), type => 'v', dbobj => $v, hiddenmsg => 1, og => og($v),
+ framework_ title => $v->{title}, index => !tuwf->capture('rev'), type => 'v', dbobj => $v, hiddenmsg => 1, js => 1, og => og($v),
sub {
rev_ $v if tuwf->capture('rev');
infobox_ $v;