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("
  • …"+(results.length-100)+" additional results
  • "); + if (results.length > 100 && results_el) { + var more = document.createElement('li'); + more.innerHTML = '…' + (results.length - 100) + ' additional results'; + results_el.appendChild(more); } - $('#symbolSearchResults').show(); + if (results_el) results_el.style.display = ''; } -$(function(){ - $("#search-box form").on("submit", function(e) { - var searchResults = $('#symbolSearchResults').children(); - if (searchResults.length > 0) { - window.location = searchResults.first().find("a").attr("href"); - e.preventDefault(); +ddoxReady(function(){ + var form = document.querySelector('#search-box form'); + if (!form) return; + form.addEventListener('submit', function(e) { + var results_el = document.getElementById('symbolSearchResults'); + if (!results_el) return; + var first = results_el.firstElementChild; + if (first) { + var link = first.querySelector('a'); + if (link) { + window.location = link.getAttribute('href'); + e.preventDefault(); + } } }); }); diff --git a/js/dlang.js b/js/dlang.js index 2ff4b721d5..68e8f22416 100644 --- a/js/dlang.js +++ b/js/dlang.js @@ -1,78 +1,111 @@ -(function($) { - $(function() { +(function() { + function ready(fn) { + if (document.readyState !== 'loading') fn(); + else document.addEventListener('DOMContentLoaded', fn); + } + + function parentsMatching(el, selector) { + var result = []; + var node = el.parentElement; + while (node) { + if (node.matches(selector)) result.push(node); + node = node.parentElement; + } + return result; + } + + ready(function() { if (typeof cssmenu_no_js === 'undefined') { // add subnav toggle - $('.subnav').addClass('expand-container'); - $('.subnav').prepend( - $('.subnav h2').clone().addClass('expand-toggle') - ); + document.querySelectorAll('.subnav').forEach(function(subnav) { + subnav.classList.add('expand-container'); + var h2 = subnav.querySelector('h2'); + if (h2) { + var toggle = h2.cloneNode(true); + toggle.classList.add('expand-toggle'); + subnav.insertBefore(toggle, subnav.firstChild); + } + }); // highlight menu entry of the current page var href = window.location.href.split('#')[0]; - var current; - var res = $('#top a, .subnav a').each(function (_, a) { - if (a.href == href) { - current = a; - return false; - } - }); - current = $(current); - // direct li parent containing the link - current.parent('li').addClass('active'); - // topmost li parent, e.g. 'std' - current.parents('#top .expand-container').addClass('active'); - current.parents('.subnav .expand-container') - .addClass('open'); + var current = null; + var links = document.querySelectorAll('#top a, .subnav a'); + for (var i = 0; i < links.length; i++) { + if (links[i].href == href) { current = links[i]; break; } + } + if (current) { + // direct li parent containing the link + var liParent = current.parentElement.closest('li'); + if (liParent) liParent.classList.add('active'); + // topmost li parent, e.g. 'std' + parentsMatching(current, '#top .expand-container').forEach(function(p) { + p.classList.add('active'); + }); + parentsMatching(current, '.subnav .expand-container').forEach(function(p) { + p.classList.add('open'); + }); + } var open_main_item = null; - $('.expand-toggle').click(function(e) { - var container = $(this).parent('.expand-container'); - container.toggleClass('open'); + document.querySelectorAll('.expand-toggle').forEach(function(toggle) { + toggle.addEventListener('click', function(e) { + var container = toggle.parentElement.closest('.expand-container'); + if (!container) { e.preventDefault(); return false; } + container.classList.toggle('open'); - /* In the main menu, let only one dropdown be open at a - time. Also close any open main menu dropdown when clicking - elsewhere. */ - if (open_main_item !== container && open_main_item !== null) { - open_main_item.removeClass("open"); - } - var clicking_main_bar = container.parents("#top").length > 0; - var clicking_hamburger = this === $('.hamburger')[0]; - if (clicking_main_bar && !clicking_hamburger) { - open_main_item = container.hasClass('open') - ? container : null; - } - return false; + if (open_main_item !== container && open_main_item !== null) { + open_main_item.classList.remove('open'); + } + var clicking_main_bar = parentsMatching(container, '#top').length > 0; + var hamburger = document.querySelector('.hamburger'); + var clicking_hamburger = toggle === hamburger; + if (clicking_main_bar && !clicking_hamburger) { + open_main_item = container.classList.contains('open') ? container : null; + } + e.preventDefault(); + return false; + }); }); - $('html').click(function(e) { - var clicking_main_bar = $(e.target).parents("#top").length > 0; + document.querySelector('html').addEventListener('click', function(e) { + var clicking_main_bar = parentsMatching(e.target, '#top').length > 0; if (clicking_main_bar) return; if (open_main_item !== null) { - open_main_item.removeClass('open'); + open_main_item.classList.remove('open'); } open_main_item = null; }); } - $('.search-container .expand-toggle').click(function() { - $('#search-query input').focus(); + document.querySelectorAll('.search-container .expand-toggle').forEach(function(t) { + t.addEventListener('click', function() { + var input = document.querySelector('#search-query input'); + if (input) input.focus(); + }); }); // Insert the show/hide button if the contents section exists - $('.page-contents-header').append('[hide]'); - - // Event to hide or show the "contents" section when the hide button - // is clicked - $(".page-contents-header a").click(function () { - var elem = $('.page-contents > ol'); + document.querySelectorAll('.page-contents-header').forEach(function(h) { + var span = document.createElement('span'); + span.innerHTML = '[hide]'; + h.appendChild(span); + }); - if (elem.is(':visible')) { - $(this).text("[show]"); - elem.hide(); - } else { - $(this).text("[hide]"); - elem.show(); - } + // Event to hide or show the "contents" section when the hide button is clicked + document.querySelectorAll('.page-contents-header a').forEach(function(a) { + a.addEventListener('click', function() { + var elem = document.querySelector('.page-contents > ol'); + if (!elem) return; + var visible = elem.offsetParent !== null && elem.style.display !== 'none'; + if (visible) { + a.textContent = '[show]'; + elem.style.display = 'none'; + } else { + a.textContent = '[hide]'; + elem.style.display = ''; + } + }); }); }); -})(jQuery); +})(); diff --git a/js/jquery-3.7.1.min.js b/js/jquery-3.7.1.min.js deleted file mode 100644 index 7f37b5d991..0000000000 --- a/js/jquery-3.7.1.min.js +++ /dev/null @@ -1,2 +0,0 @@ -/*! jQuery v3.7.1 | (c) OpenJS Foundation and other contributors | jquery.org/license */ -!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(ie,e){"use strict";var oe=[],r=Object.getPrototypeOf,ae=oe.slice,g=oe.flat?function(e){return oe.flat.call(e)}:function(e){return oe.concat.apply([],e)},s=oe.push,se=oe.indexOf,n={},i=n.toString,ue=n.hasOwnProperty,o=ue.toString,a=o.call(Object),le={},v=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType&&"function"!=typeof e.item},y=function(e){return null!=e&&e===e.window},C=ie.document,u={type:!0,src:!0,nonce:!0,noModule:!0};function m(e,t,n){var r,i,o=(n=n||C).createElement("script");if(o.text=e,t)for(r in u)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function x(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[i.call(e)]||"object":typeof e}var t="3.7.1",l=/HTML$/i,ce=function(e,t){return new ce.fn.init(e,t)};function c(e){var t=!!e&&"length"in e&&e.length,n=x(e);return!v(e)&&!y(e)&&("array"===n||0===t||"number"==typeof t&&0+~]|"+ge+")"+ge+"*"),x=new RegExp(ge+"|>"),j=new RegExp(g),A=new RegExp("^"+t+"$"),D={ID:new RegExp("^#("+t+")"),CLASS:new RegExp("^\\.("+t+")"),TAG:new RegExp("^("+t+"|[*])"),ATTR:new RegExp("^"+p),PSEUDO:new RegExp("^"+g),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+ge+"*(even|odd|(([+-]|)(\\d*)n|)"+ge+"*(?:([+-]|)"+ge+"*(\\d+)|))"+ge+"*\\)|)","i"),bool:new RegExp("^(?:"+f+")$","i"),needsContext:new RegExp("^"+ge+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+ge+"*((?:-\\d)?\\d*)"+ge+"*\\)|)(?=[^-]|$)","i")},N=/^(?:input|select|textarea|button)$/i,q=/^h\d$/i,L=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,H=/[+~]/,O=new RegExp("\\\\[\\da-fA-F]{1,6}"+ge+"?|\\\\([^\\r\\n\\f])","g"),P=function(e,t){var n="0x"+e.slice(1)-65536;return t||(n<0?String.fromCharCode(n+65536):String.fromCharCode(n>>10|55296,1023&n|56320))},M=function(){V()},R=J(function(e){return!0===e.disabled&&fe(e,"fieldset")},{dir:"parentNode",next:"legend"});try{k.apply(oe=ae.call(ye.childNodes),ye.childNodes),oe[ye.childNodes.length].nodeType}catch(e){k={apply:function(e,t){me.apply(e,ae.call(t))},call:function(e){me.apply(e,ae.call(arguments,1))}}}function I(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&(V(e),e=e||T,C)){if(11!==p&&(u=L.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return k.call(n,a),n}else if(f&&(a=f.getElementById(i))&&I.contains(e,a)&&a.id===i)return k.call(n,a),n}else{if(u[2])return k.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&e.getElementsByClassName)return k.apply(n,e.getElementsByClassName(i)),n}if(!(h[t+" "]||d&&d.test(t))){if(c=t,f=e,1===p&&(x.test(t)||m.test(t))){(f=H.test(t)&&U(e.parentNode)||e)==e&&le.scope||((s=e.getAttribute("id"))?s=ce.escapeSelector(s):e.setAttribute("id",s=S)),o=(l=Y(t)).length;while(o--)l[o]=(s?"#"+s:":scope")+" "+Q(l[o]);c=l.join(",")}try{return k.apply(n,f.querySelectorAll(c)),n}catch(e){h(t,!0)}finally{s===S&&e.removeAttribute("id")}}}return re(t.replace(ve,"$1"),e,n,r)}function W(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function F(e){return e[S]=!0,e}function $(e){var t=T.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function B(t){return function(e){return fe(e,"input")&&e.type===t}}function _(t){return function(e){return(fe(e,"input")||fe(e,"button"))&&e.type===t}}function z(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&R(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function X(a){return F(function(o){return o=+o,F(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function U(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}function V(e){var t,n=e?e.ownerDocument||e:ye;return n!=T&&9===n.nodeType&&n.documentElement&&(r=(T=n).documentElement,C=!ce.isXMLDoc(T),i=r.matches||r.webkitMatchesSelector||r.msMatchesSelector,r.msMatchesSelector&&ye!=T&&(t=T.defaultView)&&t.top!==t&&t.addEventListener("unload",M),le.getById=$(function(e){return r.appendChild(e).id=ce.expando,!T.getElementsByName||!T.getElementsByName(ce.expando).length}),le.disconnectedMatch=$(function(e){return i.call(e,"*")}),le.scope=$(function(){return T.querySelectorAll(":scope")}),le.cssHas=$(function(){try{return T.querySelector(":has(*,:jqfake)"),!1}catch(e){return!0}}),le.getById?(b.filter.ID=function(e){var t=e.replace(O,P);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&C){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(O,P);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&C){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):t.querySelectorAll(e)},b.find.CLASS=function(e,t){if("undefined"!=typeof t.getElementsByClassName&&C)return t.getElementsByClassName(e)},d=[],$(function(e){var t;r.appendChild(e).innerHTML="",e.querySelectorAll("[selected]").length||d.push("\\["+ge+"*(?:value|"+f+")"),e.querySelectorAll("[id~="+S+"-]").length||d.push("~="),e.querySelectorAll("a#"+S+"+*").length||d.push(".#.+[+~]"),e.querySelectorAll(":checked").length||d.push(":checked"),(t=T.createElement("input")).setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),r.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&d.push(":enabled",":disabled"),(t=T.createElement("input")).setAttribute("name",""),e.appendChild(t),e.querySelectorAll("[name='']").length||d.push("\\["+ge+"*name"+ge+"*="+ge+"*(?:''|\"\")")}),le.cssHas||d.push(":has"),d=d.length&&new RegExp(d.join("|")),l=function(e,t){if(e===t)return a=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!le.sortDetached&&t.compareDocumentPosition(e)===n?e===T||e.ownerDocument==ye&&I.contains(ye,e)?-1:t===T||t.ownerDocument==ye&&I.contains(ye,t)?1:o?se.call(o,e)-se.call(o,t):0:4&n?-1:1)}),T}for(e in I.matches=function(e,t){return I(e,null,null,t)},I.matchesSelector=function(e,t){if(V(e),C&&!h[t+" "]&&(!d||!d.test(t)))try{var n=i.call(e,t);if(n||le.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){h(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(O,P),e[3]=(e[3]||e[4]||e[5]||"").replace(O,P),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||I.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&I.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return D.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&j.test(n)&&(t=Y(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(O,P).toLowerCase();return"*"===e?function(){return!0}:function(e){return fe(e,t)}},CLASS:function(e){var t=s[e+" "];return t||(t=new RegExp("(^|"+ge+")"+e+"("+ge+"|$)"))&&s(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=I.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function T(e,n,r){return v(n)?ce.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?ce.grep(e,function(e){return e===n!==r}):"string"!=typeof n?ce.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(ce.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||k,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:S.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof ce?t[0]:t,ce.merge(this,ce.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:C,!0)),w.test(r[1])&&ce.isPlainObject(t))for(r in t)v(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=C.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):v(e)?void 0!==n.ready?n.ready(e):e(ce):ce.makeArray(e,this)}).prototype=ce.fn,k=ce(C);var E=/^(?:parents|prev(?:Until|All))/,j={children:!0,contents:!0,next:!0,prev:!0};function A(e,t){while((e=e[t])&&1!==e.nodeType);return e}ce.fn.extend({has:function(e){var t=ce(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,Ce=/^$|^module$|\/(?:java|ecma)script/i;xe=C.createDocumentFragment().appendChild(C.createElement("div")),(be=C.createElement("input")).setAttribute("type","radio"),be.setAttribute("checked","checked"),be.setAttribute("name","t"),xe.appendChild(be),le.checkClone=xe.cloneNode(!0).cloneNode(!0).lastChild.checked,xe.innerHTML="",le.noCloneChecked=!!xe.cloneNode(!0).lastChild.defaultValue,xe.innerHTML="",le.option=!!xe.lastChild;var ke={thead:[1,"","
    "],col:[2,"","
    "],tr:[2,"","
    "],td:[3,"","
    "],_default:[0,"",""]};function Se(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&fe(e,t)?ce.merge([e],n):n}function Ee(e,t){for(var n=0,r=e.length;n",""]);var je=/<|&#?\w+;/;function Ae(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d\s*$/g;function Re(e,t){return fe(e,"table")&&fe(11!==t.nodeType?t:t.firstChild,"tr")&&ce(e).children("tbody")[0]||e}function Ie(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function We(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Fe(e,t){var n,r,i,o,a,s;if(1===t.nodeType){if(_.hasData(e)&&(s=_.get(e).events))for(i in _.remove(t,"handle events"),s)for(n=0,r=s[i].length;n").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),C.head.appendChild(r[0])},abort:function(){i&&i()}}});var Jt,Kt=[],Zt=/(=)\?(?=&|$)|\?\?/;ce.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Kt.pop()||ce.expando+"_"+jt.guid++;return this[e]=!0,e}}),ce.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Zt.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Zt.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=v(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Zt,"$1"+r):!1!==e.jsonp&&(e.url+=(At.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||ce.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=ie[r],ie[r]=function(){o=arguments},n.always(function(){void 0===i?ce(ie).removeProp(r):ie[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,Kt.push(r)),o&&v(i)&&i(o[0]),o=i=void 0}),"script"}),le.createHTMLDocument=((Jt=C.implementation.createHTMLDocument("").body).innerHTML="
    ",2===Jt.childNodes.length),ce.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(le.createHTMLDocument?((r=(t=C.implementation.createHTMLDocument("")).createElement("base")).href=C.location.href,t.head.appendChild(r)):t=C),o=!n&&[],(i=w.exec(e))?[t.createElement(i[1])]:(i=Ae([e],t,o),o&&o.length&&ce(o).remove(),ce.merge([],i.childNodes)));var r,i,o},ce.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1").append(ce.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},ce.expr.pseudos.animated=function(t){return ce.grep(ce.timers,function(e){return t===e.elem}).length},ce.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=ce.css(e,"position"),c=ce(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=ce.css(e,"top"),u=ce.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),v(t)&&(t=t.call(e,n,ce.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},ce.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){ce.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===ce.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===ce.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=ce(e).offset()).top+=ce.css(e,"borderTopWidth",!0),i.left+=ce.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-ce.css(r,"marginTop",!0),left:t.left-i.left-ce.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===ce.css(e,"position"))e=e.offsetParent;return e||J})}}),ce.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;ce.fn[t]=function(e){return M(this,function(e,t,n){var r;if(y(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),ce.each(["top","left"],function(e,n){ce.cssHooks[n]=Ye(le.pixelPosition,function(e,t){if(t)return t=Ge(e,n),_e.test(t)?ce(e).position()[n]+"px":t})}),ce.each({Height:"height",Width:"width"},function(a,s){ce.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){ce.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return M(this,function(e,t,n){var r;return y(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?ce.css(e,t,i):ce.style(e,t,n,i)},s,n?e:void 0,n)}})}),ce.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){ce.fn[t]=function(e){return this.on(t,e)}}),ce.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},hover:function(e,t){return this.on("mouseenter",e).on("mouseleave",t||e)}}),ce.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){ce.fn[n]=function(e,t){return 0" + e.name + ""; }); - $("h1").after("
    "); + var h1 = document.querySelector("h1"); + if (!h1) return; + var container = document.createElement("div"); + container.className = "version-changer-container fa-select"; + container.innerHTML = ""; + h1.parentNode.insertBefore(container, h1.nextSibling); // attach event listener to select box -> change URL - $("#version-changer").change(function(){ - var selected = parseInt($(this).find("option:selected").val()); + var changer = document.getElementById("version-changer"); + changer.addEventListener("change", function() { + var selected = parseInt(changer.value); var option = versions[selected]; if (!option.selected) { window.location.href = option.url; diff --git a/js/platform-downloads.js b/js/platform-downloads.js index 48872e1719..df83c49e11 100644 --- a/js/platform-downloads.js +++ b/js/platform-downloads.js @@ -1,10 +1,5 @@ (function() { - var script = document.currentScript; - if (!script) { // polyfill for IE - var scripts = document.getElementsByTag('script'); - script = scripts[scripts.length - 1]; // depends on synchronous load - } - var latest = script.dataset.latest, + var latest = document.currentScript.dataset.latest, platform = navigator.platform.toLowerCase(); var model = 64; @@ -16,14 +11,12 @@ files = [{name: 'dmd-' + latest, suffix: '.exe', text: 'Windows Installer'}]; else if (platform.indexOf('mac') != -1) files = [{name: 'dmd.' + latest, suffix: '.dmg', text: 'DMG File'}]; - else if (model == null) // platforms with multiple archs follow - return; else if (platform.indexOf('linux') != -1) files = [{name: 'dmd_' + latest + '-0_' + (model == 64 ? 'amd64' : 'i386'), suffix: '.deb', text: 'DEB File'}, {name: 'dmd-' + latest + '-0.fedora.' + (model == 64 ? 'x86_64' : 'i386'), suffix: '.rpm', text: 'RPM File'} ]; else if (platform.indexOf('freebsd') != -1) - files = [{name: 'dmd.' + latest + '.freebsd-' + model.toString(), suffix: '.tar.xz', text: 'Compressed Archive'}]; + files = [{name: 'dmd.' + latest + '.freebsd-' + model, suffix: '.tar.xz', text: 'Compressed Archive'}]; else return; @@ -37,7 +30,13 @@ html = '
    ' + html + '
    '; } - var btn = $('.download a.btn'); - btn.before(html); - btn.text('Other Downloads'); + var btn = document.querySelector('.download a.btn'); + if (btn) { + var tmp = document.createElement('div'); + tmp.innerHTML = html; + while (tmp.firstChild) { + btn.parentNode.insertBefore(tmp.firstChild, btn); + } + btn.textContent = 'Other Downloads'; + } })(); diff --git a/js/run.js b/js/run.js index 4c5b81d73b..7081f9a006 100644 --- a/js/run.js +++ b/js/run.js @@ -1,188 +1,83 @@ /** -Runnable examples functionality +Runnable examples functionality. -Copyright: 2012 by Digital Mars +Replaces
     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 for 
     elements with class=d_code.
    -    
    ...
    blocks are generated by DDOC example sections. -2. Iterate each pre element and apply our custom form, replacing default
     block
    -3. Get text from original 
     block, 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 next 
     element 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
    ' @@ -217,15 +110,14 @@ $(document).ready(function() + '
    '; } - 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 = '
    '+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 = '
    ' + '
    ' + '
    '+orig+'
    ' @@ -72,30 +72,34 @@ $(document).ready(function() + '' + '
    ' + '
    ' - + '
    Edit
    ' - + '
    Run
    ' - + '' - + '
    Open in IDE
    ' + + '
    Edit
    ' + + '
    Run
    ' + + '' + + '
    Open in IDE
    ' + '
    ' + '
    Application output
    Running...
    ' - + '
    ' - ); - }); + + '
    '; + + 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("

    " + 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 += '' + contributor.login + ''; - 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))