From f740471a19faae5f1b1a32abd884454c252f02fe Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=A9mie=20Astor?= Date: Sat, 3 Apr 2021 15:20:16 +0200 Subject: [PATCH] :art: Use playground --- .github/workflows/build.yml | 4 - .gitignore | 2 +- book.toml | 4 + docs/Contributing/ContributingCode.mdr | 7 +- docs/Overview/First_Steps/InstallingGwion.mdr | 13 +- docs/Overview/Make.mdr | 7 - docs/Overview/declaration.mdr | 15 +- docs/README.mdr | 9 +- docs/Reference/ControlFlow/ForLoop.mdr | 25 +- docs/Reference/ControlFlow/Repeat.mdr | 10 +- docs/Reference/ControlFlow/whileuntil.mdr | 10 +- docs/Reference/Functions/Lambdas.mdr | 15 +- docs/Reference/Functions/README.mdr | 5 +- docs/Reference/Functions/Variadic.mdr | 5 +- docs/Reference/Types/Enums.mdr | 5 +- docs/Reference/Types/Typedefs.mdr | 12 +- docs/Reference/Types/Unions.mdr | 4 +- docs/editor_mine.js | 26 + docs/mode-gwion.js | 250 ++++++++ scripts/mdr2mdbook.sh | 2 + theme/book.js | 574 ++++++++++++++++++ theme/index.hbs | 307 ++++++++++ 22 files changed, 1217 insertions(+), 94 deletions(-) delete mode 100644 docs/Overview/Make.mdr create mode 100644 docs/editor_mine.js create mode 100644 docs/mode-gwion.js create mode 100644 theme/book.js create mode 100644 theme/index.hbs diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index daf6e983..d7ac6ee8 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -11,10 +11,6 @@ jobs: steps: - uses: actions/checkout@v1 name: Checkout - - uses: actions/setup-python@v1 - name: Setup Python - - uses: actions/setup-ruby@v1 - name: Setup Ruby - name: Dependencies run: bash scripts/update.sh diff --git a/.gitignore b/.gitignore index 04a43765..a34cbd92 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ -src +#src book log *.gw diff --git a/book.toml b/book.toml index 1ee37e00..2d0108bf 100644 --- a/book.toml +++ b/book.toml @@ -19,3 +19,7 @@ use-boolean-and = true boost-title = 3 boost-hierarchy = 2 boost-paragraph = 1 + +[output.html.playground] +line-numbers= false +editable = true diff --git a/docs/Contributing/ContributingCode.mdr b/docs/Contributing/ContributingCode.mdr index 7a775146..ba63ebc5 100644 --- a/docs/Contributing/ContributingCode.mdr +++ b/docs/Contributing/ContributingCode.mdr @@ -18,20 +18,17 @@ You can do this through the github site, or command-line tools like `gh` or `hub Clone the url of your fork ``` sh -git clone https://github.com//gwion +git clone --recursive https://github.com//Gwion ``` ### Set up the project -``` sh -git submodule update --init util ast -``` ### Edit some files Edit some files with your favorite text editor ``` sh -cd gwion +cd Gwion vim src/path/to/file ``` diff --git a/docs/Overview/First_Steps/InstallingGwion.mdr b/docs/Overview/First_Steps/InstallingGwion.mdr index 4107a178..072223cf 100644 --- a/docs/Overview/First_Steps/InstallingGwion.mdr +++ b/docs/Overview/First_Steps/InstallingGwion.mdr @@ -2,24 +2,17 @@ ## Get the sources -The source is accessible on [github](https:#!github.com). +The source is accessible on [github](https://github.com). Provided you have git installed, you can get it with: ``` sh -git clone https://github.com/Gwion/gwion +git clone --recursive https://github.com/Gwion/Gwion ``` then change to the source directory ``` sh -cd gwion -``` - -### Don't forget submodules - -You'll need the sources for all base module -``` sh -git submodule update --init util ast +cd Gwion ``` > At this point, you may want to configure the build. diff --git a/docs/Overview/Make.mdr b/docs/Overview/Make.mdr deleted file mode 100644 index 45a5452d..00000000 --- a/docs/Overview/Make.mdr +++ /dev/null @@ -1,7 +0,0 @@ -# Makefile - -## Basic operations - -## translations - -## Docs diff --git a/docs/Overview/declaration.mdr b/docs/Overview/declaration.mdr index 04b83560..5bba1a98 100644 --- a/docs/Overview/declaration.mdr +++ b/docs/Overview/declaration.mdr @@ -3,31 +3,28 @@ ## Basics Declaring a primitive or an object is quite straight forward: -@``` decl0.gw +```gwion,editable var int i; var Object o; <<< i, " ", o >>>; -@``` -@hide make -s decl0.test +``` ## Declaring a reference -@``` decl1.gw +```gwion,editable late Object object_ref; <<< "Reference points to no object yet: ", object_ref >>>; new Object => object_ref; <<< "But now it does: ", object_ref >>>; -@``` -@hide make -s decl1.test +``` ## Arrays ### array as refs -@``` decl2.gw +```gwion,editable var int array_ref[]; <<< array_ref >>>; new int[2] => array_ref; <<< array_ref >>>; -@``` -@hide make -s decl2.test +``` diff --git a/docs/README.mdr b/docs/README.mdr index bdd9742b..d640639e 100644 --- a/docs/README.mdr +++ b/docs/README.mdr @@ -1,6 +1,6 @@ # Welcome to Gwion -:gwion: is a strongly timed programming language for making music. +gwion is a strongly timed programming language for making music. It is strongly influenced by [chuck](http://chuck.stanford.edu/), but adds a bunch of high-level features: templating, first-class functions and more. @@ -13,12 +13,11 @@ We are currently looking for contributions, you can learn how to make some [here ## And now for the hello world -Here is the piece of code you're waiting for :tada:: +Here is the piece of code you're waiting for: -@```helloworld.gw +```gwion,editable <<< "Hello, World!" >>>; -@``` -@hide make -s CONTAINS="Hello, World!" helloworld.test +``` ## (Bag of) Features diff --git a/docs/Reference/ControlFlow/ForLoop.mdr b/docs/Reference/ControlFlow/ForLoop.mdr index bb7311b5..69a44eaf 100644 --- a/docs/Reference/ControlFlow/ForLoop.mdr +++ b/docs/Reference/ControlFlow/ForLoop.mdr @@ -2,25 +2,23 @@ **For** loops in Gwion is pretty similar to classic **C** syntax ## basic loops -@``` forloop0.gw +```gwion,editable for(var int i; i < 3; ++i) <<< i >>>; -@``` -@hide make -s forloop0.test +``` It also works with a block of code. -@``` forloop2.gw +```gwion,editable for(var int i; i < 3; ++i) { i/2 => var float f1; i/2. => var float f2; <<< i, " " , f1, " ", f2 >>>; } -@``` -@hide make -s forloop2.test +``` ## Nested Loops -@``` forloop3.gw +```gwion,editable var int array[3][4]; for(var int i; i < 3; ++i) { @@ -28,26 +26,24 @@ for(var int i; i < 3; ++i) { <<< array[i][j] >>>; } } -@``` -@hide make -s forloop3.test +``` ### Auto Loops #### Simple auto loop -@``` forloop4.gw +```gwion,editable var int array[2][3]; foreach(a: array) { <<< a >>>; foreach(b: a) <<< b >>>; } -@``` -@hide make -s forloop4.test +``` ### Auto Pointer loop If you want to change it the value in the array, you need a pointer -@``` forloop5.gw +``` var int array[2][3]; var int i; foreach(a: array) { @@ -58,5 +54,4 @@ foreach(a: array) { foreach(b: a) <<< b >>>; } -@``` -@hide make -s forloop5.test +``` diff --git a/docs/Reference/ControlFlow/Repeat.mdr b/docs/Reference/ControlFlow/Repeat.mdr index a15625a4..21659623 100644 --- a/docs/Reference/ControlFlow/Repeat.mdr +++ b/docs/Reference/ControlFlow/Repeat.mdr @@ -4,21 +4,19 @@ The easiest way to do an action repeatidly in Gwion is, ... the **repeat** keywo ## Basic example -@``` repeat.gw +```gwion,editable repeat(3) <<< "Hello, world!" >>>; -@``` -@hide make -s CONTAINS="Hello" repeat.test +``` ## Block example of course this also works with a block code. -@``` repeat2.gw +```gwion,editable repeat(3) { maybe ? "You" : "Me" => var string s; <<< "Hello, ", s, "!" >>>; } -@``` -@hide make -s CONTAINS="Hello" repeat2.test +``` diff --git a/docs/Reference/ControlFlow/whileuntil.mdr b/docs/Reference/ControlFlow/whileuntil.mdr index e352cc72..480d69f0 100644 --- a/docs/Reference/ControlFlow/whileuntil.mdr +++ b/docs/Reference/ControlFlow/whileuntil.mdr @@ -1,23 +1,21 @@ # While Loops -@``` while0.gw +```gwion,editable while(true) { if(maybe) break; <<< "running..." >>>; } -@``` -@hide make -s while0.test +``` well this may output nothing... lets try -@``` while1.gw +```gwion,editable <<< maybe >>>; do{ if(maybe) break; <<< "running..." >>>; } while(true); -@``` -@hide make -s while1.test +``` diff --git a/docs/Reference/Functions/Lambdas.mdr b/docs/Reference/Functions/Lambdas.mdr index 8c234bac..86ba4210 100644 --- a/docs/Reference/Functions/Lambdas.mdr +++ b/docs/Reference/Functions/Lambdas.mdr @@ -10,28 +10,25 @@ The syntax to create them is simple: ``` You can even use it to ### Call a function just once -@``` lambda_call0.gw +```gwion,editable \ i { <<< "passed '", i, "'" >>>; }(3); -@``` -@hide make -s CONTAINS="passed '3'" lambda_call0.test +``` ## Use case ### Passing to a function pointer -@``` lambda_fptr0.gw +```gwion,editable funcdef void fptr_t(int); \ i { <<< "passed '", i, "'" >>>; } => var fptr_t fptr; fptr(4); -@``` -@hide make -s CONTAINS="passed '4'" lambda_fptr0.test +``` ### As Argument to Functions -@``` lambda_args0.gw +```gwion,editable funcdef void fptr_t(int); fun void test(fptr_t fptr) { fptr(5); } test(\ i { <<< "passed '", i, "'" >>>; }); -@``` -@hide make -s CONTAINS="passed '5'" lambda_args0.test +``` diff --git a/docs/Reference/Functions/README.mdr b/docs/Reference/Functions/README.mdr index 8fd1bb98..80fb62b9 100644 --- a/docs/Reference/Functions/README.mdr +++ b/docs/Reference/Functions/README.mdr @@ -2,7 +2,7 @@ ## a simple (commented example) -@``` function0.gw +```gwion,editable #! declare function 'test_function' #! with return type int #! taking an int as argument @@ -15,5 +15,4 @@ fun int test_function(int arg) { <<< test_function(0) >>>; #! or use alternate syntax <<< 1 => test_function >>>; -@``` -@hide make -s function0.test +``` diff --git a/docs/Reference/Functions/Variadic.mdr b/docs/Reference/Functions/Variadic.mdr index b53da62f..44f95e36 100644 --- a/docs/Reference/Functions/Variadic.mdr +++ b/docs/Reference/Functions/Variadic.mdr @@ -5,7 +5,7 @@ Well, a function that takes a fixed number of arguments, and additionnal ones. ## a simple example -@``` variadic.gw +```gwion,editable fun void variadic_test(int i, ...) { <<< "first argument is ", i >>>; varloop vararg { @@ -15,5 +15,4 @@ fun void variadic_test(int i, ...) { variadic_test(1); variadic_test(1, 2); variadic_test(1, 2, 3); -@``` -@hide make -s variadic.test +``` diff --git a/docs/Reference/Types/Enums.mdr b/docs/Reference/Types/Enums.mdr index ed1e3ab7..35802b58 100644 --- a/docs/Reference/Types/Enums.mdr +++ b/docs/Reference/Types/Enums.mdr @@ -9,13 +9,12 @@ you can read about those You use an enum like this -@``` enum0.gw +```gwion,editable enum Optionnal_name { zero, one, two }; <<< zero, one, two >>>; -@``` -@hide make -s enum0.test +``` ## Storage and access Specifiers diff --git a/docs/Reference/Types/Typedefs.mdr b/docs/Reference/Types/Typedefs.mdr index 332cde61..3a26421d 100644 --- a/docs/Reference/Types/Typedefs.mdr +++ b/docs/Reference/Types/Typedefs.mdr @@ -2,27 +2,27 @@ Create an alias for a previously defined type. -@``` typedef_simple.gw +```gwion,editable typedef int MyInt; var MyInt i; <<< i >>>; <<< i $ int >>>; -@``` +``` Aliases can also point to an array type -@``` typedef_array.gw +```gwion,editable typedef float[3] Point; var Point p; foreach(a : p) <<< a >>>; -@``` +``` Aliases can be used to refer to a type family -@``` typedef_tmpl.gw +```gwion,editable typedef Ptr:[int] IntPtr; var IntPtr int_ptr; <<< int_ptr >>>; -@``` +``` diff --git a/docs/Reference/Types/Unions.mdr b/docs/Reference/Types/Unions.mdr index 128c6257..9c39ad55 100644 --- a/docs/Reference/Types/Unions.mdr +++ b/docs/Reference/Types/Unions.mdr @@ -3,11 +3,11 @@ Union store their component in the same memory space. For more infomations, see [here](https://en.wikipedia.org/wiki/Union_type). -@``` base_union +```gwion,editable union U { int a; float f; Object o; }; -@``` +``` diff --git a/docs/editor_mine.js b/docs/editor_mine.js new file mode 100644 index 00000000..b9b39a73 --- /dev/null +++ b/docs/editor_mine.js @@ -0,0 +1,26 @@ +"use strict"; +window.editors = []; +(function(editors) { + if (typeof(ace) === 'undefined' || !ace) { + return; + } + Array.from(document.querySelectorAll('.editable')).forEach(function(editable) { + let editor = ace.edit(editable); + editor.setOptions({ + theme: 'ace/theme/tomorrow_night', + mode: 'ace/mode/gwion' + }); + + editable.addEventListener('mouseenter', e => { + editor.setOptions({ + highlightActiveLine: true + }); + }); + editable.addEventListener('mouseleave', e => { + editor.setOptions({ + highlightActiveLine: false + }); + }); + + }); +})(window.editors); diff --git a/docs/mode-gwion.js b/docs/mode-gwion.js new file mode 100644 index 00000000..7fb88ce6 --- /dev/null +++ b/docs/mode-gwion.js @@ -0,0 +1,250 @@ +ace.define("ace/mode/gwion_highlight_rules", ["require", "exports", "module", "ace/lib/oop", "ace/mode/text_highlight_rules"], function(e, t, n) { + "use strict"; + var interp = 0; + var r = e("../lib/oop") + , i = e("./text_highlight_rules").TextHighlightRules + , s = /\\(?:[nrt0'"\\]|x[\da-fA-F]{2}|u\{[\da-fA-F]{6}\})/.source + , o = function() { + this.$rules = { + start: [{ + token: "variable.other.source.gwion", + regex: "'[a-zA-Z_][a-zA-Z0-9_]*" + }, { + token: "string.quoted.single.source.gwion", + regex: "'(?:[^'\\\\]|" + s + ")'" + }, { + token: "identifier", + regex: /r#[a-zA-Z_][a-zA-Z0-9_]*\b/ + }, { + stateName: "bracketedComment", + onMatch: function(e, t, n) { + return n.unshift(this.next, e.length - 1, t), + "string.quoted.raw.source.gwion" + }, + regex: /r#*"/, + next: [{ + onMatch: function(e, t, n) { + var r = "string.quoted.raw.source.gwion"; + return e.length >= n[1] ? (e.length > n[1] && (r = "invalid"), + n.shift(), + n.shift(), + this.next = n.shift()) : this.next = "", + r + }, + regex: /"#*/, + next: "start" + }, { + defaultToken: "string.quoted.raw.source.gwion" + }] + }, { + token: "string.quoted.double.source.gwion", + regex: '"', + push: [{ + token: "string.quoted.double.source.gwion", + regex: '"', + next: "pop" + }, { + token: "constant.character.escape.source.gwion", + regex: s + }, { + defaultToken: "string.quoted.double.source.gwion" + }] + }, { + token: ["keyword.source.gwion", "text", "entity.name.function.source.gwion"], + regex: "\\b(fn)(\\s+)((?:r#)?[a-zA-Z_][a-zA-Z0-9_]*)" + }, { + token: "support.constant", + regex: "\\b[a-zA-Z_][\\w\\d]*::" + }, { + token: "keyword.source.gwion", + regex: "\\b(?:abstract|defer|repeat|foreach|break|continue|const|var|late|do|else|enum|for|final|if|extends|match|case|private|protect|global|return|self|static|public|class|struct|fun|operator|funcdef|trait|union|where|when|while|new)\\b" + }, { + token: "storage.type.source.gwion", + regex: "\\b(?:Self|int|float|string|Event|Object|bool|Option|Ref|Array)\\b" + }, { + token: "variable.language.source.gwion", + regex: "\\b(?:self|this|me|adc|dac)\\b" + }, { + token: "comment.line.doc.source.gwion", + regex: "#!!.*$" + }, { + token: "comment.block.source.gwion", + regex: "#!.*!#", + }, { + token: "comment.line.double-dash.source.gwion", + regex: "#!.*$" + }, { + token: "keyword.operator", + regex: /\$|[-=]>|[-+%^=!&|<>~:]=?|[*/](?![*/>])=?/ + }, { + token: "punctuation.operator", + regex: /[?:,;.]/ + }, { + token: "paren.lparen", + regex: /[\[({]/ + }, { + token: "paren.rparen", + regex: /[\])}]/ + }, { + token: "constant.language.source.gwion", + regex: "\\b(?:true|false|maybe|None)\\b" + }, { + token: "support.constant.source.gwion", + regex: "\\b(?:pi|EXIT_FAILURE|EXIT_SUCCESS|RAND_MAX|EOF|SEEK_SET|SEEK_CUR|SEEK_END|_IOFBF|_IONBF|_IOLBF|BUFSIZ|FOPEN_MAX|FILENAME_MAX|L_tmpnam|TMP_MAX|O_RDONLY|O_WRONLY|O_RDWR|O_APPEND|O_CREAT|O_EXCL|O_TRUNC|S_IFIFO|S_IFCHR|S_IFBLK|S_IFDIR|S_IFREG|S_IFMT|S_IEXEC|S_IWRITE|S_IREAD|S_IRWXU|S_IXUSR|S_IWUSR|S_IRUSR|F_OK|R_OK|W_OK|X_OK|STDIN_FILENO|STDOUT_FILENO|STDERR_FILENO)\\b" + }, { + token: "meta.preprocessor.source.gwion", + regex : "#\\s*(?:include|require|pragma|__line__|__file__|__func__|ifdef|undef|define|undef)\\b" + }, { + token: "constant.numeric.source.gwion", + regex: /\b(?:0x[a-fA-F0-9_]+|0o[0-7_]+|0b[01_]+|[0-9][0-9_]*(?!\.))(?:[iu](?:size|8|16|32|64|128))?\b/ + }, { + token: "constant.numeric.source.gwion", + regex: /\b(?:[0-9][0-9_]*)(?:\.[0-9][0-9_]*)?(?:[Ee][+-][0-9][0-9_]*)?(?:f32|f64)?\b/ + }] + }, + this.normalizeRules() + }; + o.metaData = { + fileTypes: ["rs", "rc"], + foldingStartMarker: "^.*\\bfn\\s*(\\w+\\s*)?\\([^\\)]*\\)(\\s*\\{[^\\}]*)?\\s*$", + foldingStopMarker: "^\\s*\\}", + name: "Rust", + scopeName: "source.gwion" + }, + r.inherits(o, i), + t.RustHighlightRules = o +}), +ace.define("ace/mode/folding/cstyle", ["require", "exports", "module", "ace/lib/oop", "ace/range", "ace/mode/folding/fold_mode"], function(e, t, n) { + "use strict"; + var r = e("../../lib/oop") + , i = e("../../range").Range + , s = e("./fold_mode").FoldMode + , o = t.FoldMode = function(e) { + e && (this.foldingStartMarker = new RegExp(this.foldingStartMarker.source.replace(/\|[^|]*?$/, "|" + e.start)), + this.foldingStopMarker = new RegExp(this.foldingStopMarker.source.replace(/\|[^|]*?$/, "|" + e.end))) + } + ; + r.inherits(o, s), + function() { + this.foldingStartMarker = /([\{\[\(])[^\}\]\)]*$|^\s*(\/\*)/, + this.foldingStopMarker = /^[^\[\{\(]*([\}\]\)])|^[\s\*]*(\*\/)/, + this.singleLineBlockCommentRe = /^\s*(\/\*).*\*\/\s*$/, + this.tripleStarBlockCommentRe = /^\s*(\/\*\*\*).*\*\/\s*$/, + this.startRegionRe = /^\s*(\/\*|\/\/)#?region\b/, + this._getFoldWidgetBase = this.getFoldWidget, + this.getFoldWidget = function(e, t, n) { + var r = e.getLine(n); + if (this.singleLineBlockCommentRe.test(r) && !this.startRegionRe.test(r) && !this.tripleStarBlockCommentRe.test(r)) + return ""; + var i = this._getFoldWidgetBase(e, t, n); + return !i && this.startRegionRe.test(r) ? "start" : i + } + , + this.getFoldWidgetRange = function(e, t, n, r) { + var i = e.getLine(n); + if (this.startRegionRe.test(i)) + return this.getCommentRegionBlock(e, i, n); + var s = i.match(this.foldingStartMarker); + if (s) { + var o = s.index; + if (s[1]) + return this.openingBracketBlock(e, s[1], n, o); + var u = e.getCommentFoldRange(n, o + s[0].length, 1); + return u && !u.isMultiLine() && (r ? u = this.getSectionRange(e, n) : t != "all" && (u = null)), + u + } + if (t === "markbegin") + return; + var s = i.match(this.foldingStopMarker); + if (s) { + var o = s.index + s[0].length; + return s[1] ? this.closingBracketBlock(e, s[1], n, o) : e.getCommentFoldRange(n, o, -1) + } + } + , + this.getSectionRange = function(e, t) { + var n = e.getLine(t) + , r = n.search(/\S/) + , s = t + , o = n.length; + t += 1; + var u = t + , a = e.getLength(); + while (++t < a) { + n = e.getLine(t); + var f = n.search(/\S/); + if (f === -1) + continue; + if (r > f) + break; + var l = this.getFoldWidgetRange(e, "all", t); + if (l) { + if (l.start.row <= s) + break; + if (l.isMultiLine()) + t = l.end.row; + else if (r == f) + break + } + u = t + } + return new i(s,o,u,e.getLine(u).length) + } + , + this.getCommentRegionBlock = function(e, t, n) { + var r = t.search(/\s*$/) + , s = e.getLength() + , o = n + , u = /^\s*(?:\/\*|\/\/|--)#?(end)?region\b/ + , a = 1; + while (++n < s) { + t = e.getLine(n); + var f = u.exec(t); + if (!f) + continue; + f[1] ? a-- : a++; + if (!a) + break + } + var l = n; + if (l > o) + return new i(o,r,l,t.length) + } + } + .call(o.prototype) +}), +ace.define("ace/mode/gwion", ["require", "exports", "module", "ace/lib/oop", "ace/mode/text", "ace/mode/gwion_highlight_rules", "ace/mode/folding/cstyle"], function(e, t, n) { + "use strict"; + var r = e("../lib/oop") + , i = e("./text").Mode + , s = e("./gwion_highlight_rules").RustHighlightRules + , o = e("./folding/cstyle").FoldMode + , u = function() { + this.HighlightRules = s, + this.foldingRules = new o, + this.$behaviour = this.$defaultBehaviour + }; + r.inherits(u, i), + function() { + this.lineCommentStart = "//", + this.blockComment = { + start: "/*", + end: "*/", + nestable: !0 + }, + this.$quotes = { + '"': '"' + }, + this.$id = "ace/mode/gwion" + } + .call(u.prototype), + t.Mode = u +}); +(function() { + ace.require(["ace/mode/gwion"], function(m) { + if (typeof module == "object" && typeof exports == "object" && module) { + module.exports = m; + } + }); +} +)(); diff --git a/scripts/mdr2mdbook.sh b/scripts/mdr2mdbook.sh index 4891e41a..edfd542a 100644 --- a/scripts/mdr2mdbook.sh +++ b/scripts/mdr2mdbook.sh @@ -27,6 +27,7 @@ doc2src() { target=$(sed 's/docs/src/' <<< $mdfile) ensure_dir $target mk_target $mdfile > $target +# mv $mdfile $target rm $mdfile } @@ -44,3 +45,4 @@ then bash scripts/summary.sh > src/SUMMARY.md fi else runall fi +cp docs/*.js src diff --git a/theme/book.js b/theme/book.js new file mode 100644 index 00000000..43a4dedb --- /dev/null +++ b/theme/book.js @@ -0,0 +1,574 @@ +"use strict"; + +// Fix back button cache problem +window.onunload = function () { }; + +// Global variable, shared between modules +function playground_text(playground) { + + let code_block = playground.querySelector("code"); + + if (window.ace && code_block.classList.contains("editable")) { + let editor = window.ace.edit(code_block); + return editor.getValue(); + } else { + return code_block.textContent; + } +} + +(function codeSnippets() { + Array.from(document.querySelectorAll(".language-gwion")).forEach((element) => { + let parent = element.parentNode; + let wrapper = document.createElement('pre'); + wrapper.className = 'playground'; + // set the wrapper as child (instead of the element) + parent.replaceChild(wrapper, element); + // set element as child of wrapper + wrapper.appendChild(element); + }); + + + function fetch_with_timeout(url, options, timeout = 60000) { + return Promise.race([ + fetch(url, options), + new Promise((_, reject) => setTimeout(() => reject(new Error('timeout')), timeout)) + ]); + } + + var playgrounds = Array.from(document.querySelectorAll(".playground")); + + function run_gwion_code(code_block) { + var result_block = code_block.querySelector(".result"); + if (!result_block) { + result_block = document.createElement('code'); + result_block.className = 'result hljs f9 b9'; + + result_block.innerHTML = `${result_block.innerHTML}` + code_block.append(result_block); + } + + let text = playground_text(code_block); + + result_block.innerText = "Running..."; + + fetch_with_timeout("https://TheGwionPlayground.fennecdjay.repl.co", { + headers: { + 'Content-Type': "text/plain", + }, + method: 'POST', + mode: 'cors', + body: text + }) + .then(response => response.json()) + .then(response => result_block.innerHTML = response) + .catch(error => result_block.innerText = "Playground Communication: " + error.message); + } + + // Syntax highlighting Configuration + hljs.configure({ + tabReplace: ' ', // 4 spaces + languages: [], // Languages used for auto-detection + }); + + let code_nodes = Array + .from(document.querySelectorAll('code')) + // Don't highlight `inline code` blocks in headers. + .filter(function (node) {return !node.parentElement.classList.contains("header"); }); + + if (window.ace) { + // language-gwion class needs to be removed for editable + // blocks or highlightjs will capture events + Array + .from(document.querySelectorAll('code.editable')) + .forEach(function (block) { + block.classList.remove('language-gwion'); + let editor = window.ace.edit(block); + editor.commands.addCommand({ + name: "run", + bindKey: { + win: "Ctrl-Enter", + mac: "Ctrl-Enter" + }, + exec: _editor => run_gwion_code(block.parentNode) + }); + }); + + Array + .from(document.querySelectorAll('code:not(.editable)')) + .forEach(function (block) { hljs.highlightBlock(block); }); + } else { + code_nodes.forEach(function (block) { hljs.highlightBlock(block); }); + } + + // Adding the hljs class gives code blocks the color css + // even if highlighting doesn't apply + code_nodes.forEach(function (block) { block.classList.add('hljs'); }); + + if (window.playground_copyable) { + Array.from(document.querySelectorAll('pre code')).forEach(function (block) { + var pre_block = block.parentNode; + if (!pre_block.classList.contains('playground')) { + var buttons = pre_block.querySelector(".buttons"); + if (!buttons) { + buttons = document.createElement('div'); + buttons.className = 'buttons'; + pre_block.insertBefore(buttons, pre_block.firstChild); + } + + var clipButton = document.createElement('button'); + clipButton.className = 'fa fa-copy clip-button'; + clipButton.title = 'Copy to clipboard'; + clipButton.setAttribute('aria-label', clipButton.title); + clipButton.innerHTML = ''; + + buttons.insertBefore(clipButton, buttons.firstChild); + } + }); + } + + // Process playground code blocks + Array.from(document.querySelectorAll(".playground")).forEach(function (pre_block) { + // Add play button + var buttons = pre_block.querySelector(".buttons"); + if (!buttons) { + buttons = document.createElement('div'); + buttons.className = 'buttons'; + pre_block.insertBefore(buttons, pre_block.firstChild); + } + + var runCodeButton = document.createElement('button'); + runCodeButton.className = 'fa fa-play play-button'; + runCodeButton.hidden = true; + runCodeButton.title = 'Run this code'; + runCodeButton.setAttribute('aria-label', runCodeButton.title); + + buttons.insertBefore(runCodeButton, buttons.firstChild); + runCodeButton.addEventListener('click', function (e) { + run_gwion_code(pre_block); + }); + + if (window.playground_copyable) { + var copyCodeClipboardButton = document.createElement('button'); + copyCodeClipboardButton.className = 'fa fa-copy clip-button'; + copyCodeClipboardButton.innerHTML = ''; + copyCodeClipboardButton.title = 'Copy to clipboard'; + copyCodeClipboardButton.setAttribute('aria-label', copyCodeClipboardButton.title); + + buttons.insertBefore(copyCodeClipboardButton, buttons.firstChild); + } + + let code_block = pre_block.querySelector("code"); + + + if (window.ace && code_block.classList.contains("editable")) { + var undoChangesButton = document.createElement('button'); + undoChangesButton.className = 'fa fa-history reset-button'; + undoChangesButton.title = 'Undo changes'; + undoChangesButton.setAttribute('aria-label', undoChangesButton.title); + + buttons.insertBefore(undoChangesButton, buttons.firstChild); + + undoChangesButton.addEventListener('click', function () { + let editor = window.ace.edit(code_block); + editor.setValue(editor.originalCode); + editor.clearSelection(); + }); + } + + const play_button = pre_block.querySelector(".play-button"); + + // skip if code is `no_run` + if (pre_block.querySelector('code').classList.contains("no_run")) { + play_button.classList.add("hidden"); + return; + } + }); +})(); + +(function themes() { + var html = document.querySelector('html'); + var themeToggleButton = document.getElementById('theme-toggle'); + var themePopup = document.getElementById('theme-list'); + var themeColorMetaTag = document.querySelector('meta[name="theme-color"]'); + var stylesheets = { + ayuHighlight: document.querySelector("[href$='ayu-highlight.css']"), + tomorrowNight: document.querySelector("[href$='tomorrow-night.css']"), + highlight: document.querySelector("[href$='highlight.css']"), + }; + + function showThemes() { + themePopup.style.display = 'block'; + themeToggleButton.setAttribute('aria-expanded', true); + themePopup.querySelector("button#" + get_theme()).focus(); + } + + function hideThemes() { + themePopup.style.display = 'none'; + themeToggleButton.setAttribute('aria-expanded', false); + themeToggleButton.focus(); + } + + function get_theme() { + var theme; + try { theme = localStorage.getItem('mdbook-theme'); } catch (e) { } + if (theme === null || theme === undefined) { + return default_theme; + } else { + return theme; + } + } + + function set_theme(theme, store = true) { + let ace_theme; + + if (theme == 'coal' || theme == 'navy') { + stylesheets.ayuHighlight.disabled = true; + stylesheets.tomorrowNight.disabled = false; + stylesheets.highlight.disabled = true; + + ace_theme = "ace/theme/tomorrow_night"; + } else if (theme == 'ayu') { + stylesheets.ayuHighlight.disabled = false; + stylesheets.tomorrowNight.disabled = true; + stylesheets.highlight.disabled = true; + ace_theme = "ace/theme/tomorrow_night"; + } else { + stylesheets.ayuHighlight.disabled = true; + stylesheets.tomorrowNight.disabled = true; + stylesheets.highlight.disabled = false; + ace_theme = "ace/theme/dawn"; + } + + setTimeout(function () { + themeColorMetaTag.content = getComputedStyle(document.body).backgroundColor; + }, 1); + + if (window.ace && window.editors) { + window.editors.forEach(function (editor) { + editor.setTheme(ace_theme); + }); + } + + var previousTheme = get_theme(); + + if (store) { + try { localStorage.setItem('mdbook-theme', theme); } catch (e) { } + } + + html.classList.remove(previousTheme); + html.classList.add(theme); + } + + // Set theme + var theme = get_theme(); + + set_theme(theme, false); + + themeToggleButton.addEventListener('click', function () { + if (themePopup.style.display === 'block') { + hideThemes(); + } else { + showThemes(); + } + }); + + themePopup.addEventListener('click', function (e) { + var theme = e.target.id || e.target.parentElement.id; + set_theme(theme); + }); + + themePopup.addEventListener('focusout', function(e) { + // e.relatedTarget is null in Safari and Firefox on macOS (see workaround below) + if (!!e.relatedTarget && !themeToggleButton.contains(e.relatedTarget) && !themePopup.contains(e.relatedTarget)) { + hideThemes(); + } + }); + + // Should not be needed, but it works around an issue on macOS & iOS: https://github.com/rust-lang/mdBook/issues/628 + document.addEventListener('click', function(e) { + if (themePopup.style.display === 'block' && !themeToggleButton.contains(e.target) && !themePopup.contains(e.target)) { + hideThemes(); + } + }); + + document.addEventListener('keydown', function (e) { + if (e.altKey || e.ctrlKey || e.metaKey || e.shiftKey) { return; } + if (!themePopup.contains(e.target)) { return; } + + switch (e.key) { + case 'Escape': + e.preventDefault(); + hideThemes(); + break; + case 'ArrowUp': + e.preventDefault(); + var li = document.activeElement.parentElement; + if (li && li.previousElementSibling) { + li.previousElementSibling.querySelector('button').focus(); + } + break; + case 'ArrowDown': + e.preventDefault(); + var li = document.activeElement.parentElement; + if (li && li.nextElementSibling) { + li.nextElementSibling.querySelector('button').focus(); + } + break; + case 'Home': + e.preventDefault(); + themePopup.querySelector('li:first-child button').focus(); + break; + case 'End': + e.preventDefault(); + themePopup.querySelector('li:last-child button').focus(); + break; + } + }); +})(); + +(function sidebar() { + var html = document.querySelector("html"); + var sidebar = document.getElementById("sidebar"); + var sidebarLinks = document.querySelectorAll('#sidebar a'); + var sidebarToggleButton = document.getElementById("sidebar-toggle"); + var sidebarResizeHandle = document.getElementById("sidebar-resize-handle"); + var firstContact = null; + + function showSidebar() { + html.classList.remove('sidebar-hidden') + html.classList.add('sidebar-visible'); + Array.from(sidebarLinks).forEach(function (link) { + link.setAttribute('tabIndex', 0); + }); + sidebarToggleButton.setAttribute('aria-expanded', true); + sidebar.setAttribute('aria-hidden', false); + try { localStorage.setItem('mdbook-sidebar', 'visible'); } catch (e) { } + } + + + var sidebarAnchorToggles = document.querySelectorAll('#sidebar a.toggle'); + + function toggleSection(ev) { + ev.currentTarget.parentElement.classList.toggle('expanded'); + } + + Array.from(sidebarAnchorToggles).forEach(function (el) { + el.addEventListener('click', toggleSection); + }); + + function hideSidebar() { + html.classList.remove('sidebar-visible') + html.classList.add('sidebar-hidden'); + Array.from(sidebarLinks).forEach(function (link) { + link.setAttribute('tabIndex', -1); + }); + sidebarToggleButton.setAttribute('aria-expanded', false); + sidebar.setAttribute('aria-hidden', true); + try { localStorage.setItem('mdbook-sidebar', 'hidden'); } catch (e) { } + } + + // Toggle sidebar + sidebarToggleButton.addEventListener('click', function sidebarToggle() { + if (html.classList.contains("sidebar-hidden")) { + var current_width = parseInt( + document.documentElement.style.getPropertyValue('--sidebar-width'), 10); + if (current_width < 150) { + document.documentElement.style.setProperty('--sidebar-width', '150px'); + } + showSidebar(); + } else if (html.classList.contains("sidebar-visible")) { + hideSidebar(); + } else { + if (getComputedStyle(sidebar)['transform'] === 'none') { + hideSidebar(); + } else { + showSidebar(); + } + } + }); + + sidebarResizeHandle.addEventListener('mousedown', initResize, false); + + function initResize(e) { + window.addEventListener('mousemove', resize, false); + window.addEventListener('mouseup', stopResize, false); + html.classList.add('sidebar-resizing'); + } + function resize(e) { + var pos = (e.clientX - sidebar.offsetLeft); + if (pos < 20) { + hideSidebar(); + } else { + if (html.classList.contains("sidebar-hidden")) { + showSidebar(); + } + pos = Math.min(pos, window.innerWidth - 100); + document.documentElement.style.setProperty('--sidebar-width', pos + 'px'); + } + } + //on mouseup remove windows functions mousemove & mouseup + function stopResize(e) { + html.classList.remove('sidebar-resizing'); + window.removeEventListener('mousemove', resize, false); + window.removeEventListener('mouseup', stopResize, false); + } + + document.addEventListener('touchstart', function (e) { + firstContact = { + x: e.touches[0].clientX, + time: Date.now() + }; + }, { passive: true }); + + document.addEventListener('touchmove', function (e) { + if (!firstContact) + return; + + var curX = e.touches[0].clientX; + var xDiff = curX - firstContact.x, + tDiff = Date.now() - firstContact.time; + + if (tDiff < 250 && Math.abs(xDiff) >= 150) { + if (xDiff >= 0 && firstContact.x < Math.min(document.body.clientWidth * 0.25, 300)) + showSidebar(); + else if (xDiff < 0 && curX < 300) + hideSidebar(); + + firstContact = null; + } + }, { passive: true }); + + // Scroll sidebar to current active section + var activeSection = document.getElementById("sidebar").querySelector(".active"); + if (activeSection) { + // https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView + activeSection.scrollIntoView({ block: 'center' }); + } +})(); + +(function chapterNavigation() { + document.addEventListener('keydown', function (e) { + if (e.altKey || e.ctrlKey || e.metaKey || e.shiftKey) { return; } + if (window.search && window.search.hasFocus()) { return; } + + switch (e.key) { + case 'ArrowRight': + e.preventDefault(); + var nextButton = document.querySelector('.nav-chapters.next'); + if (nextButton) { + window.location.href = nextButton.href; + } + break; + case 'ArrowLeft': + e.preventDefault(); + var previousButton = document.querySelector('.nav-chapters.previous'); + if (previousButton) { + window.location.href = previousButton.href; + } + break; + } + }); +})(); + +(function clipboard() { + var clipButtons = document.querySelectorAll('.clip-button'); + + function hideTooltip(elem) { + elem.firstChild.innerText = ""; + elem.className = 'fa fa-copy clip-button'; + } + + function showTooltip(elem, msg) { + elem.firstChild.innerText = msg; + elem.className = 'fa fa-copy tooltipped'; + } + + var clipboardSnippets = new ClipboardJS('.clip-button', { + text: function (trigger) { + hideTooltip(trigger); + let playground = trigger.closest("pre"); + return playground_text(playground); + } + }); + + Array.from(clipButtons).forEach(function (clipButton) { + clipButton.addEventListener('mouseout', function (e) { + hideTooltip(e.currentTarget); + }); + }); + + clipboardSnippets.on('success', function (e) { + e.clearSelection(); + showTooltip(e.trigger, "Copied!"); + }); + + clipboardSnippets.on('error', function (e) { + showTooltip(e.trigger, "Clipboard error!"); + }); +})(); + +(function scrollToTop () { + var menuTitle = document.querySelector('.menu-title'); + + menuTitle.addEventListener('click', function () { + document.scrollingElement.scrollTo({ top: 0, behavior: 'smooth' }); + }); +})(); + +(function controllMenu() { + var menu = document.getElementById('menu-bar'); + + (function controllPosition() { + var scrollTop = document.scrollingElement.scrollTop; + var prevScrollTop = scrollTop; + var minMenuY = -menu.clientHeight - 50; + // When the script loads, the page can be at any scroll (e.g. if you reforesh it). + menu.style.top = scrollTop + 'px'; + // Same as parseInt(menu.style.top.slice(0, -2), but faster + var topCache = menu.style.top.slice(0, -2); + menu.classList.remove('sticky'); + var stickyCache = false; // Same as menu.classList.contains('sticky'), but faster + document.addEventListener('scroll', function () { + scrollTop = Math.max(document.scrollingElement.scrollTop, 0); + // `null` means that it doesn't need to be updated + var nextSticky = null; + var nextTop = null; + var scrollDown = scrollTop > prevScrollTop; + var menuPosAbsoluteY = topCache - scrollTop; + if (scrollDown) { + nextSticky = false; + if (menuPosAbsoluteY > 0) { + nextTop = prevScrollTop; + } + } else { + if (menuPosAbsoluteY > 0) { + nextSticky = true; + } else if (menuPosAbsoluteY < minMenuY) { + nextTop = prevScrollTop + minMenuY; + } + } + if (nextSticky === true && stickyCache === false) { + menu.classList.add('sticky'); + stickyCache = true; + } else if (nextSticky === false && stickyCache === true) { + menu.classList.remove('sticky'); + stickyCache = false; + } + if (nextTop !== null) { + menu.style.top = nextTop + 'px'; + topCache = nextTop; + } + prevScrollTop = scrollTop; + }, { passive: true }); + })(); + (function controllBorder() { + menu.classList.remove('bordered'); + document.addEventListener('scroll', function () { + if (menu.offsetTop === 0) { + menu.classList.remove('bordered'); + } else { + menu.classList.add('bordered'); + } + }, { passive: true }); + })(); +})(); diff --git a/theme/index.hbs b/theme/index.hbs new file mode 100644 index 00000000..e5191f74 --- /dev/null +++ b/theme/index.hbs @@ -0,0 +1,307 @@ + + + + + + {{ title }} + {{#if is_print }} + + {{/if}} + {{#if base_url}} + + {{/if}} + + + + {{> head}} + + + + + + + {{#if favicon_svg}} + + {{/if}} + {{#if favicon_png}} + + {{/if}} + + + + {{#if print_enable}} + + {{/if}} + + + + {{#if copy_fonts}} + + {{/if}} + + + + + + + + {{#each additional_css}} + + {{/each}} + + {{#if mathjax_support}} + + + {{/if}} + + + + + + + + + + + + + + + + +
+ +
+ {{> header}} + + + + {{#if search_enabled}} + + {{/if}} + + + + +
+
+ {{{ content }}} +
+ + +
+
+ + + +
+ + {{#if livereload}} + + + {{/if}} + + {{#if google_analytics}} + + + {{/if}} + + {{#if playground_line_numbers}} + + {{/if}} + + {{#if playground_copyable}} + + {{/if}} + + {{#if playground_js}} + + + + + + + {{/if}} + + {{#if search_js}} + + + + {{/if}} + + + + + + + {{#each additional_js}} + + {{/each}} + + {{#if is_print}} + {{#if mathjax_support}} + + {{else}} + + {{/if}} + {{/if}} + + + -- 2.43.0