diff --git a/book/dlang.org.ddoc b/book/dlang.org.ddoc index f2ee48e8a6..5bc8d83fc0 100644 --- a/book/dlang.org.ddoc +++ b/book/dlang.org.ddoc @@ -30,8 +30,7 @@ COMMON_HEADERS_DLANG= _= COMMON_SCRIPTS = - $(SCRIPTLOAD https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js) - $(SCRIPT window.jQuery || document.write('\x3Cscript src="$(STATIC js/jquery-3.7.1.min.js)">\x3C/script>');$(EXTRA_JS)) + $(SCRIPT $(EXTRA_JS)) $(SCRIPTLOAD $(STATIC js/dlang.js)) $(COMMON_SCRIPTS_DLANG) _= diff --git a/dlang.org.ddoc b/dlang.org.ddoc index f2fb4a6709..81e285c52a 100644 --- a/dlang.org.ddoc +++ b/dlang.org.ddoc @@ -31,8 +31,7 @@ COMMON_HEADERS_DLANG= _= COMMON_SCRIPTS = - $(SCRIPTLOAD https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js) - $(SCRIPT window.jQuery || document.write('\x3Cscript src="$(STATIC js/jquery-3.7.1.min.js)">\x3C/script>');$(EXTRA_JS)) + $(SCRIPT $(EXTRA_JS)) $(SCRIPTLOAD $(STATIC js/dlang.js)) $(COMMON_SCRIPTS_DLANG) _= diff --git a/js/ddox.js b/js/ddox.js index eb3bf78e2f..18cb203d12 100644 --- a/js/ddox.js +++ b/js/ddox.js @@ -1,56 +1,77 @@ +function ddoxReady(fn) { + if (document.readyState !== 'loading') fn(); + else document.addEventListener('DOMContentLoaded', fn); +} + function setupDdox() { - $(".tree-view").children(".package").click(toggleTree); - $(".tree-view.collapsed").children("ul").hide(); - $("#symbolSearch").attr("tabindex", "1000"); + document.querySelectorAll('.tree-view').forEach(function(tv) { + Array.prototype.filter.call(tv.children, function(c) { return c.classList.contains('package'); }) + .forEach(function(pkg) { pkg.addEventListener('click', toggleTree); }); + }); + document.querySelectorAll('.tree-view.collapsed').forEach(function(tv) { + Array.prototype.filter.call(tv.children, function(c) { return c.tagName === 'UL'; }) + .forEach(function(ul) { ul.style.display = 'none'; }); + }); + var sym = document.getElementById('symbolSearch'); + if (sym) sym.setAttribute('tabindex', '1000'); updateSearchBox(); - $('#sitesearch').change(updateSearchBox); + var siteSearch = document.getElementById('sitesearch'); + if (siteSearch) siteSearch.addEventListener('change', updateSearchBox); } function updateSearchBox() { - var ddox = $('#sitesearch').val() == "dlang.org/library"; - $('#q').toggle(!ddox); - $('#symbolSearch').toggle(ddox); + var siteSearch = document.getElementById('sitesearch'); + if (!siteSearch) return; + var ddox = siteSearch.value == "dlang.org/library"; + var q = document.getElementById('q'); + var sym = document.getElementById('symbolSearch'); + if (q) q.style.display = ddox ? 'none' : ''; + if (sym) sym.style.display = ddox ? '' : 'none'; } function toggleTree() { - node = $(this).parent(); - node.toggleClass("collapsed"); - if( node.hasClass("collapsed") ){ - node.children("ul").hide(); + var node = this.parentNode; + node.classList.toggle('collapsed'); + var uls = Array.prototype.filter.call(node.children, function(c) { return c.tagName === 'UL'; }); + if (node.classList.contains('collapsed')) { + uls.forEach(function(ul) { ul.style.display = 'none'; }); } else { - node.children("ul").show(); + uls.forEach(function(ul) { ul.style.display = ''; }); } return false; } -var searchCounter = 0; var lastSearchString = ""; function performSymbolSearch(maxlen) { if (maxlen === 'undefined') maxlen = 26; - var searchstring = $("#symbolSearch").val().toLowerCase(); + var symInput = document.getElementById('symbolSearch'); + if (!symInput) return; + var searchstring = symInput.value.toLowerCase(); if (searchstring == lastSearchString) return; lastSearchString = searchstring; - var scnt = ++searchCounter; - $('#symbolSearchResults').hide(); - $('#symbolSearchResults').empty(); + var results_el = document.getElementById('symbolSearchResults'); + if (results_el) { + results_el.style.display = 'none'; + while (results_el.firstChild) results_el.removeChild(results_el.firstChild); + } - var terms = $.trim(searchstring).split(/\s+/); + var terms = searchstring.replace(/^\s+|\s+$/g, '').split(/\s+/); if (terms.length == 0 || (terms.length == 1 && terms[0].length < 2)) return; var results = []; - for (i in symbols) { + for (var i in symbols) { var sym = symbols[i]; var all_match = true; - for (j in terms) + for (var j in terms) if (sym.name.toLowerCase().indexOf(terms[j]) < 0) { all_match = false; break; @@ -61,12 +82,10 @@ function performSymbolSearch(maxlen) } function compare(a, b) { - // prefer non-deprecated matches var adep = a.attributes.indexOf("deprecated") >= 0; var bdep = b.attributes.indexOf("deprecated") >= 0; if (adep != bdep) return adep - bdep; - // normalize the names var aname = a.name.toLowerCase(); var bname = b.name.toLowerCase(); @@ -76,20 +95,16 @@ function performSymbolSearch(maxlen) var asname = anameparts[anameparts.length-1]; var bsname = bnameparts[bnameparts.length-1]; - // prefer exact matches var aexact = terms.indexOf(asname) >= 0; var bexact = terms.indexOf(bsname) >= 0; if (aexact != bexact) return bexact - aexact; - // prefer elements with less nesting if (anameparts.length < bnameparts.length) return -1; if (anameparts.length > bnameparts.length) return 1; - // prefer matches with a shorter name if (asname.length < bsname.length) return -1; if (asname.length > bsname.length) return 1; - // sort the rest alphabetically if (aname < bname) return -1; if (aname > bname) return 1; return 0; @@ -97,17 +112,16 @@ function performSymbolSearch(maxlen) results.sort(compare); - for (i = 0; i < results.length && i < 100; i++) { + for (var i = 0; i < results.length && i < 100; i++) { var sym = results[i]; - var el = $(document.createElement("li")); - el.addClass(sym.kind); - for (j in sym.attributes) - el.addClass(sym.attributes[j]); + var el = document.createElement('li'); + el.classList.add(sym.kind); + for (var j in sym.attributes) + el.classList.add(sym.attributes[j]); var name = sym.name; - // compute a length limited representation of the full name var nameparts = name.split("."); var np = nameparts.length-1; var shortname = "." + nameparts[np]; @@ -118,23 +132,37 @@ function performSymbolSearch(maxlen) if (np > 0) shortname = ".." + shortname; else shortname = shortname.substr(1); - el.append(''+shortname+''); - $('#symbolSearchResults').append(el); + var a = document.createElement('a'); + a.href = symbolSearchRootDir + sym.path; + a.title = name; + a.setAttribute('tabindex', '1001'); + a.textContent = shortname; + el.appendChild(a); + if (results_el) results_el.appendChild(el); } - if (results.length > 100) { - $('#symbolSearchResults').append("
blocks from DDOC example sections with an +interactive form: an editor (CodeMirror), optional stdin/args inputs, +and a Run button that submits to tour.dlang.org. +Copyright: 2012 by Digital Mars License: http://boost.org/LICENSE_1_0.txt, Boost License 1.0 - Authors: Andrei Alexandrescu, Damian Ziemba */ -/** -Script workflow: - -1. Scan current document DOM tree forelements with class=d_code. -...blocks are generated by DDOC example sections. -2. Iterate each pre element and apply our custom form, replacing defaultblock -3. Get text from originalblock, strip any spaces and newlines from it and compute md5sum -4. Look up mainPage map with md5sum as a key and see if there are any elements associated with this key -5. If yes: Add to our custom form default Standard input and/or Standard Arguments, stdin being 0 key, stdout 1 key. -6. If no: Just skip to point 7 -7. Continue to nextelement and repeat begging from point 2 if there are still nodes left - -How to add new example or update existing: - -If example doesn't require any standard input neither standard argugments by default you are done. -Otherwise, copy example text without example separator ie: - ------- -[start here] -import std.stdio; - -void main(string[] args) { - writeln("Hello world. ", args); - writeln("What's your name?"); - writeln("Hello ", readln()); -} -[end here] ------- - -TL;DR -All examples are replaced with custom form by default. You need to do additional work only if you want -your example to have default standard input or default standard arguments. -*/ - -var nl2br = function() -{ - return this.replace(/\n/g, "
"); -} - -function safeVar(data, path) -{ - var p = path.split("."); - var res = null; - - try - { - res = data[p[0]][p[1]]; - if (typeof res == "object") - res = ""; +function childMatching(el, selector) { + for (var i = 0; i < el.children.length; i++) { + if (el.children[i].matches(selector)) return el.children[i]; } - catch (e) - { - return ""; + return null; +} +function childrenMatching(el, selector) { + var out = []; + for (var i = 0; i < el.children.length; i++) { + if (el.children[i].matches(selector)) out.push(el.children[i]); } - - return res; + return out; +} +function isVisible(el) { + return !!el && getComputedStyle(el).display !== 'none' && el.offsetParent !== null; +} +function setText(el, t) { if (el) el.textContent = t; } +function runReady(fn) { + if (document.readyState !== 'loading') fn(); + else document.addEventListener('DOMContentLoaded', fn); } // compile the examples on the prerelease pages with dmd-nightly var dmdCompilerBranch = location.href.indexOf("-prerelease/") >= 0 ? "dmd-nightly" : "dmd"; -var backends = { - dpaste: { - url: "https://dpaste.dzfl.pl/request/", - contentType: "application/x-www-form-urlencoded; charset=UTF-8", - requestTransform: function(data) { - return data; - }, - parseOutput: function(data, opts) { - var r = {}; - if (data.compilation === "undefined") - return null; - r.cout = safeVar(data, "compilation.stdout"); - r.stdout = safeVar(data, "runtime.stdout"); - r.stderr = safeVar(data, "runtime.stderr"); - r.ctime = parseInt(safeVar(data, "compilation.time")); - r.rtime = parseInt(safeVar(data, "runtime.time")); - r.cstatus = parseInt(safeVar(data, "compilation.status")); - r.rstatus = parseInt(safeVar(data, "runtime.status")); - r.cerr = safeVar(data, "compilation.err"); - r.rerr = safeVar(data, "runtime.err"); - r.defaultOutput = data.output || opts.defaultOutput; - return r; - } - }, - tour: { - url: "https://tour.dlang.org/api/v1/run", - // send json as text/plain to avoid an additional preflight OPTIONS request - // https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Preflighted_requests - contentType: "text/plain; charset=UTF-8", - requestTransform: function(data) { - var req = { - source: data.code, - // always execute unittests and main for backwards compatibility with examples - args: "-unittest -main", - runtimeArgs: "--DRT-testmode=run-main", - compiler: dmdCompilerBranch - } - // only send set attributes - if (data.stdin) { - req.stdin = data.stdin; - } - if (data.args) { - req.args = data.args; +// POST a tour.dlang.org run request and render the result. +// JSON is sent as text/plain to avoid a preflight OPTIONS request; see +// https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Preflighted_requests +function runOnTour(data, opts, output, outputTitle) { + var req = { + source: data.code, + // always execute unittests and main for backwards compatibility with examples + args: "-unittest -main", + runtimeArgs: "--DRT-testmode=run-main", + compiler: dmdCompilerBranch, + }; + if (data.stdin) req.stdin = data.stdin; + if (data.args) req.args = data.args; + var body = JSON.stringify(req); + return fetch("https://tour.dlang.org/api/v1/run", { + method: 'POST', + headers: { 'Content-Type': 'text/plain; charset=UTF-8' }, + body: body, + }) + .then(function(resp) { + if (!resp.ok) throw new Error('HTTP ' + resp.status); + return resp.json(); + }) + .then(function(res) { + var success = !(res.errors && res.errors.length > 0); + if (!success) { + setText(outputTitle, "Compilation output"); + setText(output, res.output); + } else { + setText(outputTitle, "Application output"); + setText(output, res.output || opts.defaultOutput); } - return JSON.stringify(req); - }, - parseOutput: function(data, opts) { - var r = {}; - if (data.success === "undefined") { - return null; - } - var success = !(data.errors && data.errors.length > 0); - r.cout = !success ? data.output : ""; - r.stdout = success ? data.output : ""; - r.stderr = !success ? data.output : ""; - r.ctime = ""; - r.rtime = ""; - r.cstatus = success ? 0 : 1; - r.rstatus = 0; // not supported - r.cerr = ""; - r.rerr = ""; - r.defaultOutput = data.output || opts.defaultOutput; - return r; - } - } -}; - -function parseOutput(res, o, oTitle) -{ - if (!res) - { - o.text("Temporarily unavailable"); - return; - } - - var output = ""; - var defaultOutput = res.defaultOutput || '-- No output --'; - - if (res.cstatus != 0) - { - oTitle.text("Compilation output ("+res.cstatus+": "+res.cerr+")"); - o.text(res.cout); - - return; - } - else - { - oTitle.text("Application output");// (compile "+ctime+"ms, run "+rtime+"ms)"); - if ( res.cout != "") - output = 'Compilation output: \n' + res.cout + "\n"; - - output += (res.stdout == "" && res.stderr == "" ? res.defaultOutput : res.stdout); - - if (res.stderr != "") - output += res.stderr; - - if (res.rstatus != 0) - oTitle.text("Application output ("+res.rstatus+": "+res.rerr+")"); - } - - o.text(output); + }); } // wraps a unittest into a runnable script function wrapIntoMain(code, compile) { - var currentPackage = $('body')[0].id; - // dynamically wrap into main if needed if (compile || code.indexOf("void main") >= 0 || code.indexOf("int main") >= 0) { return code; } else { var codeOut = "void main()\n{\n"; - // writing to the stdout is probably often used codeOut += " import std.stdio: write, writeln, writef, writefln;\n "; codeOut += "#line 1\n"; codeOut += code.split("\n").join("\n "); @@ -191,21 +86,19 @@ function wrapIntoMain(code, compile) { } } -$(document).ready(function() +runReady(function() { setUpExamples(); - var currentPage = $(location).attr('pathname'); - - $('.runnable-examples').each(function(index) - { - var root = $(this); - var el = root.children("pre"); + document.querySelectorAll('.runnable-examples').forEach(function(root) { + var el = childMatching(root, 'pre'); + if (!el) return; - var stdin = root.children(".runnable-examples-stdin").text(); - var args = root.children(".runnable-examples-args").text(); + var stdinNode = childMatching(root, '.runnable-examples-stdin'); + var argsNode = childMatching(root, '.runnable-examples-args'); + var stdin = stdinNode ? stdinNode.textContent : ''; + var args = argsNode ? argsNode.textContent : ''; - // only show stdin or args if they are set if (stdin.length > 0) { stdin = 'Standard input'; } - var compile = el.parent()[0].hasAttribute('data-compile'); - var runAttrs = `value="${compile ? 'Compile' : 'Run'}"`; + var compile = el.parentNode.hasAttribute('data-compile'); + var runAttrs = 'value="' + (compile ? 'Compile' : 'Run') + '"'; if (!compile) runAttrs += ' title="Note: Wraps code in `main` automatically if `main` is missing' + ' & imports std.stdio.write[f][ln]"'; - var currentExample = el; - var orig = currentExample.html(); + var orig = el.innerHTML; - currentExample.replaceWith( + var html = '
' @@ -217,15 +110,14 @@ $(document).ready(function() + '' + ''+orig+'' + '' @@ -234,19 +126,27 @@ $(document).ready(function() + '' + (args.length > 0 ? '' : '') + (stdin.length > 0 ? '' : '') - + `` + + '' + '' - + '' - ); + + ''; + + var tmp = document.createElement('div'); + tmp.innerHTML = html; + var parent = el.parentNode; + while (tmp.firstChild) { + parent.insertBefore(tmp.firstChild, el); + } + parent.removeChild(el); }); - $('textarea[class=d_code]').each(function(index) { - var parent = $(this).parent(); - var outputDiv = parent.children("div.d_code_output"); - var hasStdin = parent.children(".inputButton").length > 0; - var hasArgs = parent.children(".argsButton").length > 0; - var compile = parent.parent()[0].hasAttribute('data-compile'); - setupTextarea(this, { + document.querySelectorAll('textarea.d_code').forEach(function(ta) { + if (ta.className !== 'd_code') return; // jQuery's [class=d_code] = exact match + var parent = ta.parentNode; + var outputDiv = childMatching(parent, 'div.d_code_output'); + var hasStdin = childrenMatching(parent, '.inputButton').length > 0; + var hasArgs = childrenMatching(parent, '.argsButton').length > 0; + var compile = parent.parentNode.hasAttribute('data-compile'); + setupTextarea(ta, { parent: parent, outputDiv: outputDiv, stdin: hasStdin, @@ -261,47 +161,28 @@ $(document).ready(function() function setupTextarea(el, opts) { opts = opts || {}; - // set default opts - opts = jQuery.extend({}, { + opts = Object.assign({}, { stdin: false, args: false, transformOutput: function(out) { return out } }, opts); - var backend = backends[opts.backend || "tour"]; - - if (!!opts.parent) - var parent = opts.parent; - else - console.error("parent node node not found"); - - if (!!opts.outputDiv) - var outputDiv = opts.outputDiv; - else - console.error("outputDiv node not found"); + var parent = opts.parent; + var outputDiv = opts.outputDiv; + parent.style.display = 'block'; - var thisObj = $(el); - parent.css("display", "block"); - var orgSrc = parent.parent().children("div.d_code").children("pre.d_code"); + var siblingCodeDiv = childMatching(parent.parentNode, 'div.d_code'); + var orgSrc = siblingCodeDiv ? childMatching(siblingCodeDiv, 'pre.d_code') : null; - var prepareForMain = function() - { - var src = orgSrc.text(); - var arr = src.split("\n"); - var str = ""; - for (var i = 0; i < arr.length; i++) - { - str += arr[i]+"\n"; - } - return str; + var prepareForMain = function() { + return orgSrc ? orgSrc.textContent + "\n" : ""; }; var editor; - var code; + var code; // wrapper element produced by CodeMirror function initializeEditor(){ - if (typeof editor !== "undefined") - return; - editor = CodeMirror.fromTextArea(thisObj[0], { + if (typeof editor !== "undefined") return; + editor = CodeMirror.fromTextArea(el, { lineNumbers: true, tabSize: 4, indentUnit: 4, @@ -313,152 +194,125 @@ function setupTextarea(el, opts) matchBrackets: true }); editor.setValue(prepareForMain()); - code = $(editor.getWrapperElement()); - code.css('display', 'none'); - + code = editor.getWrapperElement(); + code.style.display = 'none'; } var height = function(diff) { - var par = code != null ? code : parent.parent().children("div.d_code"); - return (parseInt(par.css('height')) - diff) + 'px'; + var par = code != null ? code : childMatching(parent.parentNode, 'div.d_code'); + if (!par) return '0px'; + return (parseInt(getComputedStyle(par).height) - diff) + 'px'; }; - var runBtn = parent.children(".runButton"); - var editBtn = parent.children(".editButton"); - var resetBtn = parent.children(".resetButton"); - var openInEditorBtn = parent.children(".openInEditorButton"); + var runBtn = childMatching(parent, '.runButton'); + var editBtn = childMatching(parent, '.editButton'); + var resetBtn = childMatching(parent, '.resetButton'); + var openInEditorBtn = childMatching(parent, '.openInEditorButton'); - var plainSourceCode = parent.parent().children("div.d_code"); + var plainSourceCode = childMatching(parent.parentNode, 'div.d_code'); - var output = outputDiv.children("pre.d_code_output"); - var outputTitle = outputDiv.children("span.d_code_title"); + var output = childMatching(outputDiv, 'pre.d_code_output'); + var outputTitle = childMatching(outputDiv, 'span.d_code_title'); + var argsBtn, argsDiv, argsArea, orgArgs; + var inputBtn, stdinDiv, stdinArea, orgStdin; if (opts.args) { - var argsBtn = parent.children("input.argsButton"); - var argsDiv = parent.children("div.d_code_args"); - var args = argsDiv.children("textarea.d_code_args"); - var orgArgs = args.val(); + argsBtn = childMatching(parent, 'input.argsButton'); + argsDiv = childMatching(parent, 'div.d_code_args'); + argsArea = argsDiv ? childMatching(argsDiv, 'textarea.d_code_args') : null; + orgArgs = argsArea ? argsArea.value : ''; } if (opts.stdin) { - var inputBtn = parent.children("input.inputButton"); - var stdinDiv = parent.children("div.d_code_stdin"); - var stdin = stdinDiv.children("textarea.d_code_stdin"); - var orgStdin = stdin.val(); + inputBtn = childMatching(parent, 'input.inputButton'); + stdinDiv = childMatching(parent, 'div.d_code_stdin'); + stdinArea = stdinDiv ? childMatching(stdinDiv, 'textarea.d_code_stdin') : null; + orgStdin = stdinArea ? stdinArea.value : ''; } var hideAllWindows = function(optArguments) { optArguments = optArguments || {}; - if (opts.stdin) { - stdinDiv.css('display', 'none'); - } - if (opts.args) { - argsDiv.css('display', 'none'); + if (opts.stdin && stdinDiv) stdinDiv.style.display = 'none'; + if (opts.args && argsDiv) argsDiv.style.display = 'none'; + outputDiv.style.display = 'none'; + if (!optArguments.keepPlainSourceCode && plainSourceCode) { + plainSourceCode.style.display = 'none'; } - outputDiv.css('display', 'none'); - if (!optArguments.keepPlainSourceCode) { - plainSourceCode.css('display', 'none'); - } - if (!optArguments.keepCode) { - code.css('display', 'none'); + if (!optArguments.keepCode && code) { + code.style.display = 'none'; } }; - if (opts.args) { - argsBtn.click(function(){ - resetBtn.css('display', 'inline-block'); - args.css('height', height(31)); + if (opts.args && argsBtn) { + argsBtn.addEventListener('click', function(){ + resetBtn.style.display = 'inline-block'; + if (argsArea) argsArea.style.height = height(31); hideAllWindows(); - argsDiv.css('display', 'block'); - args.focus(); + argsDiv.style.display = 'block'; + if (argsArea) argsArea.focus(); }); } - if (opts.stdin) { - inputBtn.click(function(){ - resetBtn.css('display', 'inline-block'); - stdin.css('height', height(31)); + if (opts.stdin && inputBtn) { + inputBtn.addEventListener('click', function(){ + resetBtn.style.display = 'inline-block'; + if (stdinArea) stdinArea.style.height = height(31); hideAllWindows(); - stdinDiv.css('display', 'block'); - stdin.focus(); + stdinDiv.style.display = 'block'; + if (stdinArea) stdinArea.focus(); }); } - editBtn.click(function(){ + editBtn.addEventListener('click', function(){ initializeEditor(); - resetBtn.css('display', 'inline-block'); + resetBtn.style.display = 'inline-block'; hideAllWindows(); - code.css('display', 'block'); + code.style.display = 'block'; editor.refresh(); editor.focus(); }); - resetBtn.click(function(){ - resetBtn.css('display', 'none'); + resetBtn.addEventListener('click', function(){ + resetBtn.style.display = 'none'; editor.setValue(prepareForMain()); - if (opts.args) { - args.val(orgArgs); - } - if (opts.stdin) { - stdin.val(orgStdin); - } + if (opts.args && argsArea) argsArea.value = orgArgs; + if (opts.stdin && stdinArea) stdinArea.value = orgStdin; hideAllWindows(); - plainSourceCode.css('display', 'block'); + if (plainSourceCode) plainSourceCode.style.display = 'block'; }); - runBtn.click(function(){ + runBtn.addEventListener('click', function(){ initializeEditor(); - resetBtn.css('display', 'inline-block'); - $(this).attr("disabled", true); + resetBtn.style.display = 'inline-block'; + runBtn.disabled = true; var optArguments = {}; - // check what boxes are currently open if (opts.keepCode) { - optArguments.keepCode = code.is(":visible"); - optArguments.keepPlainSourceCode = plainSourceCode.is(":visible"); + optArguments.keepCode = isVisible(code); + optArguments.keepPlainSourceCode = isVisible(plainSourceCode); } hideAllWindows(optArguments); - output.css('height', opts.outputHeight || height(31)); - outputDiv.css('display', 'block'); - outputTitle.text("Application output"); - output.html("Running..."); - output.focus(); + if (output) output.style.height = opts.outputHeight || height(31); + outputDiv.style.display = 'block'; + setText(outputTitle, 'Application output'); + if (output) output.innerHTML = 'Running...'; + if (output) output.focus(); var data = { - code: opts.transformOutput(editor.getValue(), opts.compile) + code: opts.transformOutput(editor.getValue(), opts.compile), + stdin: opts.stdin && stdinArea ? stdinArea.value : "", + args: opts.args && argsArea ? argsArea.value : "", }; - if (opts.stdin) { - data.stdin = stdin.val(); - } - if (opts.args) { - data.args = args.val(); - } - $.ajax({ - type: 'POST', - url: backend.url, - contentType: backend.contentType, - dataType: "json", - data: backend.requestTransform(data), - success: function(data) - { - parseOutput(backend.parseOutput(data, opts), output, outputTitle); - runBtn.attr("disabled", false); - }, - error: function(jqXHR, textStatus, errorThrown ) - { - output.html("Temporarily unavailable"); - if (typeof console != "undefined") - { - console.log(textStatus + ": " + errorThrown); - } - - runBtn.attr("disabled", false); - } - }); + runOnTour(data, opts, output, outputTitle) + .catch(function(err) { + if (output) output.innerHTML = 'Temporarily unavailable'; + console.log(String(err)); + }) + .then(function() { runBtn.disabled = false; }); }); - openInEditorBtn.click(function(){ - var text = (editor && editor.getValue()) || prepareForMain(); - var url = "https://run.dlang.io?compiler=" + dmdCompilerBranch + "&args=-unittest&source=" + encodeURIComponent(opts.transformOutput(text)); - window.open(url, "_blank"); + openInEditorBtn.addEventListener('click', function(){ + var text = (editor && editor.getValue()) || prepareForMain(); + var url = "https://run.dlang.io?compiler=" + dmdCompilerBranch + "&args=-unittest&source=" + encodeURIComponent(opts.transformOutput(text)); + window.open(url, "_blank"); }); return editor; -}; +} function setUpExamples() @@ -466,32 +320,32 @@ function setUpExamples() /* Sets up expandable example boxes. * max-height and CSS transitions are used to animate the closing and opening for smooth animations even on less powerful devices */ - $('.example-box').each(function() { - var $box = $(this); - var boxId = $box.attr('id'); - // A little juggling here because the content needs to be a block element and the control needs to be an inline - // element in the previous paragraph. - var $control = $('#' + boxId + '-control'); - $control.attr('aria-controls', boxId); - var $showLabel = $('Show example '); - var $hideLabel = $('Hide example '); + document.querySelectorAll('.example-box').forEach(function(box) { + var boxId = box.id; + var control = document.getElementById(boxId + '-control'); + if (!control) return; + control.setAttribute('aria-controls', boxId); + var showLabel = 'Show example '; + var hideLabel = 'Hide example '; function toggle() { - if ($box.attr('aria-hidden') === 'true') { - $box.attr('aria-hidden', false); - $control.attr('aria-expanded', true); - $control.empty().append($hideLabel); - $box.css('max-height', $box[0].scrollHeight); + if (box.getAttribute('aria-hidden') === 'true') { + box.setAttribute('aria-hidden', 'false'); + control.setAttribute('aria-expanded', 'true'); + control.innerHTML = hideLabel; + box.style.maxHeight = box.scrollHeight + 'px'; } else { - $box.attr('aria-hidden', true); - $control.attr('aria-expanded', false); - $control.empty().append($showLabel); - $box.css('max-height', 0); + box.setAttribute('aria-hidden', 'true'); + control.setAttribute('aria-expanded', 'false'); + control.innerHTML = showLabel; + box.style.maxHeight = '0'; } return false; } - $control.on('click', toggle); + control.addEventListener('click', function(e) { toggle(); e.preventDefault(); }); toggle(); }); // NB: href needed for browsers to include the controls in the (keyboard) tab order - $('.example-control').attr('href', '#'); + document.querySelectorAll('.example-control').forEach(function(c) { + c.setAttribute('href', '#'); + }); } diff --git a/js/run_examples.js b/js/run_examples.js index 063fea193a..b662345446 100644 --- a/js/run_examples.js +++ b/js/run_examples.js @@ -6,17 +6,9 @@ * License: http://boost.org/LICENSE_1_0.txt, Boost License 1.0 */ -// turns asserts into writeln -function reformatExample(code) { - return code.replace(/(assert<\/span>(?:)?\((.*)==(.*)\);)+/g, function(match, text, left, right) { - return "writeln(" + left.trim() + "); " - + "// " + right.trim() + ""; - }); -} - // wraps a unittest into a runnable script function wrapIntoMain(code) { - var currentPackage = $('body')[0].id; + var currentPackage = document.body.id; var codeOut = ""; // dynamically wrap into main if needed @@ -26,7 +18,7 @@ function wrapIntoMain(code) { codeOut += code; } else { - var codeOut = "void main()\n{\n"; + codeOut = "void main()\n{\n"; codeOut += " import " + currentPackage + ";\n"; // writing to the stdout is probably often used codeOut += (currentPackage == "std.file") ? " import std.stdio: writeln, writef, writefln;\n " : " import std.stdio: write, writeln, writef, writefln;\n "; @@ -37,33 +29,41 @@ function wrapIntoMain(code) { return codeOut; } -$(document).ready(function() -{ - if ($('body')[0].id == "Home") - return; +(function() { + function ready(fn) { + if (document.readyState !== 'loading') fn(); + else document.addEventListener('DOMContentLoaded', fn); + } - // only for std at the moment - if (!$('body').hasClass("std")) - return; + function childMatching(el, selector) { + for (var i = 0; i < el.children.length; i++) { + if (el.children[i].matches(selector)) return el.children[i]; + } + return null; + } - // first selector is for ddoc - second for ddox - var codeBlocks = $('pre[class~=d_code]').add('pre[class~=code]'); - codeBlocks.each(function(index) - { - var currentExample = $(this); - var orig = currentExample.html(); + ready(function() { + if (document.body.id == 'Home') return; - // disable regex assert -> writeln rewrite logic (for now) - //orig = reformatExample(orig); + // only for std at the moment + if (!document.body.classList.contains('std')) return; - // check whether it is from a ddoced unittest - // 1) check is for ddoc, 2) for ddox - // manual created tests most likely can't be run without modifications - if (!($(this).parent().parent().prev().hasClass("dlang_runnable") || - $(this).prev().children(":last").hasClass("dlang_runnable"))) - return; + // first selector is for ddoc - second for ddox + var codeBlocks = document.querySelectorAll('pre.d_code, pre.code'); + codeBlocks.forEach(function(currentExample) { + var orig = currentExample.innerHTML; - currentExample.replaceWith( + // check whether it is from a ddoced unittest + // 1) check is for ddoc, 2) for ddox + var p1 = currentExample.parentNode && currentExample.parentNode.parentNode; + var prev1 = p1 ? p1.previousElementSibling : null; + var prev2 = currentExample.previousElementSibling; + var lastChildPrev2 = prev2 ? prev2.lastElementChild : null; + var isRunnable = (prev1 && prev1.classList.contains('dlang_runnable')) + || (lastChildPrev2 && lastChildPrev2.classList.contains('dlang_runnable')); + if (!isRunnable) return; + + var html = '' + ''; + + var tmp = document.createElement('div'); + tmp.innerHTML = html; + var p = currentExample.parentNode; + while (tmp.firstChild) p.insertBefore(tmp.firstChild, currentExample); + p.removeChild(currentExample); + }); - $('textarea[class=d_code]').each(function(index) { - var parent = $(this).parent(); - var btnParent = parent.parent().children(".d_example_buttons"); - var outputDiv = parent.parent().children(".d_code_output"); - var editor = setupTextarea(this, { - parent: btnParent, - outputDiv: outputDiv, - stdin: false, - args: false, - transformOutput: wrapIntoMain, - defaultOutput: "All tests passed", - keepCode: true, - outputHeight: "auto", - backend: "tour" + document.querySelectorAll('textarea.d_code').forEach(function(ta) { + if (ta.className !== 'd_code') return; // exact class match + var parent = ta.parentNode; + var btnParent = childMatching(parent.parentNode, '.d_example_buttons'); + var outputDiv = childMatching(parent.parentNode, '.d_code_output'); + setupTextarea(ta, { + parent: btnParent, + outputDiv: outputDiv, + transformOutput: wrapIntoMain, + defaultOutput: "All tests passed", + keepCode: true, + outputHeight: "auto", + }); }); }); -}); +})(); diff --git a/js/show_contributors.js b/js/show_contributors.js index a049189503..5824a99d71 100644 --- a/js/show_contributors.js +++ b/js/show_contributors.js @@ -11,57 +11,63 @@ Authors: Sebastian Wilzbach // find out whether the current page is a module or package function isPackage() { - return $('.tip.smallprint a[href*="package.d"]').length > 0; + return document.querySelectorAll('.tip.smallprint a[href*="package.d"]').length > 0; } -$(document).ready(function() -{ - // only for library documentation - if (!$('body').hasClass("std")) - return; - - // for index modules (package.d), we want to display all contributors of the package - var modulePath = document.body.id.replace(/[.]/g, '/'); - if (!isPackage()) - modulePath += '.d'; - - // enable only for std, etc and core - var repo; - if (modulePath.indexOf("core") == 0 || modulePath.indexOf("object") == 0) - { - repo = "dmd"; - modulePath = "druntime/src/" + modulePath; - } - else if (modulePath.indexOf("std") == 0 || modulePath.indexOf("etc") == 0) - { - repo = "phobos"; - } - else - { - return; +(function() { + function ready(fn) { + if (document.readyState !== 'loading') fn(); + else document.addEventListener('DOMContentLoaded', fn); } - $.getJSON( "https://contribs.dlang.io/contributors/file/dlang/" + repo + "?file=" + modulePath, function(contributors) - { + ready(function() { + // only for library documentation + if (!document.body.classList.contains("std")) return; - var posToInsert = $('#copyright'); - var contentNode = $(""); + // for index modules (package.d), display all contributors of the package + var modulePath = document.body.id.replace(/[.]/g, '/'); + if (!isPackage()) modulePath += '.d'; - var totalContributors = contributors.length; - // ignore invalid files - if (totalContributors == 0) + // enable only for std, etc and core + var repo; + if (modulePath.indexOf("core") == 0 || modulePath.indexOf("object") == 0) { + repo = "dmd"; + modulePath = "druntime/src/" + modulePath; + } else if (modulePath.indexOf("std") == 0 || modulePath.indexOf("etc") == 0) { + repo = "phobos"; + } else { return; + } + + fetch("https://contribs.dlang.io/contributors/file/dlang/" + repo + "?file=" + modulePath) + .then(function(resp) { return resp.json(); }) + .then(function(contributors) { + var posToInsert = document.getElementById('copyright'); + if (!posToInsert) return; + var contentNode = document.createElement('div'); + contentNode.id = 'contributors-github'; + + var totalContributors = contributors.length; + if (totalContributors == 0) return; - contentNode.append("' + '' + '' + ''+orig+'' @@ -72,30 +72,34 @@ $(document).ready(function() + '' + 'Application output' - ); - }); + + 'Running...' - + '" + totalContributors + " Contributors
"); + var h3 = document.createElement('h3'); + h3.textContent = totalContributors + ' Contributors'; + contentNode.appendChild(h3); - // list contributors with github avatar - $.each(contributors, function(i, contributor) - { - var contributorDiv = ''; - contributorDiv += ''; - contributorDiv += ""; - contentNode.append(contributorDiv); - }); - contentNode.insertBefore(posToInsert); + contributors.forEach(function(contributor) { + var a = document.createElement('a'); + a.href = contributor.html_url; + a.target = '_blank'; + var img = document.createElement('img'); + img.src = contributor.avatar_url + '&size=40'; + img.height = 40; + img.width = 40; + img.alt = contributor.login; + a.appendChild(img); + contentNode.appendChild(a); + }); + posToInsert.parentNode.insertBefore(contentNode, posToInsert); + }) + .catch(function() { /* silent */ }); }); -}); +})(); diff --git a/posix.mak b/posix.mak index 59f06c83fa..4c1bb3c9bb 100644 --- a/posix.mak +++ b/posix.mak @@ -303,7 +303,7 @@ IMAGES=favicon.ico images/d002.ico $(filter-out $(wildcard images/*_hq.*) images JAVASCRIPT=$(addsuffix .js, $(addprefix js/, \ codemirror-compressed dlang ddox listanchors platform-downloads run \ - run_examples show_contributors jquery-3.7.1.min)) + run_examples show_contributors)) STYLES=$(addsuffix .css, $(addprefix css/, \ style print codemirror ddox))