commit
7415737cf1
41 changed files with 20132 additions and 392 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -23,3 +23,4 @@ cabal.project.local~
|
||||||
.HTF/
|
.HTF/
|
||||||
.ghc.environment.*
|
.ghc.environment.*
|
||||||
node_modules/
|
node_modules/
|
||||||
|
.DS_Store
|
||||||
1916
docs/_snowpack/link/repl/krill-parser.js
Normal file
1916
docs/_snowpack/link/repl/krill-parser.js
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -292,20 +292,40 @@ class Pattern {
|
||||||
outerJoin() {
|
outerJoin() {
|
||||||
return this.outerBind(id);
|
return this.outerBind(id);
|
||||||
}
|
}
|
||||||
|
_patternify(func) {
|
||||||
|
const pat = this;
|
||||||
|
const patterned = function(...args) {
|
||||||
|
const pat_arg = sequence(...args);
|
||||||
|
return pat_arg.fmap((arg) => func.call(pat, arg)).outerJoin();
|
||||||
|
};
|
||||||
|
return patterned;
|
||||||
|
}
|
||||||
_fast(factor) {
|
_fast(factor) {
|
||||||
var fastQuery = this.withQueryTime((t) => t.mul(factor));
|
var fastQuery = this.withQueryTime((t) => t.mul(factor));
|
||||||
return fastQuery.withEventTime((t) => t.div(factor));
|
return fastQuery.withEventTime((t) => t.div(factor));
|
||||||
}
|
}
|
||||||
|
fast(factor) {
|
||||||
|
return this._patternify(Pattern.prototype._fast)(factor);
|
||||||
|
}
|
||||||
_slow(factor) {
|
_slow(factor) {
|
||||||
return this._fast(1 / factor);
|
return this._fast(1 / factor);
|
||||||
}
|
}
|
||||||
|
slow(factor) {
|
||||||
|
return this._patternify(Pattern.prototype._slow)(factor);
|
||||||
|
}
|
||||||
_early(offset) {
|
_early(offset) {
|
||||||
offset = Fraction(offset);
|
offset = Fraction(offset);
|
||||||
return this.withQueryTime((t) => t.add(offset)).withEventTime((t) => t.sub(offset));
|
return this.withQueryTime((t) => t.add(offset)).withEventTime((t) => t.sub(offset));
|
||||||
}
|
}
|
||||||
|
early(factor) {
|
||||||
|
return this._patternify(Pattern.prototype._early)(factor);
|
||||||
|
}
|
||||||
_late(offset) {
|
_late(offset) {
|
||||||
return this._early(0 - offset);
|
return this._early(0 - offset);
|
||||||
}
|
}
|
||||||
|
late(factor) {
|
||||||
|
return this._patternify(Pattern.prototype._late)(factor);
|
||||||
|
}
|
||||||
when(binary_pat, func) {
|
when(binary_pat, func) {
|
||||||
var true_pat = binary_pat._filterValues(id);
|
var true_pat = binary_pat._filterValues(id);
|
||||||
var false_pat = binary_pat._filterValues((val) => !val);
|
var false_pat = binary_pat._filterValues((val) => !val);
|
||||||
|
|
@ -379,9 +399,11 @@ function stack(...pats) {
|
||||||
}
|
}
|
||||||
function slowcat(...pats) {
|
function slowcat(...pats) {
|
||||||
pats = pats.map(reify);
|
pats = pats.map(reify);
|
||||||
var query2 = function(span) {
|
const query2 = function(span) {
|
||||||
var pat = pats[Math.floor(span.begin) % pats.length];
|
const pat_n = Math.floor(span.begin) % pats.length;
|
||||||
return pat.query(span);
|
const pat = pats[pat_n];
|
||||||
|
const offset = span.begin.floor().sub(span.begin.div(pats.length).floor());
|
||||||
|
return pat.withEventTime((t) => t.add(offset)).query(span.withTime((t) => t.sub(offset)));
|
||||||
};
|
};
|
||||||
return new Pattern(query2)._splitQueries();
|
return new Pattern(query2)._splitQueries();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
1722
docs/_snowpack/pkg/@tonaljs/tonal.js
Normal file
1722
docs/_snowpack/pkg/@tonaljs/tonal.js
Normal file
File diff suppressed because it is too large
Load diff
344
docs/_snowpack/pkg/codemirror/lib/codemirror.css
vendored
Normal file
344
docs/_snowpack/pkg/codemirror/lib/codemirror.css
vendored
Normal file
|
|
@ -0,0 +1,344 @@
|
||||||
|
/* BASICS */
|
||||||
|
|
||||||
|
.CodeMirror {
|
||||||
|
/* Set height, width, borders, and global font properties here */
|
||||||
|
font-family: monospace;
|
||||||
|
height: 300px;
|
||||||
|
color: black;
|
||||||
|
direction: ltr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* PADDING */
|
||||||
|
|
||||||
|
.CodeMirror-lines {
|
||||||
|
padding: 4px 0; /* Vertical padding around content */
|
||||||
|
}
|
||||||
|
.CodeMirror pre.CodeMirror-line,
|
||||||
|
.CodeMirror pre.CodeMirror-line-like {
|
||||||
|
padding: 0 4px; /* Horizontal padding of content */
|
||||||
|
}
|
||||||
|
|
||||||
|
.CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
|
||||||
|
background-color: white; /* The little square between H and V scrollbars */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* GUTTER */
|
||||||
|
|
||||||
|
.CodeMirror-gutters {
|
||||||
|
border-right: 1px solid #ddd;
|
||||||
|
background-color: #f7f7f7;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
.CodeMirror-linenumbers {}
|
||||||
|
.CodeMirror-linenumber {
|
||||||
|
padding: 0 3px 0 5px;
|
||||||
|
min-width: 20px;
|
||||||
|
text-align: right;
|
||||||
|
color: #999;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.CodeMirror-guttermarker { color: black; }
|
||||||
|
.CodeMirror-guttermarker-subtle { color: #999; }
|
||||||
|
|
||||||
|
/* CURSOR */
|
||||||
|
|
||||||
|
.CodeMirror-cursor {
|
||||||
|
border-left: 1px solid black;
|
||||||
|
border-right: none;
|
||||||
|
width: 0;
|
||||||
|
}
|
||||||
|
/* Shown when moving in bi-directional text */
|
||||||
|
.CodeMirror div.CodeMirror-secondarycursor {
|
||||||
|
border-left: 1px solid silver;
|
||||||
|
}
|
||||||
|
.cm-fat-cursor .CodeMirror-cursor {
|
||||||
|
width: auto;
|
||||||
|
border: 0 !important;
|
||||||
|
background: #7e7;
|
||||||
|
}
|
||||||
|
.cm-fat-cursor div.CodeMirror-cursors {
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
.cm-fat-cursor .CodeMirror-line::selection,
|
||||||
|
.cm-fat-cursor .CodeMirror-line > span::selection,
|
||||||
|
.cm-fat-cursor .CodeMirror-line > span > span::selection { background: transparent; }
|
||||||
|
.cm-fat-cursor .CodeMirror-line::-moz-selection,
|
||||||
|
.cm-fat-cursor .CodeMirror-line > span::-moz-selection,
|
||||||
|
.cm-fat-cursor .CodeMirror-line > span > span::-moz-selection { background: transparent; }
|
||||||
|
.cm-fat-cursor { caret-color: transparent; }
|
||||||
|
@-moz-keyframes blink {
|
||||||
|
0% {}
|
||||||
|
50% { background-color: transparent; }
|
||||||
|
100% {}
|
||||||
|
}
|
||||||
|
@-webkit-keyframes blink {
|
||||||
|
0% {}
|
||||||
|
50% { background-color: transparent; }
|
||||||
|
100% {}
|
||||||
|
}
|
||||||
|
@keyframes blink {
|
||||||
|
0% {}
|
||||||
|
50% { background-color: transparent; }
|
||||||
|
100% {}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Can style cursor different in overwrite (non-insert) mode */
|
||||||
|
.CodeMirror-overwrite .CodeMirror-cursor {}
|
||||||
|
|
||||||
|
.cm-tab { display: inline-block; text-decoration: inherit; }
|
||||||
|
|
||||||
|
.CodeMirror-rulers {
|
||||||
|
position: absolute;
|
||||||
|
left: 0; right: 0; top: -50px; bottom: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.CodeMirror-ruler {
|
||||||
|
border-left: 1px solid #ccc;
|
||||||
|
top: 0; bottom: 0;
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* DEFAULT THEME */
|
||||||
|
|
||||||
|
.cm-s-default .cm-header {color: blue;}
|
||||||
|
.cm-s-default .cm-quote {color: #090;}
|
||||||
|
.cm-negative {color: #d44;}
|
||||||
|
.cm-positive {color: #292;}
|
||||||
|
.cm-header, .cm-strong {font-weight: bold;}
|
||||||
|
.cm-em {font-style: italic;}
|
||||||
|
.cm-link {text-decoration: underline;}
|
||||||
|
.cm-strikethrough {text-decoration: line-through;}
|
||||||
|
|
||||||
|
.cm-s-default .cm-keyword {color: #708;}
|
||||||
|
.cm-s-default .cm-atom {color: #219;}
|
||||||
|
.cm-s-default .cm-number {color: #164;}
|
||||||
|
.cm-s-default .cm-def {color: #00f;}
|
||||||
|
.cm-s-default .cm-variable,
|
||||||
|
.cm-s-default .cm-punctuation,
|
||||||
|
.cm-s-default .cm-property,
|
||||||
|
.cm-s-default .cm-operator {}
|
||||||
|
.cm-s-default .cm-variable-2 {color: #05a;}
|
||||||
|
.cm-s-default .cm-variable-3, .cm-s-default .cm-type {color: #085;}
|
||||||
|
.cm-s-default .cm-comment {color: #a50;}
|
||||||
|
.cm-s-default .cm-string {color: #a11;}
|
||||||
|
.cm-s-default .cm-string-2 {color: #f50;}
|
||||||
|
.cm-s-default .cm-meta {color: #555;}
|
||||||
|
.cm-s-default .cm-qualifier {color: #555;}
|
||||||
|
.cm-s-default .cm-builtin {color: #30a;}
|
||||||
|
.cm-s-default .cm-bracket {color: #997;}
|
||||||
|
.cm-s-default .cm-tag {color: #170;}
|
||||||
|
.cm-s-default .cm-attribute {color: #00c;}
|
||||||
|
.cm-s-default .cm-hr {color: #999;}
|
||||||
|
.cm-s-default .cm-link {color: #00c;}
|
||||||
|
|
||||||
|
.cm-s-default .cm-error {color: #f00;}
|
||||||
|
.cm-invalidchar {color: #f00;}
|
||||||
|
|
||||||
|
.CodeMirror-composing { border-bottom: 2px solid; }
|
||||||
|
|
||||||
|
/* Default styles for common addons */
|
||||||
|
|
||||||
|
div.CodeMirror span.CodeMirror-matchingbracket {color: #0b0;}
|
||||||
|
div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #a22;}
|
||||||
|
.CodeMirror-matchingtag { background: rgba(255, 150, 0, .3); }
|
||||||
|
.CodeMirror-activeline-background {background: #e8f2ff;}
|
||||||
|
|
||||||
|
/* STOP */
|
||||||
|
|
||||||
|
/* The rest of this file contains styles related to the mechanics of
|
||||||
|
the editor. You probably shouldn't touch them. */
|
||||||
|
|
||||||
|
.CodeMirror {
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
background: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.CodeMirror-scroll {
|
||||||
|
overflow: scroll !important; /* Things will break if this is overridden */
|
||||||
|
/* 50px is the magic margin used to hide the element's real scrollbars */
|
||||||
|
/* See overflow: hidden in .CodeMirror */
|
||||||
|
margin-bottom: -50px; margin-right: -50px;
|
||||||
|
padding-bottom: 50px;
|
||||||
|
height: 100%;
|
||||||
|
outline: none; /* Prevent dragging from highlighting the element */
|
||||||
|
position: relative;
|
||||||
|
z-index: 0;
|
||||||
|
}
|
||||||
|
.CodeMirror-sizer {
|
||||||
|
position: relative;
|
||||||
|
border-right: 50px solid transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The fake, visible scrollbars. Used to force redraw during scrolling
|
||||||
|
before actual scrolling happens, thus preventing shaking and
|
||||||
|
flickering artifacts. */
|
||||||
|
.CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 6;
|
||||||
|
display: none;
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
.CodeMirror-vscrollbar {
|
||||||
|
right: 0; top: 0;
|
||||||
|
overflow-x: hidden;
|
||||||
|
overflow-y: scroll;
|
||||||
|
}
|
||||||
|
.CodeMirror-hscrollbar {
|
||||||
|
bottom: 0; left: 0;
|
||||||
|
overflow-y: hidden;
|
||||||
|
overflow-x: scroll;
|
||||||
|
}
|
||||||
|
.CodeMirror-scrollbar-filler {
|
||||||
|
right: 0; bottom: 0;
|
||||||
|
}
|
||||||
|
.CodeMirror-gutter-filler {
|
||||||
|
left: 0; bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.CodeMirror-gutters {
|
||||||
|
position: absolute; left: 0; top: 0;
|
||||||
|
min-height: 100%;
|
||||||
|
z-index: 3;
|
||||||
|
}
|
||||||
|
.CodeMirror-gutter {
|
||||||
|
white-space: normal;
|
||||||
|
height: 100%;
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: top;
|
||||||
|
margin-bottom: -50px;
|
||||||
|
}
|
||||||
|
.CodeMirror-gutter-wrapper {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 4;
|
||||||
|
background: none !important;
|
||||||
|
border: none !important;
|
||||||
|
}
|
||||||
|
.CodeMirror-gutter-background {
|
||||||
|
position: absolute;
|
||||||
|
top: 0; bottom: 0;
|
||||||
|
z-index: 4;
|
||||||
|
}
|
||||||
|
.CodeMirror-gutter-elt {
|
||||||
|
position: absolute;
|
||||||
|
cursor: default;
|
||||||
|
z-index: 4;
|
||||||
|
}
|
||||||
|
.CodeMirror-gutter-wrapper ::selection { background-color: transparent }
|
||||||
|
.CodeMirror-gutter-wrapper ::-moz-selection { background-color: transparent }
|
||||||
|
|
||||||
|
.CodeMirror-lines {
|
||||||
|
cursor: text;
|
||||||
|
min-height: 1px; /* prevents collapsing before first draw */
|
||||||
|
}
|
||||||
|
.CodeMirror pre.CodeMirror-line,
|
||||||
|
.CodeMirror pre.CodeMirror-line-like {
|
||||||
|
/* Reset some styles that the rest of the page might have set */
|
||||||
|
-moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0;
|
||||||
|
border-width: 0;
|
||||||
|
background: transparent;
|
||||||
|
font-family: inherit;
|
||||||
|
font-size: inherit;
|
||||||
|
margin: 0;
|
||||||
|
white-space: pre;
|
||||||
|
word-wrap: normal;
|
||||||
|
line-height: inherit;
|
||||||
|
color: inherit;
|
||||||
|
z-index: 2;
|
||||||
|
position: relative;
|
||||||
|
overflow: visible;
|
||||||
|
-webkit-tap-highlight-color: transparent;
|
||||||
|
-webkit-font-variant-ligatures: contextual;
|
||||||
|
font-variant-ligatures: contextual;
|
||||||
|
}
|
||||||
|
.CodeMirror-wrap pre.CodeMirror-line,
|
||||||
|
.CodeMirror-wrap pre.CodeMirror-line-like {
|
||||||
|
word-wrap: break-word;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
word-break: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.CodeMirror-linebackground {
|
||||||
|
position: absolute;
|
||||||
|
left: 0; right: 0; top: 0; bottom: 0;
|
||||||
|
z-index: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.CodeMirror-linewidget {
|
||||||
|
position: relative;
|
||||||
|
z-index: 2;
|
||||||
|
padding: 0.1px; /* Force widget margins to stay inside of the container */
|
||||||
|
}
|
||||||
|
|
||||||
|
.CodeMirror-widget {}
|
||||||
|
|
||||||
|
.CodeMirror-rtl pre { direction: rtl; }
|
||||||
|
|
||||||
|
.CodeMirror-code {
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Force content-box sizing for the elements where we expect it */
|
||||||
|
.CodeMirror-scroll,
|
||||||
|
.CodeMirror-sizer,
|
||||||
|
.CodeMirror-gutter,
|
||||||
|
.CodeMirror-gutters,
|
||||||
|
.CodeMirror-linenumber {
|
||||||
|
-moz-box-sizing: content-box;
|
||||||
|
box-sizing: content-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.CodeMirror-measure {
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
height: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.CodeMirror-cursor {
|
||||||
|
position: absolute;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
.CodeMirror-measure pre { position: static; }
|
||||||
|
|
||||||
|
div.CodeMirror-cursors {
|
||||||
|
visibility: hidden;
|
||||||
|
position: relative;
|
||||||
|
z-index: 3;
|
||||||
|
}
|
||||||
|
div.CodeMirror-dragcursors {
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
.CodeMirror-focused div.CodeMirror-cursors {
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
.CodeMirror-selected { background: #d9d9d9; }
|
||||||
|
.CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; }
|
||||||
|
.CodeMirror-crosshair { cursor: crosshair; }
|
||||||
|
.CodeMirror-line::selection, .CodeMirror-line > span::selection, .CodeMirror-line > span > span::selection { background: #d7d4f0; }
|
||||||
|
.CodeMirror-line::-moz-selection, .CodeMirror-line > span::-moz-selection, .CodeMirror-line > span > span::-moz-selection { background: #d7d4f0; }
|
||||||
|
|
||||||
|
.cm-searching {
|
||||||
|
background-color: #ffa;
|
||||||
|
background-color: rgba(255, 255, 0, .4);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Used to force a border model for a node */
|
||||||
|
.cm-force-border { padding-right: .1px; }
|
||||||
|
|
||||||
|
@media print {
|
||||||
|
/* Hide the cursor when printing */
|
||||||
|
.CodeMirror div.CodeMirror-cursors {
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* See issue #2901 */
|
||||||
|
.cm-tab-wrap-hack:after { content: ''; }
|
||||||
|
|
||||||
|
/* Help users use markselection to safely style text background */
|
||||||
|
span.CodeMirror-selectedtext { background: none; }
|
||||||
10
docs/_snowpack/pkg/codemirror/lib/codemirror.css.proxy.js
vendored
Normal file
10
docs/_snowpack/pkg/codemirror/lib/codemirror.css.proxy.js
vendored
Normal file
File diff suppressed because one or more lines are too long
960
docs/_snowpack/pkg/codemirror/mode/javascript/javascript.js
vendored
Normal file
960
docs/_snowpack/pkg/codemirror/mode/javascript/javascript.js
vendored
Normal file
|
|
@ -0,0 +1,960 @@
|
||||||
|
import { c as createCommonjsModule } from '../../../common/_commonjsHelpers-8c19dec8.js';
|
||||||
|
import { c as codemirror } from '../../../common/codemirror-d650d44d.js';
|
||||||
|
|
||||||
|
var javascript = createCommonjsModule(function (module, exports) {
|
||||||
|
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||||
|
// Distributed under an MIT license: https://codemirror.net/LICENSE
|
||||||
|
|
||||||
|
(function(mod) {
|
||||||
|
mod(codemirror);
|
||||||
|
})(function(CodeMirror) {
|
||||||
|
|
||||||
|
CodeMirror.defineMode("javascript", function(config, parserConfig) {
|
||||||
|
var indentUnit = config.indentUnit;
|
||||||
|
var statementIndent = parserConfig.statementIndent;
|
||||||
|
var jsonldMode = parserConfig.jsonld;
|
||||||
|
var jsonMode = parserConfig.json || jsonldMode;
|
||||||
|
var trackScope = parserConfig.trackScope !== false;
|
||||||
|
var isTS = parserConfig.typescript;
|
||||||
|
var wordRE = parserConfig.wordCharacters || /[\w$\xa1-\uffff]/;
|
||||||
|
|
||||||
|
// Tokenizer
|
||||||
|
|
||||||
|
var keywords = function(){
|
||||||
|
function kw(type) {return {type: type, style: "keyword"};}
|
||||||
|
var A = kw("keyword a"), B = kw("keyword b"), C = kw("keyword c"), D = kw("keyword d");
|
||||||
|
var operator = kw("operator"), atom = {type: "atom", style: "atom"};
|
||||||
|
|
||||||
|
return {
|
||||||
|
"if": kw("if"), "while": A, "with": A, "else": B, "do": B, "try": B, "finally": B,
|
||||||
|
"return": D, "break": D, "continue": D, "new": kw("new"), "delete": C, "void": C, "throw": C,
|
||||||
|
"debugger": kw("debugger"), "var": kw("var"), "const": kw("var"), "let": kw("var"),
|
||||||
|
"function": kw("function"), "catch": kw("catch"),
|
||||||
|
"for": kw("for"), "switch": kw("switch"), "case": kw("case"), "default": kw("default"),
|
||||||
|
"in": operator, "typeof": operator, "instanceof": operator,
|
||||||
|
"true": atom, "false": atom, "null": atom, "undefined": atom, "NaN": atom, "Infinity": atom,
|
||||||
|
"this": kw("this"), "class": kw("class"), "super": kw("atom"),
|
||||||
|
"yield": C, "export": kw("export"), "import": kw("import"), "extends": C,
|
||||||
|
"await": C
|
||||||
|
};
|
||||||
|
}();
|
||||||
|
|
||||||
|
var isOperatorChar = /[+\-*&%=<>!?|~^@]/;
|
||||||
|
var isJsonldKeyword = /^@(context|id|value|language|type|container|list|set|reverse|index|base|vocab|graph)"/;
|
||||||
|
|
||||||
|
function readRegexp(stream) {
|
||||||
|
var escaped = false, next, inSet = false;
|
||||||
|
while ((next = stream.next()) != null) {
|
||||||
|
if (!escaped) {
|
||||||
|
if (next == "/" && !inSet) return;
|
||||||
|
if (next == "[") inSet = true;
|
||||||
|
else if (inSet && next == "]") inSet = false;
|
||||||
|
}
|
||||||
|
escaped = !escaped && next == "\\";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Used as scratch variables to communicate multiple values without
|
||||||
|
// consing up tons of objects.
|
||||||
|
var type, content;
|
||||||
|
function ret(tp, style, cont) {
|
||||||
|
type = tp; content = cont;
|
||||||
|
return style;
|
||||||
|
}
|
||||||
|
function tokenBase(stream, state) {
|
||||||
|
var ch = stream.next();
|
||||||
|
if (ch == '"' || ch == "'") {
|
||||||
|
state.tokenize = tokenString(ch);
|
||||||
|
return state.tokenize(stream, state);
|
||||||
|
} else if (ch == "." && stream.match(/^\d[\d_]*(?:[eE][+\-]?[\d_]+)?/)) {
|
||||||
|
return ret("number", "number");
|
||||||
|
} else if (ch == "." && stream.match("..")) {
|
||||||
|
return ret("spread", "meta");
|
||||||
|
} else if (/[\[\]{}\(\),;\:\.]/.test(ch)) {
|
||||||
|
return ret(ch);
|
||||||
|
} else if (ch == "=" && stream.eat(">")) {
|
||||||
|
return ret("=>", "operator");
|
||||||
|
} else if (ch == "0" && stream.match(/^(?:x[\dA-Fa-f_]+|o[0-7_]+|b[01_]+)n?/)) {
|
||||||
|
return ret("number", "number");
|
||||||
|
} else if (/\d/.test(ch)) {
|
||||||
|
stream.match(/^[\d_]*(?:n|(?:\.[\d_]*)?(?:[eE][+\-]?[\d_]+)?)?/);
|
||||||
|
return ret("number", "number");
|
||||||
|
} else if (ch == "/") {
|
||||||
|
if (stream.eat("*")) {
|
||||||
|
state.tokenize = tokenComment;
|
||||||
|
return tokenComment(stream, state);
|
||||||
|
} else if (stream.eat("/")) {
|
||||||
|
stream.skipToEnd();
|
||||||
|
return ret("comment", "comment");
|
||||||
|
} else if (expressionAllowed(stream, state, 1)) {
|
||||||
|
readRegexp(stream);
|
||||||
|
stream.match(/^\b(([gimyus])(?![gimyus]*\2))+\b/);
|
||||||
|
return ret("regexp", "string-2");
|
||||||
|
} else {
|
||||||
|
stream.eat("=");
|
||||||
|
return ret("operator", "operator", stream.current());
|
||||||
|
}
|
||||||
|
} else if (ch == "`") {
|
||||||
|
state.tokenize = tokenQuasi;
|
||||||
|
return tokenQuasi(stream, state);
|
||||||
|
} else if (ch == "#" && stream.peek() == "!") {
|
||||||
|
stream.skipToEnd();
|
||||||
|
return ret("meta", "meta");
|
||||||
|
} else if (ch == "#" && stream.eatWhile(wordRE)) {
|
||||||
|
return ret("variable", "property")
|
||||||
|
} else if (ch == "<" && stream.match("!--") ||
|
||||||
|
(ch == "-" && stream.match("->") && !/\S/.test(stream.string.slice(0, stream.start)))) {
|
||||||
|
stream.skipToEnd();
|
||||||
|
return ret("comment", "comment")
|
||||||
|
} else if (isOperatorChar.test(ch)) {
|
||||||
|
if (ch != ">" || !state.lexical || state.lexical.type != ">") {
|
||||||
|
if (stream.eat("=")) {
|
||||||
|
if (ch == "!" || ch == "=") stream.eat("=");
|
||||||
|
} else if (/[<>*+\-|&?]/.test(ch)) {
|
||||||
|
stream.eat(ch);
|
||||||
|
if (ch == ">") stream.eat(ch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ch == "?" && stream.eat(".")) return ret(".")
|
||||||
|
return ret("operator", "operator", stream.current());
|
||||||
|
} else if (wordRE.test(ch)) {
|
||||||
|
stream.eatWhile(wordRE);
|
||||||
|
var word = stream.current();
|
||||||
|
if (state.lastType != ".") {
|
||||||
|
if (keywords.propertyIsEnumerable(word)) {
|
||||||
|
var kw = keywords[word];
|
||||||
|
return ret(kw.type, kw.style, word)
|
||||||
|
}
|
||||||
|
if (word == "async" && stream.match(/^(\s|\/\*([^*]|\*(?!\/))*?\*\/)*[\[\(\w]/, false))
|
||||||
|
return ret("async", "keyword", word)
|
||||||
|
}
|
||||||
|
return ret("variable", "variable", word)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function tokenString(quote) {
|
||||||
|
return function(stream, state) {
|
||||||
|
var escaped = false, next;
|
||||||
|
if (jsonldMode && stream.peek() == "@" && stream.match(isJsonldKeyword)){
|
||||||
|
state.tokenize = tokenBase;
|
||||||
|
return ret("jsonld-keyword", "meta");
|
||||||
|
}
|
||||||
|
while ((next = stream.next()) != null) {
|
||||||
|
if (next == quote && !escaped) break;
|
||||||
|
escaped = !escaped && next == "\\";
|
||||||
|
}
|
||||||
|
if (!escaped) state.tokenize = tokenBase;
|
||||||
|
return ret("string", "string");
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function tokenComment(stream, state) {
|
||||||
|
var maybeEnd = false, ch;
|
||||||
|
while (ch = stream.next()) {
|
||||||
|
if (ch == "/" && maybeEnd) {
|
||||||
|
state.tokenize = tokenBase;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
maybeEnd = (ch == "*");
|
||||||
|
}
|
||||||
|
return ret("comment", "comment");
|
||||||
|
}
|
||||||
|
|
||||||
|
function tokenQuasi(stream, state) {
|
||||||
|
var escaped = false, next;
|
||||||
|
while ((next = stream.next()) != null) {
|
||||||
|
if (!escaped && (next == "`" || next == "$" && stream.eat("{"))) {
|
||||||
|
state.tokenize = tokenBase;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
escaped = !escaped && next == "\\";
|
||||||
|
}
|
||||||
|
return ret("quasi", "string-2", stream.current());
|
||||||
|
}
|
||||||
|
|
||||||
|
var brackets = "([{}])";
|
||||||
|
// This is a crude lookahead trick to try and notice that we're
|
||||||
|
// parsing the argument patterns for a fat-arrow function before we
|
||||||
|
// actually hit the arrow token. It only works if the arrow is on
|
||||||
|
// the same line as the arguments and there's no strange noise
|
||||||
|
// (comments) in between. Fallback is to only notice when we hit the
|
||||||
|
// arrow, and not declare the arguments as locals for the arrow
|
||||||
|
// body.
|
||||||
|
function findFatArrow(stream, state) {
|
||||||
|
if (state.fatArrowAt) state.fatArrowAt = null;
|
||||||
|
var arrow = stream.string.indexOf("=>", stream.start);
|
||||||
|
if (arrow < 0) return;
|
||||||
|
|
||||||
|
if (isTS) { // Try to skip TypeScript return type declarations after the arguments
|
||||||
|
var m = /:\s*(?:\w+(?:<[^>]*>|\[\])?|\{[^}]*\})\s*$/.exec(stream.string.slice(stream.start, arrow));
|
||||||
|
if (m) arrow = m.index;
|
||||||
|
}
|
||||||
|
|
||||||
|
var depth = 0, sawSomething = false;
|
||||||
|
for (var pos = arrow - 1; pos >= 0; --pos) {
|
||||||
|
var ch = stream.string.charAt(pos);
|
||||||
|
var bracket = brackets.indexOf(ch);
|
||||||
|
if (bracket >= 0 && bracket < 3) {
|
||||||
|
if (!depth) { ++pos; break; }
|
||||||
|
if (--depth == 0) { if (ch == "(") sawSomething = true; break; }
|
||||||
|
} else if (bracket >= 3 && bracket < 6) {
|
||||||
|
++depth;
|
||||||
|
} else if (wordRE.test(ch)) {
|
||||||
|
sawSomething = true;
|
||||||
|
} else if (/["'\/`]/.test(ch)) {
|
||||||
|
for (;; --pos) {
|
||||||
|
if (pos == 0) return
|
||||||
|
var next = stream.string.charAt(pos - 1);
|
||||||
|
if (next == ch && stream.string.charAt(pos - 2) != "\\") { pos--; break }
|
||||||
|
}
|
||||||
|
} else if (sawSomething && !depth) {
|
||||||
|
++pos;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (sawSomething && !depth) state.fatArrowAt = pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parser
|
||||||
|
|
||||||
|
var atomicTypes = {"atom": true, "number": true, "variable": true, "string": true,
|
||||||
|
"regexp": true, "this": true, "import": true, "jsonld-keyword": true};
|
||||||
|
|
||||||
|
function JSLexical(indented, column, type, align, prev, info) {
|
||||||
|
this.indented = indented;
|
||||||
|
this.column = column;
|
||||||
|
this.type = type;
|
||||||
|
this.prev = prev;
|
||||||
|
this.info = info;
|
||||||
|
if (align != null) this.align = align;
|
||||||
|
}
|
||||||
|
|
||||||
|
function inScope(state, varname) {
|
||||||
|
if (!trackScope) return false
|
||||||
|
for (var v = state.localVars; v; v = v.next)
|
||||||
|
if (v.name == varname) return true;
|
||||||
|
for (var cx = state.context; cx; cx = cx.prev) {
|
||||||
|
for (var v = cx.vars; v; v = v.next)
|
||||||
|
if (v.name == varname) return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseJS(state, style, type, content, stream) {
|
||||||
|
var cc = state.cc;
|
||||||
|
// Communicate our context to the combinators.
|
||||||
|
// (Less wasteful than consing up a hundred closures on every call.)
|
||||||
|
cx.state = state; cx.stream = stream; cx.marked = null, cx.cc = cc; cx.style = style;
|
||||||
|
|
||||||
|
if (!state.lexical.hasOwnProperty("align"))
|
||||||
|
state.lexical.align = true;
|
||||||
|
|
||||||
|
while(true) {
|
||||||
|
var combinator = cc.length ? cc.pop() : jsonMode ? expression : statement;
|
||||||
|
if (combinator(type, content)) {
|
||||||
|
while(cc.length && cc[cc.length - 1].lex)
|
||||||
|
cc.pop()();
|
||||||
|
if (cx.marked) return cx.marked;
|
||||||
|
if (type == "variable" && inScope(state, content)) return "variable-2";
|
||||||
|
return style;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Combinator utils
|
||||||
|
|
||||||
|
var cx = {state: null, column: null, marked: null, cc: null};
|
||||||
|
function pass() {
|
||||||
|
for (var i = arguments.length - 1; i >= 0; i--) cx.cc.push(arguments[i]);
|
||||||
|
}
|
||||||
|
function cont() {
|
||||||
|
pass.apply(null, arguments);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
function inList(name, list) {
|
||||||
|
for (var v = list; v; v = v.next) if (v.name == name) return true
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
function register(varname) {
|
||||||
|
var state = cx.state;
|
||||||
|
cx.marked = "def";
|
||||||
|
if (!trackScope) return
|
||||||
|
if (state.context) {
|
||||||
|
if (state.lexical.info == "var" && state.context && state.context.block) {
|
||||||
|
// FIXME function decls are also not block scoped
|
||||||
|
var newContext = registerVarScoped(varname, state.context);
|
||||||
|
if (newContext != null) {
|
||||||
|
state.context = newContext;
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else if (!inList(varname, state.localVars)) {
|
||||||
|
state.localVars = new Var(varname, state.localVars);
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Fall through means this is global
|
||||||
|
if (parserConfig.globalVars && !inList(varname, state.globalVars))
|
||||||
|
state.globalVars = new Var(varname, state.globalVars);
|
||||||
|
}
|
||||||
|
function registerVarScoped(varname, context) {
|
||||||
|
if (!context) {
|
||||||
|
return null
|
||||||
|
} else if (context.block) {
|
||||||
|
var inner = registerVarScoped(varname, context.prev);
|
||||||
|
if (!inner) return null
|
||||||
|
if (inner == context.prev) return context
|
||||||
|
return new Context(inner, context.vars, true)
|
||||||
|
} else if (inList(varname, context.vars)) {
|
||||||
|
return context
|
||||||
|
} else {
|
||||||
|
return new Context(context.prev, new Var(varname, context.vars), false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function isModifier(name) {
|
||||||
|
return name == "public" || name == "private" || name == "protected" || name == "abstract" || name == "readonly"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Combinators
|
||||||
|
|
||||||
|
function Context(prev, vars, block) { this.prev = prev; this.vars = vars; this.block = block; }
|
||||||
|
function Var(name, next) { this.name = name; this.next = next; }
|
||||||
|
|
||||||
|
var defaultVars = new Var("this", new Var("arguments", null));
|
||||||
|
function pushcontext() {
|
||||||
|
cx.state.context = new Context(cx.state.context, cx.state.localVars, false);
|
||||||
|
cx.state.localVars = defaultVars;
|
||||||
|
}
|
||||||
|
function pushblockcontext() {
|
||||||
|
cx.state.context = new Context(cx.state.context, cx.state.localVars, true);
|
||||||
|
cx.state.localVars = null;
|
||||||
|
}
|
||||||
|
pushcontext.lex = pushblockcontext.lex = true;
|
||||||
|
function popcontext() {
|
||||||
|
cx.state.localVars = cx.state.context.vars;
|
||||||
|
cx.state.context = cx.state.context.prev;
|
||||||
|
}
|
||||||
|
popcontext.lex = true;
|
||||||
|
function pushlex(type, info) {
|
||||||
|
var result = function() {
|
||||||
|
var state = cx.state, indent = state.indented;
|
||||||
|
if (state.lexical.type == "stat") indent = state.lexical.indented;
|
||||||
|
else for (var outer = state.lexical; outer && outer.type == ")" && outer.align; outer = outer.prev)
|
||||||
|
indent = outer.indented;
|
||||||
|
state.lexical = new JSLexical(indent, cx.stream.column(), type, null, state.lexical, info);
|
||||||
|
};
|
||||||
|
result.lex = true;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
function poplex() {
|
||||||
|
var state = cx.state;
|
||||||
|
if (state.lexical.prev) {
|
||||||
|
if (state.lexical.type == ")")
|
||||||
|
state.indented = state.lexical.indented;
|
||||||
|
state.lexical = state.lexical.prev;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
poplex.lex = true;
|
||||||
|
|
||||||
|
function expect(wanted) {
|
||||||
|
function exp(type) {
|
||||||
|
if (type == wanted) return cont();
|
||||||
|
else if (wanted == ";" || type == "}" || type == ")" || type == "]") return pass();
|
||||||
|
else return cont(exp);
|
||||||
|
} return exp;
|
||||||
|
}
|
||||||
|
|
||||||
|
function statement(type, value) {
|
||||||
|
if (type == "var") return cont(pushlex("vardef", value), vardef, expect(";"), poplex);
|
||||||
|
if (type == "keyword a") return cont(pushlex("form"), parenExpr, statement, poplex);
|
||||||
|
if (type == "keyword b") return cont(pushlex("form"), statement, poplex);
|
||||||
|
if (type == "keyword d") return cx.stream.match(/^\s*$/, false) ? cont() : cont(pushlex("stat"), maybeexpression, expect(";"), poplex);
|
||||||
|
if (type == "debugger") return cont(expect(";"));
|
||||||
|
if (type == "{") return cont(pushlex("}"), pushblockcontext, block, poplex, popcontext);
|
||||||
|
if (type == ";") return cont();
|
||||||
|
if (type == "if") {
|
||||||
|
if (cx.state.lexical.info == "else" && cx.state.cc[cx.state.cc.length - 1] == poplex)
|
||||||
|
cx.state.cc.pop()();
|
||||||
|
return cont(pushlex("form"), parenExpr, statement, poplex, maybeelse);
|
||||||
|
}
|
||||||
|
if (type == "function") return cont(functiondef);
|
||||||
|
if (type == "for") return cont(pushlex("form"), pushblockcontext, forspec, statement, popcontext, poplex);
|
||||||
|
if (type == "class" || (isTS && value == "interface")) {
|
||||||
|
cx.marked = "keyword";
|
||||||
|
return cont(pushlex("form", type == "class" ? type : value), className, poplex)
|
||||||
|
}
|
||||||
|
if (type == "variable") {
|
||||||
|
if (isTS && value == "declare") {
|
||||||
|
cx.marked = "keyword";
|
||||||
|
return cont(statement)
|
||||||
|
} else if (isTS && (value == "module" || value == "enum" || value == "type") && cx.stream.match(/^\s*\w/, false)) {
|
||||||
|
cx.marked = "keyword";
|
||||||
|
if (value == "enum") return cont(enumdef);
|
||||||
|
else if (value == "type") return cont(typename, expect("operator"), typeexpr, expect(";"));
|
||||||
|
else return cont(pushlex("form"), pattern, expect("{"), pushlex("}"), block, poplex, poplex)
|
||||||
|
} else if (isTS && value == "namespace") {
|
||||||
|
cx.marked = "keyword";
|
||||||
|
return cont(pushlex("form"), expression, statement, poplex)
|
||||||
|
} else if (isTS && value == "abstract") {
|
||||||
|
cx.marked = "keyword";
|
||||||
|
return cont(statement)
|
||||||
|
} else {
|
||||||
|
return cont(pushlex("stat"), maybelabel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (type == "switch") return cont(pushlex("form"), parenExpr, expect("{"), pushlex("}", "switch"), pushblockcontext,
|
||||||
|
block, poplex, poplex, popcontext);
|
||||||
|
if (type == "case") return cont(expression, expect(":"));
|
||||||
|
if (type == "default") return cont(expect(":"));
|
||||||
|
if (type == "catch") return cont(pushlex("form"), pushcontext, maybeCatchBinding, statement, poplex, popcontext);
|
||||||
|
if (type == "export") return cont(pushlex("stat"), afterExport, poplex);
|
||||||
|
if (type == "import") return cont(pushlex("stat"), afterImport, poplex);
|
||||||
|
if (type == "async") return cont(statement)
|
||||||
|
if (value == "@") return cont(expression, statement)
|
||||||
|
return pass(pushlex("stat"), expression, expect(";"), poplex);
|
||||||
|
}
|
||||||
|
function maybeCatchBinding(type) {
|
||||||
|
if (type == "(") return cont(funarg, expect(")"))
|
||||||
|
}
|
||||||
|
function expression(type, value) {
|
||||||
|
return expressionInner(type, value, false);
|
||||||
|
}
|
||||||
|
function expressionNoComma(type, value) {
|
||||||
|
return expressionInner(type, value, true);
|
||||||
|
}
|
||||||
|
function parenExpr(type) {
|
||||||
|
if (type != "(") return pass()
|
||||||
|
return cont(pushlex(")"), maybeexpression, expect(")"), poplex)
|
||||||
|
}
|
||||||
|
function expressionInner(type, value, noComma) {
|
||||||
|
if (cx.state.fatArrowAt == cx.stream.start) {
|
||||||
|
var body = noComma ? arrowBodyNoComma : arrowBody;
|
||||||
|
if (type == "(") return cont(pushcontext, pushlex(")"), commasep(funarg, ")"), poplex, expect("=>"), body, popcontext);
|
||||||
|
else if (type == "variable") return pass(pushcontext, pattern, expect("=>"), body, popcontext);
|
||||||
|
}
|
||||||
|
|
||||||
|
var maybeop = noComma ? maybeoperatorNoComma : maybeoperatorComma;
|
||||||
|
if (atomicTypes.hasOwnProperty(type)) return cont(maybeop);
|
||||||
|
if (type == "function") return cont(functiondef, maybeop);
|
||||||
|
if (type == "class" || (isTS && value == "interface")) { cx.marked = "keyword"; return cont(pushlex("form"), classExpression, poplex); }
|
||||||
|
if (type == "keyword c" || type == "async") return cont(noComma ? expressionNoComma : expression);
|
||||||
|
if (type == "(") return cont(pushlex(")"), maybeexpression, expect(")"), poplex, maybeop);
|
||||||
|
if (type == "operator" || type == "spread") return cont(noComma ? expressionNoComma : expression);
|
||||||
|
if (type == "[") return cont(pushlex("]"), arrayLiteral, poplex, maybeop);
|
||||||
|
if (type == "{") return contCommasep(objprop, "}", null, maybeop);
|
||||||
|
if (type == "quasi") return pass(quasi, maybeop);
|
||||||
|
if (type == "new") return cont(maybeTarget(noComma));
|
||||||
|
return cont();
|
||||||
|
}
|
||||||
|
function maybeexpression(type) {
|
||||||
|
if (type.match(/[;\}\)\],]/)) return pass();
|
||||||
|
return pass(expression);
|
||||||
|
}
|
||||||
|
|
||||||
|
function maybeoperatorComma(type, value) {
|
||||||
|
if (type == ",") return cont(maybeexpression);
|
||||||
|
return maybeoperatorNoComma(type, value, false);
|
||||||
|
}
|
||||||
|
function maybeoperatorNoComma(type, value, noComma) {
|
||||||
|
var me = noComma == false ? maybeoperatorComma : maybeoperatorNoComma;
|
||||||
|
var expr = noComma == false ? expression : expressionNoComma;
|
||||||
|
if (type == "=>") return cont(pushcontext, noComma ? arrowBodyNoComma : arrowBody, popcontext);
|
||||||
|
if (type == "operator") {
|
||||||
|
if (/\+\+|--/.test(value) || isTS && value == "!") return cont(me);
|
||||||
|
if (isTS && value == "<" && cx.stream.match(/^([^<>]|<[^<>]*>)*>\s*\(/, false))
|
||||||
|
return cont(pushlex(">"), commasep(typeexpr, ">"), poplex, me);
|
||||||
|
if (value == "?") return cont(expression, expect(":"), expr);
|
||||||
|
return cont(expr);
|
||||||
|
}
|
||||||
|
if (type == "quasi") { return pass(quasi, me); }
|
||||||
|
if (type == ";") return;
|
||||||
|
if (type == "(") return contCommasep(expressionNoComma, ")", "call", me);
|
||||||
|
if (type == ".") return cont(property, me);
|
||||||
|
if (type == "[") return cont(pushlex("]"), maybeexpression, expect("]"), poplex, me);
|
||||||
|
if (isTS && value == "as") { cx.marked = "keyword"; return cont(typeexpr, me) }
|
||||||
|
if (type == "regexp") {
|
||||||
|
cx.state.lastType = cx.marked = "operator";
|
||||||
|
cx.stream.backUp(cx.stream.pos - cx.stream.start - 1);
|
||||||
|
return cont(expr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function quasi(type, value) {
|
||||||
|
if (type != "quasi") return pass();
|
||||||
|
if (value.slice(value.length - 2) != "${") return cont(quasi);
|
||||||
|
return cont(maybeexpression, continueQuasi);
|
||||||
|
}
|
||||||
|
function continueQuasi(type) {
|
||||||
|
if (type == "}") {
|
||||||
|
cx.marked = "string-2";
|
||||||
|
cx.state.tokenize = tokenQuasi;
|
||||||
|
return cont(quasi);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function arrowBody(type) {
|
||||||
|
findFatArrow(cx.stream, cx.state);
|
||||||
|
return pass(type == "{" ? statement : expression);
|
||||||
|
}
|
||||||
|
function arrowBodyNoComma(type) {
|
||||||
|
findFatArrow(cx.stream, cx.state);
|
||||||
|
return pass(type == "{" ? statement : expressionNoComma);
|
||||||
|
}
|
||||||
|
function maybeTarget(noComma) {
|
||||||
|
return function(type) {
|
||||||
|
if (type == ".") return cont(noComma ? targetNoComma : target);
|
||||||
|
else if (type == "variable" && isTS) return cont(maybeTypeArgs, noComma ? maybeoperatorNoComma : maybeoperatorComma)
|
||||||
|
else return pass(noComma ? expressionNoComma : expression);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function target(_, value) {
|
||||||
|
if (value == "target") { cx.marked = "keyword"; return cont(maybeoperatorComma); }
|
||||||
|
}
|
||||||
|
function targetNoComma(_, value) {
|
||||||
|
if (value == "target") { cx.marked = "keyword"; return cont(maybeoperatorNoComma); }
|
||||||
|
}
|
||||||
|
function maybelabel(type) {
|
||||||
|
if (type == ":") return cont(poplex, statement);
|
||||||
|
return pass(maybeoperatorComma, expect(";"), poplex);
|
||||||
|
}
|
||||||
|
function property(type) {
|
||||||
|
if (type == "variable") {cx.marked = "property"; return cont();}
|
||||||
|
}
|
||||||
|
function objprop(type, value) {
|
||||||
|
if (type == "async") {
|
||||||
|
cx.marked = "property";
|
||||||
|
return cont(objprop);
|
||||||
|
} else if (type == "variable" || cx.style == "keyword") {
|
||||||
|
cx.marked = "property";
|
||||||
|
if (value == "get" || value == "set") return cont(getterSetter);
|
||||||
|
var m; // Work around fat-arrow-detection complication for detecting typescript typed arrow params
|
||||||
|
if (isTS && cx.state.fatArrowAt == cx.stream.start && (m = cx.stream.match(/^\s*:\s*/, false)))
|
||||||
|
cx.state.fatArrowAt = cx.stream.pos + m[0].length;
|
||||||
|
return cont(afterprop);
|
||||||
|
} else if (type == "number" || type == "string") {
|
||||||
|
cx.marked = jsonldMode ? "property" : (cx.style + " property");
|
||||||
|
return cont(afterprop);
|
||||||
|
} else if (type == "jsonld-keyword") {
|
||||||
|
return cont(afterprop);
|
||||||
|
} else if (isTS && isModifier(value)) {
|
||||||
|
cx.marked = "keyword";
|
||||||
|
return cont(objprop)
|
||||||
|
} else if (type == "[") {
|
||||||
|
return cont(expression, maybetype, expect("]"), afterprop);
|
||||||
|
} else if (type == "spread") {
|
||||||
|
return cont(expressionNoComma, afterprop);
|
||||||
|
} else if (value == "*") {
|
||||||
|
cx.marked = "keyword";
|
||||||
|
return cont(objprop);
|
||||||
|
} else if (type == ":") {
|
||||||
|
return pass(afterprop)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function getterSetter(type) {
|
||||||
|
if (type != "variable") return pass(afterprop);
|
||||||
|
cx.marked = "property";
|
||||||
|
return cont(functiondef);
|
||||||
|
}
|
||||||
|
function afterprop(type) {
|
||||||
|
if (type == ":") return cont(expressionNoComma);
|
||||||
|
if (type == "(") return pass(functiondef);
|
||||||
|
}
|
||||||
|
function commasep(what, end, sep) {
|
||||||
|
function proceed(type, value) {
|
||||||
|
if (sep ? sep.indexOf(type) > -1 : type == ",") {
|
||||||
|
var lex = cx.state.lexical;
|
||||||
|
if (lex.info == "call") lex.pos = (lex.pos || 0) + 1;
|
||||||
|
return cont(function(type, value) {
|
||||||
|
if (type == end || value == end) return pass()
|
||||||
|
return pass(what)
|
||||||
|
}, proceed);
|
||||||
|
}
|
||||||
|
if (type == end || value == end) return cont();
|
||||||
|
if (sep && sep.indexOf(";") > -1) return pass(what)
|
||||||
|
return cont(expect(end));
|
||||||
|
}
|
||||||
|
return function(type, value) {
|
||||||
|
if (type == end || value == end) return cont();
|
||||||
|
return pass(what, proceed);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function contCommasep(what, end, info) {
|
||||||
|
for (var i = 3; i < arguments.length; i++)
|
||||||
|
cx.cc.push(arguments[i]);
|
||||||
|
return cont(pushlex(end, info), commasep(what, end), poplex);
|
||||||
|
}
|
||||||
|
function block(type) {
|
||||||
|
if (type == "}") return cont();
|
||||||
|
return pass(statement, block);
|
||||||
|
}
|
||||||
|
function maybetype(type, value) {
|
||||||
|
if (isTS) {
|
||||||
|
if (type == ":") return cont(typeexpr);
|
||||||
|
if (value == "?") return cont(maybetype);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function maybetypeOrIn(type, value) {
|
||||||
|
if (isTS && (type == ":" || value == "in")) return cont(typeexpr)
|
||||||
|
}
|
||||||
|
function mayberettype(type) {
|
||||||
|
if (isTS && type == ":") {
|
||||||
|
if (cx.stream.match(/^\s*\w+\s+is\b/, false)) return cont(expression, isKW, typeexpr)
|
||||||
|
else return cont(typeexpr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function isKW(_, value) {
|
||||||
|
if (value == "is") {
|
||||||
|
cx.marked = "keyword";
|
||||||
|
return cont()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function typeexpr(type, value) {
|
||||||
|
if (value == "keyof" || value == "typeof" || value == "infer" || value == "readonly") {
|
||||||
|
cx.marked = "keyword";
|
||||||
|
return cont(value == "typeof" ? expressionNoComma : typeexpr)
|
||||||
|
}
|
||||||
|
if (type == "variable" || value == "void") {
|
||||||
|
cx.marked = "type";
|
||||||
|
return cont(afterType)
|
||||||
|
}
|
||||||
|
if (value == "|" || value == "&") return cont(typeexpr)
|
||||||
|
if (type == "string" || type == "number" || type == "atom") return cont(afterType);
|
||||||
|
if (type == "[") return cont(pushlex("]"), commasep(typeexpr, "]", ","), poplex, afterType)
|
||||||
|
if (type == "{") return cont(pushlex("}"), typeprops, poplex, afterType)
|
||||||
|
if (type == "(") return cont(commasep(typearg, ")"), maybeReturnType, afterType)
|
||||||
|
if (type == "<") return cont(commasep(typeexpr, ">"), typeexpr)
|
||||||
|
if (type == "quasi") { return pass(quasiType, afterType); }
|
||||||
|
}
|
||||||
|
function maybeReturnType(type) {
|
||||||
|
if (type == "=>") return cont(typeexpr)
|
||||||
|
}
|
||||||
|
function typeprops(type) {
|
||||||
|
if (type.match(/[\}\)\]]/)) return cont()
|
||||||
|
if (type == "," || type == ";") return cont(typeprops)
|
||||||
|
return pass(typeprop, typeprops)
|
||||||
|
}
|
||||||
|
function typeprop(type, value) {
|
||||||
|
if (type == "variable" || cx.style == "keyword") {
|
||||||
|
cx.marked = "property";
|
||||||
|
return cont(typeprop)
|
||||||
|
} else if (value == "?" || type == "number" || type == "string") {
|
||||||
|
return cont(typeprop)
|
||||||
|
} else if (type == ":") {
|
||||||
|
return cont(typeexpr)
|
||||||
|
} else if (type == "[") {
|
||||||
|
return cont(expect("variable"), maybetypeOrIn, expect("]"), typeprop)
|
||||||
|
} else if (type == "(") {
|
||||||
|
return pass(functiondecl, typeprop)
|
||||||
|
} else if (!type.match(/[;\}\)\],]/)) {
|
||||||
|
return cont()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function quasiType(type, value) {
|
||||||
|
if (type != "quasi") return pass();
|
||||||
|
if (value.slice(value.length - 2) != "${") return cont(quasiType);
|
||||||
|
return cont(typeexpr, continueQuasiType);
|
||||||
|
}
|
||||||
|
function continueQuasiType(type) {
|
||||||
|
if (type == "}") {
|
||||||
|
cx.marked = "string-2";
|
||||||
|
cx.state.tokenize = tokenQuasi;
|
||||||
|
return cont(quasiType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function typearg(type, value) {
|
||||||
|
if (type == "variable" && cx.stream.match(/^\s*[?:]/, false) || value == "?") return cont(typearg)
|
||||||
|
if (type == ":") return cont(typeexpr)
|
||||||
|
if (type == "spread") return cont(typearg)
|
||||||
|
return pass(typeexpr)
|
||||||
|
}
|
||||||
|
function afterType(type, value) {
|
||||||
|
if (value == "<") return cont(pushlex(">"), commasep(typeexpr, ">"), poplex, afterType)
|
||||||
|
if (value == "|" || type == "." || value == "&") return cont(typeexpr)
|
||||||
|
if (type == "[") return cont(typeexpr, expect("]"), afterType)
|
||||||
|
if (value == "extends" || value == "implements") { cx.marked = "keyword"; return cont(typeexpr) }
|
||||||
|
if (value == "?") return cont(typeexpr, expect(":"), typeexpr)
|
||||||
|
}
|
||||||
|
function maybeTypeArgs(_, value) {
|
||||||
|
if (value == "<") return cont(pushlex(">"), commasep(typeexpr, ">"), poplex, afterType)
|
||||||
|
}
|
||||||
|
function typeparam() {
|
||||||
|
return pass(typeexpr, maybeTypeDefault)
|
||||||
|
}
|
||||||
|
function maybeTypeDefault(_, value) {
|
||||||
|
if (value == "=") return cont(typeexpr)
|
||||||
|
}
|
||||||
|
function vardef(_, value) {
|
||||||
|
if (value == "enum") {cx.marked = "keyword"; return cont(enumdef)}
|
||||||
|
return pass(pattern, maybetype, maybeAssign, vardefCont);
|
||||||
|
}
|
||||||
|
function pattern(type, value) {
|
||||||
|
if (isTS && isModifier(value)) { cx.marked = "keyword"; return cont(pattern) }
|
||||||
|
if (type == "variable") { register(value); return cont(); }
|
||||||
|
if (type == "spread") return cont(pattern);
|
||||||
|
if (type == "[") return contCommasep(eltpattern, "]");
|
||||||
|
if (type == "{") return contCommasep(proppattern, "}");
|
||||||
|
}
|
||||||
|
function proppattern(type, value) {
|
||||||
|
if (type == "variable" && !cx.stream.match(/^\s*:/, false)) {
|
||||||
|
register(value);
|
||||||
|
return cont(maybeAssign);
|
||||||
|
}
|
||||||
|
if (type == "variable") cx.marked = "property";
|
||||||
|
if (type == "spread") return cont(pattern);
|
||||||
|
if (type == "}") return pass();
|
||||||
|
if (type == "[") return cont(expression, expect(']'), expect(':'), proppattern);
|
||||||
|
return cont(expect(":"), pattern, maybeAssign);
|
||||||
|
}
|
||||||
|
function eltpattern() {
|
||||||
|
return pass(pattern, maybeAssign)
|
||||||
|
}
|
||||||
|
function maybeAssign(_type, value) {
|
||||||
|
if (value == "=") return cont(expressionNoComma);
|
||||||
|
}
|
||||||
|
function vardefCont(type) {
|
||||||
|
if (type == ",") return cont(vardef);
|
||||||
|
}
|
||||||
|
function maybeelse(type, value) {
|
||||||
|
if (type == "keyword b" && value == "else") return cont(pushlex("form", "else"), statement, poplex);
|
||||||
|
}
|
||||||
|
function forspec(type, value) {
|
||||||
|
if (value == "await") return cont(forspec);
|
||||||
|
if (type == "(") return cont(pushlex(")"), forspec1, poplex);
|
||||||
|
}
|
||||||
|
function forspec1(type) {
|
||||||
|
if (type == "var") return cont(vardef, forspec2);
|
||||||
|
if (type == "variable") return cont(forspec2);
|
||||||
|
return pass(forspec2)
|
||||||
|
}
|
||||||
|
function forspec2(type, value) {
|
||||||
|
if (type == ")") return cont()
|
||||||
|
if (type == ";") return cont(forspec2)
|
||||||
|
if (value == "in" || value == "of") { cx.marked = "keyword"; return cont(expression, forspec2) }
|
||||||
|
return pass(expression, forspec2)
|
||||||
|
}
|
||||||
|
function functiondef(type, value) {
|
||||||
|
if (value == "*") {cx.marked = "keyword"; return cont(functiondef);}
|
||||||
|
if (type == "variable") {register(value); return cont(functiondef);}
|
||||||
|
if (type == "(") return cont(pushcontext, pushlex(")"), commasep(funarg, ")"), poplex, mayberettype, statement, popcontext);
|
||||||
|
if (isTS && value == "<") return cont(pushlex(">"), commasep(typeparam, ">"), poplex, functiondef)
|
||||||
|
}
|
||||||
|
function functiondecl(type, value) {
|
||||||
|
if (value == "*") {cx.marked = "keyword"; return cont(functiondecl);}
|
||||||
|
if (type == "variable") {register(value); return cont(functiondecl);}
|
||||||
|
if (type == "(") return cont(pushcontext, pushlex(")"), commasep(funarg, ")"), poplex, mayberettype, popcontext);
|
||||||
|
if (isTS && value == "<") return cont(pushlex(">"), commasep(typeparam, ">"), poplex, functiondecl)
|
||||||
|
}
|
||||||
|
function typename(type, value) {
|
||||||
|
if (type == "keyword" || type == "variable") {
|
||||||
|
cx.marked = "type";
|
||||||
|
return cont(typename)
|
||||||
|
} else if (value == "<") {
|
||||||
|
return cont(pushlex(">"), commasep(typeparam, ">"), poplex)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function funarg(type, value) {
|
||||||
|
if (value == "@") cont(expression, funarg);
|
||||||
|
if (type == "spread") return cont(funarg);
|
||||||
|
if (isTS && isModifier(value)) { cx.marked = "keyword"; return cont(funarg); }
|
||||||
|
if (isTS && type == "this") return cont(maybetype, maybeAssign)
|
||||||
|
return pass(pattern, maybetype, maybeAssign);
|
||||||
|
}
|
||||||
|
function classExpression(type, value) {
|
||||||
|
// Class expressions may have an optional name.
|
||||||
|
if (type == "variable") return className(type, value);
|
||||||
|
return classNameAfter(type, value);
|
||||||
|
}
|
||||||
|
function className(type, value) {
|
||||||
|
if (type == "variable") {register(value); return cont(classNameAfter);}
|
||||||
|
}
|
||||||
|
function classNameAfter(type, value) {
|
||||||
|
if (value == "<") return cont(pushlex(">"), commasep(typeparam, ">"), poplex, classNameAfter)
|
||||||
|
if (value == "extends" || value == "implements" || (isTS && type == ",")) {
|
||||||
|
if (value == "implements") cx.marked = "keyword";
|
||||||
|
return cont(isTS ? typeexpr : expression, classNameAfter);
|
||||||
|
}
|
||||||
|
if (type == "{") return cont(pushlex("}"), classBody, poplex);
|
||||||
|
}
|
||||||
|
function classBody(type, value) {
|
||||||
|
if (type == "async" ||
|
||||||
|
(type == "variable" &&
|
||||||
|
(value == "static" || value == "get" || value == "set" || (isTS && isModifier(value))) &&
|
||||||
|
cx.stream.match(/^\s+[\w$\xa1-\uffff]/, false))) {
|
||||||
|
cx.marked = "keyword";
|
||||||
|
return cont(classBody);
|
||||||
|
}
|
||||||
|
if (type == "variable" || cx.style == "keyword") {
|
||||||
|
cx.marked = "property";
|
||||||
|
return cont(classfield, classBody);
|
||||||
|
}
|
||||||
|
if (type == "number" || type == "string") return cont(classfield, classBody);
|
||||||
|
if (type == "[")
|
||||||
|
return cont(expression, maybetype, expect("]"), classfield, classBody)
|
||||||
|
if (value == "*") {
|
||||||
|
cx.marked = "keyword";
|
||||||
|
return cont(classBody);
|
||||||
|
}
|
||||||
|
if (isTS && type == "(") return pass(functiondecl, classBody)
|
||||||
|
if (type == ";" || type == ",") return cont(classBody);
|
||||||
|
if (type == "}") return cont();
|
||||||
|
if (value == "@") return cont(expression, classBody)
|
||||||
|
}
|
||||||
|
function classfield(type, value) {
|
||||||
|
if (value == "!") return cont(classfield)
|
||||||
|
if (value == "?") return cont(classfield)
|
||||||
|
if (type == ":") return cont(typeexpr, maybeAssign)
|
||||||
|
if (value == "=") return cont(expressionNoComma)
|
||||||
|
var context = cx.state.lexical.prev, isInterface = context && context.info == "interface";
|
||||||
|
return pass(isInterface ? functiondecl : functiondef)
|
||||||
|
}
|
||||||
|
function afterExport(type, value) {
|
||||||
|
if (value == "*") { cx.marked = "keyword"; return cont(maybeFrom, expect(";")); }
|
||||||
|
if (value == "default") { cx.marked = "keyword"; return cont(expression, expect(";")); }
|
||||||
|
if (type == "{") return cont(commasep(exportField, "}"), maybeFrom, expect(";"));
|
||||||
|
return pass(statement);
|
||||||
|
}
|
||||||
|
function exportField(type, value) {
|
||||||
|
if (value == "as") { cx.marked = "keyword"; return cont(expect("variable")); }
|
||||||
|
if (type == "variable") return pass(expressionNoComma, exportField);
|
||||||
|
}
|
||||||
|
function afterImport(type) {
|
||||||
|
if (type == "string") return cont();
|
||||||
|
if (type == "(") return pass(expression);
|
||||||
|
if (type == ".") return pass(maybeoperatorComma);
|
||||||
|
return pass(importSpec, maybeMoreImports, maybeFrom);
|
||||||
|
}
|
||||||
|
function importSpec(type, value) {
|
||||||
|
if (type == "{") return contCommasep(importSpec, "}");
|
||||||
|
if (type == "variable") register(value);
|
||||||
|
if (value == "*") cx.marked = "keyword";
|
||||||
|
return cont(maybeAs);
|
||||||
|
}
|
||||||
|
function maybeMoreImports(type) {
|
||||||
|
if (type == ",") return cont(importSpec, maybeMoreImports)
|
||||||
|
}
|
||||||
|
function maybeAs(_type, value) {
|
||||||
|
if (value == "as") { cx.marked = "keyword"; return cont(importSpec); }
|
||||||
|
}
|
||||||
|
function maybeFrom(_type, value) {
|
||||||
|
if (value == "from") { cx.marked = "keyword"; return cont(expression); }
|
||||||
|
}
|
||||||
|
function arrayLiteral(type) {
|
||||||
|
if (type == "]") return cont();
|
||||||
|
return pass(commasep(expressionNoComma, "]"));
|
||||||
|
}
|
||||||
|
function enumdef() {
|
||||||
|
return pass(pushlex("form"), pattern, expect("{"), pushlex("}"), commasep(enummember, "}"), poplex, poplex)
|
||||||
|
}
|
||||||
|
function enummember() {
|
||||||
|
return pass(pattern, maybeAssign);
|
||||||
|
}
|
||||||
|
|
||||||
|
function isContinuedStatement(state, textAfter) {
|
||||||
|
return state.lastType == "operator" || state.lastType == "," ||
|
||||||
|
isOperatorChar.test(textAfter.charAt(0)) ||
|
||||||
|
/[,.]/.test(textAfter.charAt(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
function expressionAllowed(stream, state, backUp) {
|
||||||
|
return state.tokenize == tokenBase &&
|
||||||
|
/^(?:operator|sof|keyword [bcd]|case|new|export|default|spread|[\[{}\(,;:]|=>)$/.test(state.lastType) ||
|
||||||
|
(state.lastType == "quasi" && /\{\s*$/.test(stream.string.slice(0, stream.pos - (backUp || 0))))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Interface
|
||||||
|
|
||||||
|
return {
|
||||||
|
startState: function(basecolumn) {
|
||||||
|
var state = {
|
||||||
|
tokenize: tokenBase,
|
||||||
|
lastType: "sof",
|
||||||
|
cc: [],
|
||||||
|
lexical: new JSLexical((basecolumn || 0) - indentUnit, 0, "block", false),
|
||||||
|
localVars: parserConfig.localVars,
|
||||||
|
context: parserConfig.localVars && new Context(null, null, false),
|
||||||
|
indented: basecolumn || 0
|
||||||
|
};
|
||||||
|
if (parserConfig.globalVars && typeof parserConfig.globalVars == "object")
|
||||||
|
state.globalVars = parserConfig.globalVars;
|
||||||
|
return state;
|
||||||
|
},
|
||||||
|
|
||||||
|
token: function(stream, state) {
|
||||||
|
if (stream.sol()) {
|
||||||
|
if (!state.lexical.hasOwnProperty("align"))
|
||||||
|
state.lexical.align = false;
|
||||||
|
state.indented = stream.indentation();
|
||||||
|
findFatArrow(stream, state);
|
||||||
|
}
|
||||||
|
if (state.tokenize != tokenComment && stream.eatSpace()) return null;
|
||||||
|
var style = state.tokenize(stream, state);
|
||||||
|
if (type == "comment") return style;
|
||||||
|
state.lastType = type == "operator" && (content == "++" || content == "--") ? "incdec" : type;
|
||||||
|
return parseJS(state, style, type, content, stream);
|
||||||
|
},
|
||||||
|
|
||||||
|
indent: function(state, textAfter) {
|
||||||
|
if (state.tokenize == tokenComment || state.tokenize == tokenQuasi) return CodeMirror.Pass;
|
||||||
|
if (state.tokenize != tokenBase) return 0;
|
||||||
|
var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical, top;
|
||||||
|
// Kludge to prevent 'maybelse' from blocking lexical scope pops
|
||||||
|
if (!/^\s*else\b/.test(textAfter)) for (var i = state.cc.length - 1; i >= 0; --i) {
|
||||||
|
var c = state.cc[i];
|
||||||
|
if (c == poplex) lexical = lexical.prev;
|
||||||
|
else if (c != maybeelse && c != popcontext) break;
|
||||||
|
}
|
||||||
|
while ((lexical.type == "stat" || lexical.type == "form") &&
|
||||||
|
(firstChar == "}" || ((top = state.cc[state.cc.length - 1]) &&
|
||||||
|
(top == maybeoperatorComma || top == maybeoperatorNoComma) &&
|
||||||
|
!/^[,\.=+\-*:?[\(]/.test(textAfter))))
|
||||||
|
lexical = lexical.prev;
|
||||||
|
if (statementIndent && lexical.type == ")" && lexical.prev.type == "stat")
|
||||||
|
lexical = lexical.prev;
|
||||||
|
var type = lexical.type, closing = firstChar == type;
|
||||||
|
|
||||||
|
if (type == "vardef") return lexical.indented + (state.lastType == "operator" || state.lastType == "," ? lexical.info.length + 1 : 0);
|
||||||
|
else if (type == "form" && firstChar == "{") return lexical.indented;
|
||||||
|
else if (type == "form") return lexical.indented + indentUnit;
|
||||||
|
else if (type == "stat")
|
||||||
|
return lexical.indented + (isContinuedStatement(state, textAfter) ? statementIndent || indentUnit : 0);
|
||||||
|
else if (lexical.info == "switch" && !closing && parserConfig.doubleIndentSwitch != false)
|
||||||
|
return lexical.indented + (/^(?:case|default)\b/.test(textAfter) ? indentUnit : 2 * indentUnit);
|
||||||
|
else if (lexical.align) return lexical.column + (closing ? 0 : 1);
|
||||||
|
else return lexical.indented + (closing ? 0 : indentUnit);
|
||||||
|
},
|
||||||
|
|
||||||
|
electricInput: /^\s*(?:case .*?:|default:|\{|\})$/,
|
||||||
|
blockCommentStart: jsonMode ? null : "/*",
|
||||||
|
blockCommentEnd: jsonMode ? null : "*/",
|
||||||
|
blockCommentContinue: jsonMode ? null : " * ",
|
||||||
|
lineComment: jsonMode ? null : "//",
|
||||||
|
fold: "brace",
|
||||||
|
closeBrackets: "()[]{}''\"\"``",
|
||||||
|
|
||||||
|
helperType: jsonMode ? "json" : "javascript",
|
||||||
|
jsonldMode: jsonldMode,
|
||||||
|
jsonMode: jsonMode,
|
||||||
|
|
||||||
|
expressionAllowed: expressionAllowed,
|
||||||
|
|
||||||
|
skipExpression: function(state) {
|
||||||
|
parseJS(state, "atom", "atom", "true", new CodeMirror.StringStream("", 2, null));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
CodeMirror.registerHelper("wordChars", "javascript", /[\w$]/);
|
||||||
|
|
||||||
|
CodeMirror.defineMIME("text/javascript", "javascript");
|
||||||
|
CodeMirror.defineMIME("text/ecmascript", "javascript");
|
||||||
|
CodeMirror.defineMIME("application/javascript", "javascript");
|
||||||
|
CodeMirror.defineMIME("application/x-javascript", "javascript");
|
||||||
|
CodeMirror.defineMIME("application/ecmascript", "javascript");
|
||||||
|
CodeMirror.defineMIME("application/json", { name: "javascript", json: true });
|
||||||
|
CodeMirror.defineMIME("application/x-json", { name: "javascript", json: true });
|
||||||
|
CodeMirror.defineMIME("application/manifest+json", { name: "javascript", json: true });
|
||||||
|
CodeMirror.defineMIME("application/ld+json", { name: "javascript", jsonld: true });
|
||||||
|
CodeMirror.defineMIME("text/typescript", { name: "javascript", typescript: true });
|
||||||
|
CodeMirror.defineMIME("application/typescript", { name: "javascript", typescript: true });
|
||||||
|
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
export default javascript;
|
||||||
115
docs/_snowpack/pkg/codemirror/mode/pegjs/pegjs.js
vendored
Normal file
115
docs/_snowpack/pkg/codemirror/mode/pegjs/pegjs.js
vendored
Normal file
|
|
@ -0,0 +1,115 @@
|
||||||
|
import { c as createCommonjsModule } from '../../../common/_commonjsHelpers-8c19dec8.js';
|
||||||
|
import { c as codemirror } from '../../../common/codemirror-d650d44d.js';
|
||||||
|
import javascript from '../javascript/javascript.js';
|
||||||
|
|
||||||
|
var pegjs = createCommonjsModule(function (module, exports) {
|
||||||
|
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||||
|
// Distributed under an MIT license: https://codemirror.net/LICENSE
|
||||||
|
|
||||||
|
(function(mod) {
|
||||||
|
mod(codemirror, javascript);
|
||||||
|
})(function(CodeMirror) {
|
||||||
|
|
||||||
|
CodeMirror.defineMode("pegjs", function (config) {
|
||||||
|
var jsMode = CodeMirror.getMode(config, "javascript");
|
||||||
|
|
||||||
|
function identifier(stream) {
|
||||||
|
return stream.match(/^[a-zA-Z_][a-zA-Z0-9_]*/);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
startState: function () {
|
||||||
|
return {
|
||||||
|
inString: false,
|
||||||
|
stringType: null,
|
||||||
|
inComment: false,
|
||||||
|
inCharacterClass: false,
|
||||||
|
braced: 0,
|
||||||
|
lhs: true,
|
||||||
|
localState: null
|
||||||
|
};
|
||||||
|
},
|
||||||
|
token: function (stream, state) {
|
||||||
|
if (stream)
|
||||||
|
|
||||||
|
//check for state changes
|
||||||
|
if (!state.inString && !state.inComment && ((stream.peek() == '"') || (stream.peek() == "'"))) {
|
||||||
|
state.stringType = stream.peek();
|
||||||
|
stream.next(); // Skip quote
|
||||||
|
state.inString = true; // Update state
|
||||||
|
}
|
||||||
|
if (!state.inString && !state.inComment && stream.match('/*')) {
|
||||||
|
state.inComment = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//return state
|
||||||
|
if (state.inString) {
|
||||||
|
while (state.inString && !stream.eol()) {
|
||||||
|
if (stream.peek() === state.stringType) {
|
||||||
|
stream.next(); // Skip quote
|
||||||
|
state.inString = false; // Clear flag
|
||||||
|
} else if (stream.peek() === '\\') {
|
||||||
|
stream.next();
|
||||||
|
stream.next();
|
||||||
|
} else {
|
||||||
|
stream.match(/^.[^\\\"\']*/);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return state.lhs ? "property string" : "string"; // Token style
|
||||||
|
} else if (state.inComment) {
|
||||||
|
while (state.inComment && !stream.eol()) {
|
||||||
|
if (stream.match('*/')) {
|
||||||
|
state.inComment = false; // Clear flag
|
||||||
|
} else {
|
||||||
|
stream.match(/^.[^\*]*/);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "comment";
|
||||||
|
} else if (state.inCharacterClass) {
|
||||||
|
while (state.inCharacterClass && !stream.eol()) {
|
||||||
|
if (!(stream.match(/^[^\]\\]+/) || stream.match(/^\\./))) {
|
||||||
|
state.inCharacterClass = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (stream.peek() === '[') {
|
||||||
|
stream.next();
|
||||||
|
state.inCharacterClass = true;
|
||||||
|
return 'bracket';
|
||||||
|
} else if (stream.match('//')) {
|
||||||
|
stream.skipToEnd();
|
||||||
|
return "comment";
|
||||||
|
} else if (state.braced || stream.peek() === '{') {
|
||||||
|
if (state.localState === null) {
|
||||||
|
state.localState = CodeMirror.startState(jsMode);
|
||||||
|
}
|
||||||
|
var token = jsMode.token(stream, state.localState);
|
||||||
|
var text = stream.current();
|
||||||
|
if (!token) {
|
||||||
|
for (var i = 0; i < text.length; i++) {
|
||||||
|
if (text[i] === '{') {
|
||||||
|
state.braced++;
|
||||||
|
} else if (text[i] === '}') {
|
||||||
|
state.braced--;
|
||||||
|
}
|
||||||
|
} }
|
||||||
|
return token;
|
||||||
|
} else if (identifier(stream)) {
|
||||||
|
if (stream.peek() === ':') {
|
||||||
|
return 'variable';
|
||||||
|
}
|
||||||
|
return 'variable-2';
|
||||||
|
} else if (['[', ']', '(', ')'].indexOf(stream.peek()) != -1) {
|
||||||
|
stream.next();
|
||||||
|
return 'bracket';
|
||||||
|
} else if (!stream.eatSpace()) {
|
||||||
|
stream.next();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}, "javascript");
|
||||||
|
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
export default pegjs;
|
||||||
141
docs/_snowpack/pkg/codemirror/theme/material.css
vendored
Normal file
141
docs/_snowpack/pkg/codemirror/theme/material.css
vendored
Normal file
|
|
@ -0,0 +1,141 @@
|
||||||
|
/*
|
||||||
|
Name: material
|
||||||
|
Author: Mattia Astorino (http://github.com/equinusocio)
|
||||||
|
Website: https://material-theme.site/
|
||||||
|
*/
|
||||||
|
|
||||||
|
.cm-s-material.CodeMirror {
|
||||||
|
background-color: #263238;
|
||||||
|
color: #EEFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cm-s-material .CodeMirror-gutters {
|
||||||
|
background: #263238;
|
||||||
|
color: #546E7A;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cm-s-material .CodeMirror-guttermarker,
|
||||||
|
.cm-s-material .CodeMirror-guttermarker-subtle,
|
||||||
|
.cm-s-material .CodeMirror-linenumber {
|
||||||
|
color: #546E7A;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cm-s-material .CodeMirror-cursor {
|
||||||
|
border-left: 1px solid #FFCC00;
|
||||||
|
}
|
||||||
|
.cm-s-material.cm-fat-cursor .CodeMirror-cursor {
|
||||||
|
background-color: #5d6d5c80 !important;
|
||||||
|
}
|
||||||
|
.cm-s-material .cm-animate-fat-cursor {
|
||||||
|
background-color: #5d6d5c80 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cm-s-material div.CodeMirror-selected {
|
||||||
|
background: rgba(128, 203, 196, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.cm-s-material.CodeMirror-focused div.CodeMirror-selected {
|
||||||
|
background: rgba(128, 203, 196, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.cm-s-material .CodeMirror-line::selection,
|
||||||
|
.cm-s-material .CodeMirror-line>span::selection,
|
||||||
|
.cm-s-material .CodeMirror-line>span>span::selection {
|
||||||
|
background: rgba(128, 203, 196, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.cm-s-material .CodeMirror-line::-moz-selection,
|
||||||
|
.cm-s-material .CodeMirror-line>span::-moz-selection,
|
||||||
|
.cm-s-material .CodeMirror-line>span>span::-moz-selection {
|
||||||
|
background: rgba(128, 203, 196, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.cm-s-material .CodeMirror-activeline-background {
|
||||||
|
background: rgba(0, 0, 0, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
.cm-s-material .cm-keyword {
|
||||||
|
color: #C792EA;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cm-s-material .cm-operator {
|
||||||
|
color: #89DDFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cm-s-material .cm-variable-2 {
|
||||||
|
color: #EEFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cm-s-material .cm-variable-3,
|
||||||
|
.cm-s-material .cm-type {
|
||||||
|
color: #f07178;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cm-s-material .cm-builtin {
|
||||||
|
color: #FFCB6B;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cm-s-material .cm-atom {
|
||||||
|
color: #F78C6C;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cm-s-material .cm-number {
|
||||||
|
color: #FF5370;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cm-s-material .cm-def {
|
||||||
|
color: #82AAFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cm-s-material .cm-string {
|
||||||
|
color: #C3E88D;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cm-s-material .cm-string-2 {
|
||||||
|
color: #f07178;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cm-s-material .cm-comment {
|
||||||
|
color: #546E7A;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cm-s-material .cm-variable {
|
||||||
|
color: #f07178;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cm-s-material .cm-tag {
|
||||||
|
color: #FF5370;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cm-s-material .cm-meta {
|
||||||
|
color: #FFCB6B;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cm-s-material .cm-attribute {
|
||||||
|
color: #C792EA;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cm-s-material .cm-property {
|
||||||
|
color: #C792EA;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cm-s-material .cm-qualifier {
|
||||||
|
color: #DECB6B;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cm-s-material .cm-variable-3,
|
||||||
|
.cm-s-material .cm-type {
|
||||||
|
color: #DECB6B;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.cm-s-material .cm-error {
|
||||||
|
color: rgba(255, 255, 255, 1.0);
|
||||||
|
background-color: #FF5370;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cm-s-material .CodeMirror-matchingbracket {
|
||||||
|
text-decoration: underline;
|
||||||
|
color: white !important;
|
||||||
|
}
|
||||||
10
docs/_snowpack/pkg/codemirror/theme/material.css.proxy.js
vendored
Normal file
10
docs/_snowpack/pkg/codemirror/theme/material.css.proxy.js
vendored
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
// [snowpack] add styles to the page (skip if no document exists)
|
||||||
|
if (typeof document !== 'undefined') {
|
||||||
|
const code = "/*\n Name: material\n Author: Mattia Astorino (http://github.com/equinusocio)\n Website: https://material-theme.site/\n*/\n\n.cm-s-material.CodeMirror {\n background-color: #263238;\n color: #EEFFFF;\n}\n\n.cm-s-material .CodeMirror-gutters {\n background: #263238;\n color: #546E7A;\n border: none;\n}\n\n.cm-s-material .CodeMirror-guttermarker,\n.cm-s-material .CodeMirror-guttermarker-subtle,\n.cm-s-material .CodeMirror-linenumber {\n color: #546E7A;\n}\n\n.cm-s-material .CodeMirror-cursor {\n border-left: 1px solid #FFCC00;\n}\n.cm-s-material.cm-fat-cursor .CodeMirror-cursor {\n background-color: #5d6d5c80 !important;\n}\n.cm-s-material .cm-animate-fat-cursor {\n background-color: #5d6d5c80 !important;\n}\n\n.cm-s-material div.CodeMirror-selected {\n background: rgba(128, 203, 196, 0.2);\n}\n\n.cm-s-material.CodeMirror-focused div.CodeMirror-selected {\n background: rgba(128, 203, 196, 0.2);\n}\n\n.cm-s-material .CodeMirror-line::selection,\n.cm-s-material .CodeMirror-line>span::selection,\n.cm-s-material .CodeMirror-line>span>span::selection {\n background: rgba(128, 203, 196, 0.2);\n}\n\n.cm-s-material .CodeMirror-line::-moz-selection,\n.cm-s-material .CodeMirror-line>span::-moz-selection,\n.cm-s-material .CodeMirror-line>span>span::-moz-selection {\n background: rgba(128, 203, 196, 0.2);\n}\n\n.cm-s-material .CodeMirror-activeline-background {\n background: rgba(0, 0, 0, 0.5);\n}\n\n.cm-s-material .cm-keyword {\n color: #C792EA;\n}\n\n.cm-s-material .cm-operator {\n color: #89DDFF;\n}\n\n.cm-s-material .cm-variable-2 {\n color: #EEFFFF;\n}\n\n.cm-s-material .cm-variable-3,\n.cm-s-material .cm-type {\n color: #f07178;\n}\n\n.cm-s-material .cm-builtin {\n color: #FFCB6B;\n}\n\n.cm-s-material .cm-atom {\n color: #F78C6C;\n}\n\n.cm-s-material .cm-number {\n color: #FF5370;\n}\n\n.cm-s-material .cm-def {\n color: #82AAFF;\n}\n\n.cm-s-material .cm-string {\n color: #C3E88D;\n}\n\n.cm-s-material .cm-string-2 {\n color: #f07178;\n}\n\n.cm-s-material .cm-comment {\n color: #546E7A;\n}\n\n.cm-s-material .cm-variable {\n color: #f07178;\n}\n\n.cm-s-material .cm-tag {\n color: #FF5370;\n}\n\n.cm-s-material .cm-meta {\n color: #FFCB6B;\n}\n\n.cm-s-material .cm-attribute {\n color: #C792EA;\n}\n\n.cm-s-material .cm-property {\n color: #C792EA;\n}\n\n.cm-s-material .cm-qualifier {\n color: #DECB6B;\n}\n\n.cm-s-material .cm-variable-3,\n.cm-s-material .cm-type {\n color: #DECB6B;\n}\n\n\n.cm-s-material .cm-error {\n color: rgba(255, 255, 255, 1.0);\n background-color: #FF5370;\n}\n\n.cm-s-material .CodeMirror-matchingbracket {\n text-decoration: underline;\n color: white !important;\n}\n";
|
||||||
|
|
||||||
|
const styleEl = document.createElement("style");
|
||||||
|
const codeEl = document.createTextNode(code);
|
||||||
|
styleEl.type = 'text/css';
|
||||||
|
styleEl.appendChild(codeEl);
|
||||||
|
document.head.appendChild(styleEl);
|
||||||
|
}
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
|
||||||
|
|
||||||
function getDefaultExportFromCjs (x) {
|
function getDefaultExportFromCjs (x) {
|
||||||
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
|
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
|
||||||
}
|
}
|
||||||
|
|
@ -16,4 +18,4 @@ function commonjsRequire () {
|
||||||
throw new Error('Dynamic requires are not currently supported by @rollup/plugin-commonjs');
|
throw new Error('Dynamic requires are not currently supported by @rollup/plugin-commonjs');
|
||||||
}
|
}
|
||||||
|
|
||||||
export { createCommonjsModule as c, getDefaultExportFromCjs as g };
|
export { commonjsGlobal as a, createCommonjsModule as c, getDefaultExportFromCjs as g };
|
||||||
9852
docs/_snowpack/pkg/common/codemirror-d650d44d.js
Normal file
9852
docs/_snowpack/pkg/common/codemirror-d650d44d.js
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -1,4 +1,4 @@
|
||||||
import { c as createCommonjsModule } from './_commonjsHelpers-913f9c4a.js';
|
import { c as createCommonjsModule } from './_commonjsHelpers-8c19dec8.js';
|
||||||
|
|
||||||
/*
|
/*
|
||||||
object-assign
|
object-assign
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { g as getDefaultExportFromCjs, c as createCommonjsModule } from './common/_commonjsHelpers-913f9c4a.js';
|
import { g as getDefaultExportFromCjs, c as createCommonjsModule } from './common/_commonjsHelpers-8c19dec8.js';
|
||||||
|
|
||||||
var fraction = createCommonjsModule(function (module, exports) {
|
var fraction = createCommonjsModule(function (module, exports) {
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,13 @@
|
||||||
{
|
{
|
||||||
"imports": {
|
"imports": {
|
||||||
|
"@tonaljs/tonal": "./@tonaljs/tonal.js",
|
||||||
|
"codemirror/lib/codemirror.css": "./codemirror/lib/codemirror.css",
|
||||||
|
"codemirror/mode/javascript/javascript.js": "./codemirror/mode/javascript/javascript.js",
|
||||||
|
"codemirror/mode/pegjs/pegjs.js": "./codemirror/mode/pegjs/pegjs.js",
|
||||||
|
"codemirror/theme/material.css": "./codemirror/theme/material.css",
|
||||||
"fraction.js": "./fractionjs.js",
|
"fraction.js": "./fractionjs.js",
|
||||||
"react": "./react.js",
|
"react": "./react.js",
|
||||||
|
"react-codemirror2": "./react-codemirror2.js",
|
||||||
"react-dom": "./react-dom.js",
|
"react-dom": "./react-dom.js",
|
||||||
"tone": "./tone.js"
|
"tone": "./tone.js"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
788
docs/_snowpack/pkg/react-codemirror2.js
vendored
Normal file
788
docs/_snowpack/pkg/react-codemirror2.js
vendored
Normal file
|
|
@ -0,0 +1,788 @@
|
||||||
|
import { c as createCommonjsModule, a as commonjsGlobal } from './common/_commonjsHelpers-8c19dec8.js';
|
||||||
|
import { r as react } from './common/index-04edb6a1.js';
|
||||||
|
import { c as codemirror } from './common/codemirror-d650d44d.js';
|
||||||
|
|
||||||
|
var reactCodemirror2 = createCommonjsModule(function (module, exports) {
|
||||||
|
|
||||||
|
function _extends() {
|
||||||
|
_extends = Object.assign || function(target) {
|
||||||
|
for (var i = 1; i < arguments.length; i++) {
|
||||||
|
var source = arguments[i];
|
||||||
|
for (var key in source) {
|
||||||
|
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
||||||
|
target[key] = source[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return target;
|
||||||
|
};
|
||||||
|
return _extends.apply(this, arguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
function _typeof(obj) {
|
||||||
|
"@babel/helpers - typeof";
|
||||||
|
if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
|
||||||
|
_typeof = function _typeof(obj) {
|
||||||
|
return typeof obj;
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
_typeof = function _typeof(obj) {
|
||||||
|
return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return _typeof(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
var __extends = function() {
|
||||||
|
var _extendStatics = function extendStatics(d, b) {
|
||||||
|
_extendStatics = Object.setPrototypeOf || {
|
||||||
|
__proto__: []
|
||||||
|
}
|
||||||
|
instanceof Array && function(d, b) {
|
||||||
|
d.__proto__ = b;
|
||||||
|
} || function(d, b) {
|
||||||
|
for (var p in b) {
|
||||||
|
if (b.hasOwnProperty(p)) d[p] = b[p];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return _extendStatics(d, b);
|
||||||
|
};
|
||||||
|
|
||||||
|
return function(d, b) {
|
||||||
|
_extendStatics(d, b);
|
||||||
|
|
||||||
|
function __() {
|
||||||
|
this.constructor = d;
|
||||||
|
}
|
||||||
|
|
||||||
|
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
||||||
|
};
|
||||||
|
}();
|
||||||
|
|
||||||
|
Object.defineProperty(exports, '__esModule', {
|
||||||
|
value: true
|
||||||
|
});
|
||||||
|
exports.UnControlled = exports.Controlled = void 0;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
var SERVER_RENDERED = typeof navigator === 'undefined' || commonjsGlobal['PREVENT_CODEMIRROR_RENDER'] === true;
|
||||||
|
var cm;
|
||||||
|
|
||||||
|
if (!SERVER_RENDERED) {
|
||||||
|
cm = codemirror;
|
||||||
|
}
|
||||||
|
|
||||||
|
var Helper = function() {
|
||||||
|
function Helper() {}
|
||||||
|
|
||||||
|
Helper.equals = function(x, y) {
|
||||||
|
var _this = this;
|
||||||
|
|
||||||
|
var ok = Object.keys,
|
||||||
|
tx = _typeof(x),
|
||||||
|
ty = _typeof(y);
|
||||||
|
|
||||||
|
return x && y && tx === 'object' && tx === ty ? ok(x).length === ok(y).length && ok(x).every(function(key) {
|
||||||
|
return _this.equals(x[key], y[key]);
|
||||||
|
}) : x === y;
|
||||||
|
};
|
||||||
|
|
||||||
|
return Helper;
|
||||||
|
}();
|
||||||
|
|
||||||
|
var Shared = function() {
|
||||||
|
function Shared(editor, props) {
|
||||||
|
this.editor = editor;
|
||||||
|
this.props = props;
|
||||||
|
}
|
||||||
|
|
||||||
|
Shared.prototype.delegateCursor = function(position, scroll, focus) {
|
||||||
|
var doc = this.editor.getDoc();
|
||||||
|
|
||||||
|
if (focus) {
|
||||||
|
this.editor.focus();
|
||||||
|
}
|
||||||
|
|
||||||
|
scroll ? doc.setCursor(position) : doc.setCursor(position, null, {
|
||||||
|
scroll: false
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
Shared.prototype.delegateScroll = function(coordinates) {
|
||||||
|
this.editor.scrollTo(coordinates.x, coordinates.y);
|
||||||
|
};
|
||||||
|
|
||||||
|
Shared.prototype.delegateSelection = function(ranges, focus) {
|
||||||
|
var doc = this.editor.getDoc();
|
||||||
|
doc.setSelections(ranges);
|
||||||
|
|
||||||
|
if (focus) {
|
||||||
|
this.editor.focus();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Shared.prototype.apply = function(props) {
|
||||||
|
if (props && props.selection && props.selection.ranges) {
|
||||||
|
this.delegateSelection(props.selection.ranges, props.selection.focus || false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (props && props.cursor) {
|
||||||
|
this.delegateCursor(props.cursor, props.autoScroll || false, this.editor.getOption('autofocus') || false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (props && props.scroll) {
|
||||||
|
this.delegateScroll(props.scroll);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Shared.prototype.applyNext = function(props, next, preserved) {
|
||||||
|
if (props && props.selection && props.selection.ranges) {
|
||||||
|
if (next && next.selection && next.selection.ranges && !Helper.equals(props.selection.ranges, next.selection.ranges)) {
|
||||||
|
this.delegateSelection(next.selection.ranges, next.selection.focus || false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (props && props.cursor) {
|
||||||
|
if (next && next.cursor && !Helper.equals(props.cursor, next.cursor)) {
|
||||||
|
this.delegateCursor(preserved.cursor || next.cursor, next.autoScroll || false, next.autoCursor || false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (props && props.scroll) {
|
||||||
|
if (next && next.scroll && !Helper.equals(props.scroll, next.scroll)) {
|
||||||
|
this.delegateScroll(next.scroll);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Shared.prototype.applyUserDefined = function(props, preserved) {
|
||||||
|
if (preserved && preserved.cursor) {
|
||||||
|
this.delegateCursor(preserved.cursor, props.autoScroll || false, this.editor.getOption('autofocus') || false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Shared.prototype.wire = function(props) {
|
||||||
|
var _this = this;
|
||||||
|
|
||||||
|
Object.keys(props || {}).filter(function(p) {
|
||||||
|
return /^on/.test(p);
|
||||||
|
}).forEach(function(prop) {
|
||||||
|
switch (prop) {
|
||||||
|
case 'onBlur': {
|
||||||
|
_this.editor.on('blur', function(cm, event) {
|
||||||
|
_this.props.onBlur(_this.editor, event);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'onContextMenu': {
|
||||||
|
_this.editor.on('contextmenu', function(cm, event) {
|
||||||
|
_this.props.onContextMenu(_this.editor, event);
|
||||||
|
});
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'onCopy': {
|
||||||
|
_this.editor.on('copy', function(cm, event) {
|
||||||
|
_this.props.onCopy(_this.editor, event);
|
||||||
|
});
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'onCursor': {
|
||||||
|
_this.editor.on('cursorActivity', function(cm) {
|
||||||
|
_this.props.onCursor(_this.editor, _this.editor.getDoc().getCursor());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'onCursorActivity': {
|
||||||
|
_this.editor.on('cursorActivity', function(cm) {
|
||||||
|
_this.props.onCursorActivity(_this.editor);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'onCut': {
|
||||||
|
_this.editor.on('cut', function(cm, event) {
|
||||||
|
_this.props.onCut(_this.editor, event);
|
||||||
|
});
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'onDblClick': {
|
||||||
|
_this.editor.on('dblclick', function(cm, event) {
|
||||||
|
_this.props.onDblClick(_this.editor, event);
|
||||||
|
});
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'onDragEnter': {
|
||||||
|
_this.editor.on('dragenter', function(cm, event) {
|
||||||
|
_this.props.onDragEnter(_this.editor, event);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'onDragLeave': {
|
||||||
|
_this.editor.on('dragleave', function(cm, event) {
|
||||||
|
_this.props.onDragLeave(_this.editor, event);
|
||||||
|
});
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'onDragOver': {
|
||||||
|
_this.editor.on('dragover', function(cm, event) {
|
||||||
|
_this.props.onDragOver(_this.editor, event);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'onDragStart': {
|
||||||
|
_this.editor.on('dragstart', function(cm, event) {
|
||||||
|
_this.props.onDragStart(_this.editor, event);
|
||||||
|
});
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'onDrop': {
|
||||||
|
_this.editor.on('drop', function(cm, event) {
|
||||||
|
_this.props.onDrop(_this.editor, event);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'onFocus': {
|
||||||
|
_this.editor.on('focus', function(cm, event) {
|
||||||
|
_this.props.onFocus(_this.editor, event);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'onGutterClick': {
|
||||||
|
_this.editor.on('gutterClick', function(cm, lineNumber, gutter, event) {
|
||||||
|
_this.props.onGutterClick(_this.editor, lineNumber, gutter, event);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'onInputRead': {
|
||||||
|
_this.editor.on('inputRead', function(cm, EditorChangeEvent) {
|
||||||
|
_this.props.onInputRead(_this.editor, EditorChangeEvent);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'onKeyDown': {
|
||||||
|
_this.editor.on('keydown', function(cm, event) {
|
||||||
|
_this.props.onKeyDown(_this.editor, event);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'onKeyHandled': {
|
||||||
|
_this.editor.on('keyHandled', function(cm, key, event) {
|
||||||
|
_this.props.onKeyHandled(_this.editor, key, event);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'onKeyPress': {
|
||||||
|
_this.editor.on('keypress', function(cm, event) {
|
||||||
|
_this.props.onKeyPress(_this.editor, event);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'onKeyUp': {
|
||||||
|
_this.editor.on('keyup', function(cm, event) {
|
||||||
|
_this.props.onKeyUp(_this.editor, event);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'onMouseDown': {
|
||||||
|
_this.editor.on('mousedown', function(cm, event) {
|
||||||
|
_this.props.onMouseDown(_this.editor, event);
|
||||||
|
});
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'onPaste': {
|
||||||
|
_this.editor.on('paste', function(cm, event) {
|
||||||
|
_this.props.onPaste(_this.editor, event);
|
||||||
|
});
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'onRenderLine': {
|
||||||
|
_this.editor.on('renderLine', function(cm, line, element) {
|
||||||
|
_this.props.onRenderLine(_this.editor, line, element);
|
||||||
|
});
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'onScroll': {
|
||||||
|
_this.editor.on('scroll', function(cm) {
|
||||||
|
_this.props.onScroll(_this.editor, _this.editor.getScrollInfo());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'onSelection': {
|
||||||
|
_this.editor.on('beforeSelectionChange', function(cm, data) {
|
||||||
|
_this.props.onSelection(_this.editor, data);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'onTouchStart': {
|
||||||
|
_this.editor.on('touchstart', function(cm, event) {
|
||||||
|
_this.props.onTouchStart(_this.editor, event);
|
||||||
|
});
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'onUpdate': {
|
||||||
|
_this.editor.on('update', function(cm) {
|
||||||
|
_this.props.onUpdate(_this.editor);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'onViewportChange': {
|
||||||
|
_this.editor.on('viewportChange', function(cm, from, to) {
|
||||||
|
_this.props.onViewportChange(_this.editor, from, to);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return Shared;
|
||||||
|
}();
|
||||||
|
|
||||||
|
var Controlled = function(_super) {
|
||||||
|
__extends(Controlled, _super);
|
||||||
|
|
||||||
|
function Controlled(props) {
|
||||||
|
var _this = _super.call(this, props) || this;
|
||||||
|
|
||||||
|
if (SERVER_RENDERED) return _this;
|
||||||
|
_this.applied = false;
|
||||||
|
_this.appliedNext = false;
|
||||||
|
_this.appliedUserDefined = false;
|
||||||
|
_this.deferred = null;
|
||||||
|
_this.emulating = false;
|
||||||
|
_this.hydrated = false;
|
||||||
|
|
||||||
|
_this.initCb = function() {
|
||||||
|
if (_this.props.editorDidConfigure) {
|
||||||
|
_this.props.editorDidConfigure(_this.editor);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
_this.mounted = false;
|
||||||
|
return _this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Controlled.prototype.hydrate = function(props) {
|
||||||
|
var _this = this;
|
||||||
|
|
||||||
|
var _options = props && props.options ? props.options : {};
|
||||||
|
|
||||||
|
var userDefinedOptions = _extends({}, cm.defaults, this.editor.options, _options);
|
||||||
|
|
||||||
|
var optionDelta = Object.keys(userDefinedOptions).some(function(key) {
|
||||||
|
return _this.editor.getOption(key) !== userDefinedOptions[key];
|
||||||
|
});
|
||||||
|
|
||||||
|
if (optionDelta) {
|
||||||
|
Object.keys(userDefinedOptions).forEach(function(key) {
|
||||||
|
if (_options.hasOwnProperty(key)) {
|
||||||
|
if (_this.editor.getOption(key) !== userDefinedOptions[key]) {
|
||||||
|
_this.editor.setOption(key, userDefinedOptions[key]);
|
||||||
|
|
||||||
|
_this.mirror.setOption(key, userDefinedOptions[key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.hydrated) {
|
||||||
|
this.deferred ? this.resolveChange(props.value) : this.initChange(props.value || '');
|
||||||
|
}
|
||||||
|
|
||||||
|
this.hydrated = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
Controlled.prototype.initChange = function(value) {
|
||||||
|
this.emulating = true;
|
||||||
|
var doc = this.editor.getDoc();
|
||||||
|
var lastLine = doc.lastLine();
|
||||||
|
var lastChar = doc.getLine(doc.lastLine()).length;
|
||||||
|
doc.replaceRange(value || '', {
|
||||||
|
line: 0,
|
||||||
|
ch: 0
|
||||||
|
}, {
|
||||||
|
line: lastLine,
|
||||||
|
ch: lastChar
|
||||||
|
});
|
||||||
|
this.mirror.setValue(value);
|
||||||
|
doc.clearHistory();
|
||||||
|
this.mirror.clearHistory();
|
||||||
|
this.emulating = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
Controlled.prototype.resolveChange = function(value) {
|
||||||
|
this.emulating = true;
|
||||||
|
var doc = this.editor.getDoc();
|
||||||
|
|
||||||
|
if (this.deferred.origin === 'undo') {
|
||||||
|
doc.undo();
|
||||||
|
} else if (this.deferred.origin === 'redo') {
|
||||||
|
doc.redo();
|
||||||
|
} else {
|
||||||
|
doc.replaceRange(this.deferred.text, this.deferred.from, this.deferred.to, this.deferred.origin);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value && value !== doc.getValue()) {
|
||||||
|
var cursor = doc.getCursor();
|
||||||
|
doc.setValue(value);
|
||||||
|
doc.setCursor(cursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.emulating = false;
|
||||||
|
this.deferred = null;
|
||||||
|
};
|
||||||
|
|
||||||
|
Controlled.prototype.mirrorChange = function(deferred) {
|
||||||
|
var doc = this.editor.getDoc();
|
||||||
|
|
||||||
|
if (deferred.origin === 'undo') {
|
||||||
|
doc.setHistory(this.mirror.getHistory());
|
||||||
|
this.mirror.undo();
|
||||||
|
} else if (deferred.origin === 'redo') {
|
||||||
|
doc.setHistory(this.mirror.getHistory());
|
||||||
|
this.mirror.redo();
|
||||||
|
} else {
|
||||||
|
this.mirror.replaceRange(deferred.text, deferred.from, deferred.to, deferred.origin);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.mirror.getValue();
|
||||||
|
};
|
||||||
|
|
||||||
|
Controlled.prototype.componentDidMount = function() {
|
||||||
|
var _this = this;
|
||||||
|
|
||||||
|
if (SERVER_RENDERED) return;
|
||||||
|
|
||||||
|
if (this.props.defineMode) {
|
||||||
|
if (this.props.defineMode.name && this.props.defineMode.fn) {
|
||||||
|
cm.defineMode(this.props.defineMode.name, this.props.defineMode.fn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.editor = cm(this.ref, this.props.options);
|
||||||
|
this.shared = new Shared(this.editor, this.props);
|
||||||
|
this.mirror = cm(function() {}, this.props.options);
|
||||||
|
this.editor.on('electricInput', function() {
|
||||||
|
_this.mirror.setHistory(_this.editor.getDoc().getHistory());
|
||||||
|
});
|
||||||
|
this.editor.on('cursorActivity', function() {
|
||||||
|
_this.mirror.setCursor(_this.editor.getDoc().getCursor());
|
||||||
|
});
|
||||||
|
this.editor.on('beforeChange', function(cm, data) {
|
||||||
|
if (_this.emulating) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
data.cancel();
|
||||||
|
_this.deferred = data;
|
||||||
|
|
||||||
|
var phantomChange = _this.mirrorChange(_this.deferred);
|
||||||
|
|
||||||
|
if (_this.props.onBeforeChange) _this.props.onBeforeChange(_this.editor, _this.deferred, phantomChange);
|
||||||
|
});
|
||||||
|
this.editor.on('change', function(cm, data) {
|
||||||
|
if (!_this.mounted) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_this.props.onChange) {
|
||||||
|
_this.props.onChange(_this.editor, data, _this.editor.getValue());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.hydrate(this.props);
|
||||||
|
this.shared.apply(this.props);
|
||||||
|
this.applied = true;
|
||||||
|
this.mounted = true;
|
||||||
|
this.shared.wire(this.props);
|
||||||
|
|
||||||
|
if (this.editor.getOption('autofocus')) {
|
||||||
|
this.editor.focus();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.props.editorDidMount) {
|
||||||
|
this.props.editorDidMount(this.editor, this.editor.getValue(), this.initCb);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Controlled.prototype.componentDidUpdate = function(prevProps) {
|
||||||
|
if (SERVER_RENDERED) return;
|
||||||
|
var preserved = {
|
||||||
|
cursor: null
|
||||||
|
};
|
||||||
|
|
||||||
|
if (this.props.value !== prevProps.value) {
|
||||||
|
this.hydrated = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.props.autoCursor && this.props.autoCursor !== undefined) {
|
||||||
|
preserved.cursor = this.editor.getDoc().getCursor();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.hydrate(this.props);
|
||||||
|
|
||||||
|
if (!this.appliedNext) {
|
||||||
|
this.shared.applyNext(prevProps, this.props, preserved);
|
||||||
|
this.appliedNext = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.shared.applyUserDefined(prevProps, preserved);
|
||||||
|
this.appliedUserDefined = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
Controlled.prototype.componentWillUnmount = function() {
|
||||||
|
if (SERVER_RENDERED) return;
|
||||||
|
|
||||||
|
if (this.props.editorWillUnmount) {
|
||||||
|
this.props.editorWillUnmount(cm);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Controlled.prototype.shouldComponentUpdate = function(nextProps, nextState) {
|
||||||
|
return !SERVER_RENDERED;
|
||||||
|
};
|
||||||
|
|
||||||
|
Controlled.prototype.render = function() {
|
||||||
|
var _this = this;
|
||||||
|
|
||||||
|
if (SERVER_RENDERED) return null;
|
||||||
|
var className = this.props.className ? 'react-codemirror2 ' + this.props.className : 'react-codemirror2';
|
||||||
|
return react.createElement('div', {
|
||||||
|
className: className,
|
||||||
|
ref: function ref(self) {
|
||||||
|
return _this.ref = self;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return Controlled;
|
||||||
|
}(react.Component);
|
||||||
|
|
||||||
|
exports.Controlled = Controlled;
|
||||||
|
|
||||||
|
var UnControlled = function(_super) {
|
||||||
|
__extends(UnControlled, _super);
|
||||||
|
|
||||||
|
function UnControlled(props) {
|
||||||
|
var _this = _super.call(this, props) || this;
|
||||||
|
|
||||||
|
if (SERVER_RENDERED) return _this;
|
||||||
|
_this.applied = false;
|
||||||
|
_this.appliedUserDefined = false;
|
||||||
|
_this.continueChange = false;
|
||||||
|
_this.detached = false;
|
||||||
|
_this.hydrated = false;
|
||||||
|
|
||||||
|
_this.initCb = function() {
|
||||||
|
if (_this.props.editorDidConfigure) {
|
||||||
|
_this.props.editorDidConfigure(_this.editor);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
_this.mounted = false;
|
||||||
|
|
||||||
|
_this.onBeforeChangeCb = function() {
|
||||||
|
_this.continueChange = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
return _this;
|
||||||
|
}
|
||||||
|
|
||||||
|
UnControlled.prototype.hydrate = function(props) {
|
||||||
|
var _this = this;
|
||||||
|
|
||||||
|
var _options = props && props.options ? props.options : {};
|
||||||
|
|
||||||
|
var userDefinedOptions = _extends({}, cm.defaults, this.editor.options, _options);
|
||||||
|
|
||||||
|
var optionDelta = Object.keys(userDefinedOptions).some(function(key) {
|
||||||
|
return _this.editor.getOption(key) !== userDefinedOptions[key];
|
||||||
|
});
|
||||||
|
|
||||||
|
if (optionDelta) {
|
||||||
|
Object.keys(userDefinedOptions).forEach(function(key) {
|
||||||
|
if (_options.hasOwnProperty(key)) {
|
||||||
|
if (_this.editor.getOption(key) !== userDefinedOptions[key]) {
|
||||||
|
_this.editor.setOption(key, userDefinedOptions[key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.hydrated) {
|
||||||
|
var doc = this.editor.getDoc();
|
||||||
|
var lastLine = doc.lastLine();
|
||||||
|
var lastChar = doc.getLine(doc.lastLine()).length;
|
||||||
|
doc.replaceRange(props.value || '', {
|
||||||
|
line: 0,
|
||||||
|
ch: 0
|
||||||
|
}, {
|
||||||
|
line: lastLine,
|
||||||
|
ch: lastChar
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.hydrated = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
UnControlled.prototype.componentDidMount = function() {
|
||||||
|
var _this = this;
|
||||||
|
|
||||||
|
if (SERVER_RENDERED) return;
|
||||||
|
this.detached = this.props.detach === true;
|
||||||
|
|
||||||
|
if (this.props.defineMode) {
|
||||||
|
if (this.props.defineMode.name && this.props.defineMode.fn) {
|
||||||
|
cm.defineMode(this.props.defineMode.name, this.props.defineMode.fn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.editor = cm(this.ref, this.props.options);
|
||||||
|
this.shared = new Shared(this.editor, this.props);
|
||||||
|
this.editor.on('beforeChange', function(cm, data) {
|
||||||
|
if (_this.props.onBeforeChange) {
|
||||||
|
_this.props.onBeforeChange(_this.editor, data, _this.editor.getValue(), _this.onBeforeChangeCb);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.editor.on('change', function(cm, data) {
|
||||||
|
if (!_this.mounted || !_this.props.onChange) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_this.props.onBeforeChange) {
|
||||||
|
if (_this.continueChange) {
|
||||||
|
_this.props.onChange(_this.editor, data, _this.editor.getValue());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_this.props.onChange(_this.editor, data, _this.editor.getValue());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.hydrate(this.props);
|
||||||
|
this.shared.apply(this.props);
|
||||||
|
this.applied = true;
|
||||||
|
this.mounted = true;
|
||||||
|
this.shared.wire(this.props);
|
||||||
|
this.editor.getDoc().clearHistory();
|
||||||
|
|
||||||
|
if (this.props.editorDidMount) {
|
||||||
|
this.props.editorDidMount(this.editor, this.editor.getValue(), this.initCb);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
UnControlled.prototype.componentDidUpdate = function(prevProps) {
|
||||||
|
if (this.detached && this.props.detach === false) {
|
||||||
|
this.detached = false;
|
||||||
|
|
||||||
|
if (prevProps.editorDidAttach) {
|
||||||
|
prevProps.editorDidAttach(this.editor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.detached && this.props.detach === true) {
|
||||||
|
this.detached = true;
|
||||||
|
|
||||||
|
if (prevProps.editorDidDetach) {
|
||||||
|
prevProps.editorDidDetach(this.editor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SERVER_RENDERED || this.detached) return;
|
||||||
|
var preserved = {
|
||||||
|
cursor: null
|
||||||
|
};
|
||||||
|
|
||||||
|
if (this.props.value !== prevProps.value) {
|
||||||
|
this.hydrated = false;
|
||||||
|
this.applied = false;
|
||||||
|
this.appliedUserDefined = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!prevProps.autoCursor && prevProps.autoCursor !== undefined) {
|
||||||
|
preserved.cursor = this.editor.getDoc().getCursor();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.hydrate(this.props);
|
||||||
|
|
||||||
|
if (!this.applied) {
|
||||||
|
this.shared.apply(prevProps);
|
||||||
|
this.applied = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.appliedUserDefined) {
|
||||||
|
this.shared.applyUserDefined(prevProps, preserved);
|
||||||
|
this.appliedUserDefined = true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
UnControlled.prototype.componentWillUnmount = function() {
|
||||||
|
if (SERVER_RENDERED) return;
|
||||||
|
|
||||||
|
if (this.props.editorWillUnmount) {
|
||||||
|
this.props.editorWillUnmount(cm);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
UnControlled.prototype.shouldComponentUpdate = function(nextProps, nextState) {
|
||||||
|
var update = true;
|
||||||
|
if (SERVER_RENDERED) update = false;
|
||||||
|
if (this.detached && nextProps.detach) update = false;
|
||||||
|
return update;
|
||||||
|
};
|
||||||
|
|
||||||
|
UnControlled.prototype.render = function() {
|
||||||
|
var _this = this;
|
||||||
|
|
||||||
|
if (SERVER_RENDERED) return null;
|
||||||
|
var className = this.props.className ? 'react-codemirror2 ' + this.props.className : 'react-codemirror2';
|
||||||
|
return react.createElement('div', {
|
||||||
|
className: className,
|
||||||
|
ref: function ref(self) {
|
||||||
|
return _this.ref = self;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return UnControlled;
|
||||||
|
}(react.Component);
|
||||||
|
|
||||||
|
exports.UnControlled = UnControlled;
|
||||||
|
});
|
||||||
|
|
||||||
|
var Controlled = reactCodemirror2.Controlled;
|
||||||
|
export { Controlled };
|
||||||
4
docs/_snowpack/pkg/react-dom.js
vendored
4
docs/_snowpack/pkg/react-dom.js
vendored
|
|
@ -1,5 +1,5 @@
|
||||||
import { c as createCommonjsModule } from './common/_commonjsHelpers-913f9c4a.js';
|
import { c as createCommonjsModule } from './common/_commonjsHelpers-8c19dec8.js';
|
||||||
import { r as react, o as objectAssign } from './common/index-c9e50cb4.js';
|
import { r as react, o as objectAssign } from './common/index-04edb6a1.js';
|
||||||
|
|
||||||
var scheduler_production_min = createCommonjsModule(function (module, exports) {
|
var scheduler_production_min = createCommonjsModule(function (module, exports) {
|
||||||
var f,g,h,k;if("object"===typeof performance&&"function"===typeof performance.now){var l=performance;exports.unstable_now=function(){return l.now()};}else {var p=Date,q=p.now();exports.unstable_now=function(){return p.now()-q};}
|
var f,g,h,k;if("object"===typeof performance&&"function"===typeof performance.now){var l=performance;exports.unstable_now=function(){return l.now()};}else {var p=Date,q=p.now();exports.unstable_now=function(){return p.now()-q};}
|
||||||
|
|
|
||||||
6
docs/_snowpack/pkg/react.js
vendored
6
docs/_snowpack/pkg/react.js
vendored
|
|
@ -1,6 +1,6 @@
|
||||||
import { r as react } from './common/index-c9e50cb4.js';
|
import { r as react } from './common/index-04edb6a1.js';
|
||||||
export { r as default } from './common/index-c9e50cb4.js';
|
export { r as default } from './common/index-04edb6a1.js';
|
||||||
import './common/_commonjsHelpers-913f9c4a.js';
|
import './common/_commonjsHelpers-8c19dec8.js';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
66
docs/dist/App.js
vendored
66
docs/dist/App.js
vendored
|
|
@ -4,14 +4,13 @@ import * as strudel from "../_snowpack/link/strudel.js";
|
||||||
import cx from "./cx.js";
|
import cx from "./cx.js";
|
||||||
import * as Tone from "../_snowpack/pkg/tone.js";
|
import * as Tone from "../_snowpack/pkg/tone.js";
|
||||||
import useCycle from "./useCycle.js";
|
import useCycle from "./useCycle.js";
|
||||||
import {tetris} from "./tunes.js";
|
import * as tunes from "./tunes.js";
|
||||||
const {Fraction, TimeSpan} = strudel;
|
import * as krill from "./parse.js";
|
||||||
const fr = (v) => new Fraction(v);
|
import CodeMirror from "./CodeMirror.js";
|
||||||
const ts = (start, end) => new TimeSpan(fr(start), fr(end));
|
const {tetris, tetrisMini, tetrisHaskell} = tunes;
|
||||||
const parse = (code) => {
|
const {sequence, pure, reify, slowcat, fastcat, cat, stack, silence} = strudel;
|
||||||
const {sequence, pure, reify, slowcat, fastcat, cat, stack, silence} = strudel;
|
const {mini, h} = krill;
|
||||||
return eval(code);
|
const parse = (code) => eval(code);
|
||||||
};
|
|
||||||
const synth = new Tone.PolySynth().toDestination();
|
const synth = new Tone.PolySynth().toDestination();
|
||||||
synth.set({
|
synth.set({
|
||||||
oscillator: {type: "triangle"},
|
oscillator: {type: "triangle"},
|
||||||
|
|
@ -20,7 +19,8 @@ synth.set({
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
function App() {
|
function App() {
|
||||||
const [code, setCode] = useState(tetris);
|
const [mode, setMode] = useState("javascript");
|
||||||
|
const [code, setCode] = useState(tetrisHaskell);
|
||||||
const [log, setLog] = useState("");
|
const [log, setLog] = useState("");
|
||||||
const logBox = useRef();
|
const logBox = useRef();
|
||||||
const [error, setError] = useState();
|
const [error, setError] = useState();
|
||||||
|
|
@ -50,10 +50,18 @@ function App() {
|
||||||
});
|
});
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
try {
|
try {
|
||||||
const _pattern = parse(code);
|
let _pattern;
|
||||||
|
try {
|
||||||
|
_pattern = h(code);
|
||||||
|
setMode("pegjs");
|
||||||
|
} catch (err) {
|
||||||
|
setMode("javascript");
|
||||||
|
_pattern = parse(code);
|
||||||
|
}
|
||||||
setPattern(_pattern);
|
setPattern(_pattern);
|
||||||
setError(void 0);
|
setError(void 0);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
console.warn(err);
|
||||||
setError(err);
|
setError(err);
|
||||||
}
|
}
|
||||||
}, [code]);
|
}, [code]);
|
||||||
|
|
@ -61,9 +69,9 @@ function App() {
|
||||||
logBox.current.scrollTop = logBox.current?.scrollHeight;
|
logBox.current.scrollTop = logBox.current?.scrollHeight;
|
||||||
}, [log]);
|
}, [log]);
|
||||||
return /* @__PURE__ */ React.createElement("div", {
|
return /* @__PURE__ */ React.createElement("div", {
|
||||||
className: "h-[100vh] bg-slate-900 flex-row"
|
className: "h-screen bg-slate-900 flex flex-col"
|
||||||
}, /* @__PURE__ */ React.createElement("header", {
|
}, /* @__PURE__ */ React.createElement("header", {
|
||||||
className: "px-2 flex items-center space-x-2 border-b border-gray-200 bg-white"
|
className: "flex-none w-full h-16 px-2 flex items-center space-x-2 border-b border-gray-200 bg-white"
|
||||||
}, /* @__PURE__ */ React.createElement("img", {
|
}, /* @__PURE__ */ React.createElement("img", {
|
||||||
src: logo,
|
src: logo,
|
||||||
className: "Tidal-logo w-16 h-16",
|
className: "Tidal-logo w-16 h-16",
|
||||||
|
|
@ -71,29 +79,35 @@ function App() {
|
||||||
}), /* @__PURE__ */ React.createElement("h1", {
|
}), /* @__PURE__ */ React.createElement("h1", {
|
||||||
className: "text-2xl"
|
className: "text-2xl"
|
||||||
}, "Strudel REPL")), /* @__PURE__ */ React.createElement("section", {
|
}, "Strudel REPL")), /* @__PURE__ */ React.createElement("section", {
|
||||||
className: "grow p-2 text-gray-100"
|
className: "grow flex flex-col p-2 text-gray-100"
|
||||||
}, /* @__PURE__ */ React.createElement("div", {
|
}, /* @__PURE__ */ React.createElement("div", {
|
||||||
className: "relative"
|
className: "grow relative"
|
||||||
}, /* @__PURE__ */ React.createElement("div", {
|
}, /* @__PURE__ */ React.createElement("div", {
|
||||||
className: "absolute right-2 bottom-2 text-red-500"
|
className: cx("h-full bg-slate-600", error ? "focus:ring-red-500" : "focus:ring-slate-800")
|
||||||
}, error?.message), /* @__PURE__ */ React.createElement("textarea", {
|
}, /* @__PURE__ */ React.createElement(CodeMirror, {
|
||||||
className: cx("w-full h-64 bg-slate-600", error ? "focus:ring-red-500" : "focus:ring-slate-800"),
|
|
||||||
value: code,
|
value: code,
|
||||||
onChange: (e) => {
|
options: {
|
||||||
|
mode,
|
||||||
|
theme: "material",
|
||||||
|
lineNumbers: true
|
||||||
|
},
|
||||||
|
onChange: (_, __, value) => {
|
||||||
setLog((log2) => log2 + `${log2 ? "\n\n" : ""}✏️ edit
|
setLog((log2) => log2 + `${log2 ? "\n\n" : ""}✏️ edit
|
||||||
${code}
|
${code}
|
||||||
${e.target.value}`);
|
${value}`);
|
||||||
setCode(e.target.value);
|
setCode(value);
|
||||||
}
|
}
|
||||||
})), /* @__PURE__ */ React.createElement("textarea", {
|
})), error && /* @__PURE__ */ React.createElement("div", {
|
||||||
className: "w-full h-64 bg-slate-600",
|
className: "absolute right-2 bottom-2 text-red-500"
|
||||||
|
}, error?.message || "unknown error")), /* @__PURE__ */ React.createElement("button", {
|
||||||
|
className: "flex-none w-full border border-gray-700 p-2 bg-slate-700 hover:bg-slate-500",
|
||||||
|
onClick: () => cycle.toggle()
|
||||||
|
}, cycle.started ? "pause" : "play"), /* @__PURE__ */ React.createElement("textarea", {
|
||||||
|
className: "grow bg-[#283237] border-0",
|
||||||
value: log,
|
value: log,
|
||||||
readOnly: true,
|
readOnly: true,
|
||||||
ref: logBox,
|
ref: logBox,
|
||||||
style: {fontFamily: "monospace"}
|
style: {fontFamily: "monospace"}
|
||||||
}), /* @__PURE__ */ React.createElement("button", {
|
})));
|
||||||
className: "w-full border border-gray-700 p-2 bg-slate-700 hover:bg-slate-500",
|
|
||||||
onClick: () => cycle.toggle()
|
|
||||||
}, cycle.started ? "pause" : "play")));
|
|
||||||
}
|
}
|
||||||
export default App;
|
export default App;
|
||||||
|
|
|
||||||
18
docs/dist/CodeMirror.js
vendored
Normal file
18
docs/dist/CodeMirror.js
vendored
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
import React from "../_snowpack/pkg/react.js";
|
||||||
|
import {Controlled as CodeMirror2} from "../_snowpack/pkg/react-codemirror2.js";
|
||||||
|
import "../_snowpack/pkg/codemirror/mode/javascript/javascript.js";
|
||||||
|
import "../_snowpack/pkg/codemirror/mode/pegjs/pegjs.js";
|
||||||
|
import "../_snowpack/pkg/codemirror/theme/material.css.proxy.js";
|
||||||
|
import "../_snowpack/pkg/codemirror/lib/codemirror.css.proxy.js";
|
||||||
|
export default function CodeMirror({value, onChange, options}) {
|
||||||
|
options = options || {
|
||||||
|
mode: "javascript",
|
||||||
|
theme: "material",
|
||||||
|
lineNumbers: true
|
||||||
|
};
|
||||||
|
return /* @__PURE__ */ React.createElement(CodeMirror2, {
|
||||||
|
value,
|
||||||
|
options,
|
||||||
|
onBeforeChange: onChange
|
||||||
|
});
|
||||||
|
}
|
||||||
2
docs/dist/logo.svg.proxy.js
vendored
2
docs/dist/logo.svg.proxy.js
vendored
|
|
@ -1 +1 @@
|
||||||
export default "/dist/logo.svg";
|
export default "/strudel/dist/logo.svg";
|
||||||
80
docs/dist/parse.js
vendored
Normal file
80
docs/dist/parse.js
vendored
Normal file
|
|
@ -0,0 +1,80 @@
|
||||||
|
import * as krill from "../_snowpack/link/repl/krill-parser.js";
|
||||||
|
import * as strudel from "../_snowpack/link/strudel.js";
|
||||||
|
import {Scale, Note, Interval} from "../_snowpack/pkg/@tonaljs/tonal.js";
|
||||||
|
const {sequence, stack, silence, Fraction, pure} = strudel;
|
||||||
|
function reify(thing) {
|
||||||
|
if (thing?.constructor?.name === "Pattern") {
|
||||||
|
return thing;
|
||||||
|
}
|
||||||
|
return pure(thing);
|
||||||
|
}
|
||||||
|
const applyOptions = (parent) => (pat, i) => {
|
||||||
|
const ast = parent.source_[i];
|
||||||
|
const options = ast.options_;
|
||||||
|
const operator = options?.operator;
|
||||||
|
if (operator) {
|
||||||
|
switch (operator.type_) {
|
||||||
|
case "stretch":
|
||||||
|
const speed = new Fraction(operator.arguments_.amount).inverse().valueOf();
|
||||||
|
return reify(pat).fast(speed);
|
||||||
|
}
|
||||||
|
console.warn(`operator "${operator.type_}" not implemented`);
|
||||||
|
}
|
||||||
|
const unimplemented = Object.keys(options || {}).filter((key) => key !== "operator");
|
||||||
|
if (unimplemented.length) {
|
||||||
|
console.warn(`option${unimplemented.length > 1 ? "s" : ""} ${unimplemented.map((o) => `"${o}"`).join(", ")} not implemented`);
|
||||||
|
}
|
||||||
|
return pat;
|
||||||
|
};
|
||||||
|
export function patternifyAST(ast) {
|
||||||
|
switch (ast.type_) {
|
||||||
|
case "pattern":
|
||||||
|
const children = ast.source_.map(patternifyAST).map(applyOptions(ast));
|
||||||
|
if (ast.arguments_.alignment === "v") {
|
||||||
|
return stack(...children);
|
||||||
|
}
|
||||||
|
return sequence(...children);
|
||||||
|
case "element":
|
||||||
|
if (ast.source_ === "~") {
|
||||||
|
return silence;
|
||||||
|
}
|
||||||
|
if (typeof ast.source_ !== "object") {
|
||||||
|
return ast.source_;
|
||||||
|
}
|
||||||
|
return patternifyAST(ast.source_);
|
||||||
|
case "stretch":
|
||||||
|
return patternifyAST(ast.source_).slow(ast.arguments_.amount);
|
||||||
|
case "scale":
|
||||||
|
let [tonic, scale] = Scale.tokenize(ast.arguments_.scale);
|
||||||
|
const intervals = Scale.get(scale).intervals;
|
||||||
|
const pattern = patternifyAST(ast.source_);
|
||||||
|
tonic = tonic || "C4";
|
||||||
|
console.log("tonic", tonic);
|
||||||
|
return pattern.fmap((step) => {
|
||||||
|
step = Number(step);
|
||||||
|
if (isNaN(step)) {
|
||||||
|
console.warn(`scale step "${step}" not a number`);
|
||||||
|
return step;
|
||||||
|
}
|
||||||
|
const octaves = Math.floor(step / intervals.length);
|
||||||
|
const mod = (n, m) => n < 0 ? mod(n + m, m) : n % m;
|
||||||
|
const index = mod(step, intervals.length);
|
||||||
|
const interval = Interval.add(intervals[index], Interval.fromSemitones(octaves * 12));
|
||||||
|
return Note.transpose(tonic, interval || "1P");
|
||||||
|
});
|
||||||
|
default:
|
||||||
|
console.warn(`node type "${ast.type_}" not implemented -> returning silence`);
|
||||||
|
return silence;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export const mini = (...strings) => {
|
||||||
|
const pattern = sequence(...strings.map((str) => {
|
||||||
|
const ast = krill.parse(`"${str}"`);
|
||||||
|
return patternifyAST(ast);
|
||||||
|
}));
|
||||||
|
return pattern;
|
||||||
|
};
|
||||||
|
export const h = (string) => {
|
||||||
|
const ast = krill.parse(string);
|
||||||
|
return patternifyAST(ast);
|
||||||
|
};
|
||||||
80
docs/dist/tunes.js
vendored
80
docs/dist/tunes.js
vendored
|
|
@ -1,4 +1,4 @@
|
||||||
export const tetris = `stack(sequence(
|
export const tetrisWithFunctions = `stack(sequence(
|
||||||
'e5', sequence('b4', 'c5'), 'd5', sequence('c5', 'b4'),
|
'e5', sequence('b4', 'c5'), 'd5', sequence('c5', 'b4'),
|
||||||
'a4', sequence('a4', 'c5'), 'e5', sequence('d5', 'c5'),
|
'a4', sequence('a4', 'c5'), 'e5', sequence('d5', 'c5'),
|
||||||
'b4', sequence(silence, 'c5'), 'd5', 'e5',
|
'b4', sequence(silence, 'c5'), 'd5', 'e5',
|
||||||
|
|
@ -18,6 +18,84 @@ export const tetris = `stack(sequence(
|
||||||
'a1', 'a2', 'a1', 'a2', 'a1', 'a2', 'a1', 'a2',
|
'a1', 'a2', 'a1', 'a2', 'a1', 'a2', 'a1', 'a2',
|
||||||
)
|
)
|
||||||
)._slow(16)`;
|
)._slow(16)`;
|
||||||
|
export const tetris = `stack(
|
||||||
|
sequence(
|
||||||
|
mini(
|
||||||
|
'e5 [b4 c5] d5 [c5 b4]',
|
||||||
|
'a4 [a4 c5] e5 [d5 c5]',
|
||||||
|
'b4 [~ c5] d5 e5',
|
||||||
|
'c5 a4 a4 ~',
|
||||||
|
'[~ d5] [~ f5] a5 [g5 f5]',
|
||||||
|
'e5 [~ c5] e5 [d5 c5]',
|
||||||
|
'b4 [b4 c5] d5 e5',
|
||||||
|
'c5 a4 a4 ~'
|
||||||
|
)
|
||||||
|
),
|
||||||
|
sequence(
|
||||||
|
mini(
|
||||||
|
'e2 e3 e2 e3 e2 e3 e2 e3',
|
||||||
|
'a2 a3 a2 a3 a2 a3 a2 a3',
|
||||||
|
'g#2 g#3 g#2 g#3 e2 e3 e2 e3',
|
||||||
|
'a2 a3 a2 a3 a2 a3 b1 c2',
|
||||||
|
'd2 d3 d2 d3 d2 d3 d2 d3',
|
||||||
|
'c2 c3 c2 c3 c2 c3 c2 c3',
|
||||||
|
'b1 b2 b1 b2 e2 e3 e2 e3',
|
||||||
|
'a1 a2 a1 a2 a1 a2 a1 a2'
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)._slow(16);`;
|
||||||
|
export const tetrisMini1 = `mini('[[e5 [b4 c5] d5 [c5 b4]] [a4 [a4 c5] e5 [d5 c5]] [b4 [~ c5] d5 e5] [c5 a4 a4 ~] [[~ d5] [~ f5] a5 [g5 f5]] [e5 [~ c5] e5 [d5 c5]] [b4 [b4 c5] d5 e5] [c5 a4 a4 ~]],[[e2 e3 e2 e3 e2 e3 e2 e3] [a2 a3 a2 a3 a2 a3 a2 a3] [g#2 g#3 g#2 g#3 e2 e3 e2 e3] [a2 a3 a2 a3 a2 a3 b1 c2] [d2 d3 d2 d3 d2 d3 d2 d3] [c2 c3 c2 c3 c2 c3 c2 c3] [b1 b2 b1 b2 e2 e3 e2 e3] [a1 a2 a1 a2 a1 a2 a1 a2]]')._slow(16);`;
|
||||||
|
export const tetrisMini = `mini(\`[[e5 [b4 c5] d5 [c5 b4]]
|
||||||
|
[a4 [a4 c5] e5 [d5 c5]]
|
||||||
|
[b4 [~ c5] d5 e5]
|
||||||
|
[c5 a4 a4 ~]
|
||||||
|
[[~ d5] [~ f5] a5 [g5 f5]]
|
||||||
|
[e5 [~ c5] e5 [d5 c5]]
|
||||||
|
[b4 [b4 c5] d5 e5]
|
||||||
|
[c5 a4 a4 ~]],
|
||||||
|
[[e2 e3]*4]
|
||||||
|
[[a2 a3]*4]
|
||||||
|
[[g#2 g#3]*2 [e2 e3]*2]
|
||||||
|
[a2 a3 a2 a3 a2 a3 b1 c2]
|
||||||
|
[[d2 d3]*4]
|
||||||
|
[[c2 c3]*4]
|
||||||
|
[[b1 b2]*2 [e2 e3]*2]
|
||||||
|
[[a1 a2]*4]\`)._slow(16);
|
||||||
|
`;
|
||||||
|
export const tetrisHaskellH = `h(\`slow 16 $ "[[e5 [b4 c5] d5 [c5 b4]]
|
||||||
|
[a4 [a4 c5] e5 [d5 c5]]
|
||||||
|
[b4 [~ c5] d5 e5]
|
||||||
|
[c5 a4 a4 ~]
|
||||||
|
[[~ d5] [~ f5] a5 [g5 f5]]
|
||||||
|
[e5 [~ c5] e5 [d5 c5]]
|
||||||
|
[b4 [b4 c5] d5 e5]
|
||||||
|
[c5 a4 a4 ~]],
|
||||||
|
[[e2 e3]*4]
|
||||||
|
[[a2 a3]*4]
|
||||||
|
[[g#2 g#3]*2 [e2 e3]*2]
|
||||||
|
[a2 a3 a2 a3 a2 a3 b1 c2]
|
||||||
|
[[d2 d3]*4]
|
||||||
|
[[c2 c3]*4]
|
||||||
|
[[b1 b2]*2 [e2 e3]*2]
|
||||||
|
[[a1 a2]*4]"\`)
|
||||||
|
`;
|
||||||
|
export const tetrisHaskell = `slow 16 $ "[[e5 [b4 c5] d5 [c5 b4]]
|
||||||
|
[a4 [a4 c5] e5 [d5 c5]]
|
||||||
|
[b4 [~ c5] d5 e5]
|
||||||
|
[c5 a4 a4 ~]
|
||||||
|
[[~ d5] [~ f5] a5 [g5 f5]]
|
||||||
|
[e5 [~ c5] e5 [d5 c5]]
|
||||||
|
[b4 [b4 c5] d5 e5]
|
||||||
|
[c5 a4 a4 ~]],
|
||||||
|
[[e2 e3]*4]
|
||||||
|
[[a2 a3]*4]
|
||||||
|
[[g#2 g#3]*2 [e2 e3]*2]
|
||||||
|
[a2 a3 a2 a3 a2 a3 b1 c2]
|
||||||
|
[[d2 d3]*4]
|
||||||
|
[[c2 c3]*4]
|
||||||
|
[[b1 b2]*2 [e2 e3]*2]
|
||||||
|
[[a1 a2]*4]"
|
||||||
|
`;
|
||||||
export const spanish = `slowcat(
|
export const spanish = `slowcat(
|
||||||
stack('c4','eb4','g4'),
|
stack('c4','eb4','g4'),
|
||||||
stack('bb3','d4','f4'),
|
stack('bb3','d4','f4'),
|
||||||
|
|
|
||||||
4
docs/dist/useCycle.js
vendored
4
docs/dist/useCycle.js
vendored
|
|
@ -25,11 +25,11 @@ function useCycle(props) {
|
||||||
query(cycle + 1);
|
query(cycle + 1);
|
||||||
}, queryNextTime);
|
}, queryNextTime);
|
||||||
}
|
}
|
||||||
events?.forEach((event) => {
|
events?.filter((event) => event.part.begin.valueOf() === event.whole.begin.valueOf()).forEach((event) => {
|
||||||
Tone.Transport.schedule((time) => {
|
Tone.Transport.schedule((time) => {
|
||||||
const toneEvent = {
|
const toneEvent = {
|
||||||
time: event.part.begin.valueOf(),
|
time: event.part.begin.valueOf(),
|
||||||
duration: event.part.end.valueOf() - event.part.begin.valueOf(),
|
duration: event.whole.end.valueOf() - event.whole.begin.valueOf(),
|
||||||
value: event.value
|
value: event.value
|
||||||
};
|
};
|
||||||
onEvent(time, toneEvent);
|
onEvent(time, toneEvent);
|
||||||
|
|
|
||||||
|
|
@ -605,26 +605,32 @@ select {
|
||||||
.flex {
|
.flex {
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
.h-\[100vh\] {
|
.h-screen {
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
}
|
}
|
||||||
.h-16 {
|
.h-16 {
|
||||||
height: 4rem;
|
height: 4rem;
|
||||||
}
|
}
|
||||||
|
.h-full {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
.h-64 {
|
.h-64 {
|
||||||
height: 16rem;
|
height: 16rem;
|
||||||
}
|
}
|
||||||
.w-16 {
|
|
||||||
width: 4rem;
|
|
||||||
}
|
|
||||||
.w-full {
|
.w-full {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
.w-16 {
|
||||||
|
width: 4rem;
|
||||||
|
}
|
||||||
|
.flex-none {
|
||||||
|
flex: none;
|
||||||
|
}
|
||||||
.grow {
|
.grow {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
}
|
}
|
||||||
.flex-row {
|
.flex-col {
|
||||||
flex-direction: row;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
.items-center {
|
.items-center {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
@ -637,6 +643,9 @@ select {
|
||||||
.border {
|
.border {
|
||||||
border-width: 1px;
|
border-width: 1px;
|
||||||
}
|
}
|
||||||
|
.border-0 {
|
||||||
|
border-width: 0px;
|
||||||
|
}
|
||||||
.border-b {
|
.border-b {
|
||||||
border-bottom-width: 1px;
|
border-bottom-width: 1px;
|
||||||
}
|
}
|
||||||
|
|
@ -664,6 +673,10 @@ select {
|
||||||
--tw-bg-opacity: 1;
|
--tw-bg-opacity: 1;
|
||||||
background-color: rgb(51 65 85 / var(--tw-bg-opacity));
|
background-color: rgb(51 65 85 / var(--tw-bg-opacity));
|
||||||
}
|
}
|
||||||
|
.bg-\[\#283237\] {
|
||||||
|
--tw-bg-opacity: 1;
|
||||||
|
background-color: rgb(40 50 55 / var(--tw-bg-opacity));
|
||||||
|
}
|
||||||
.p-2 {
|
.p-2 {
|
||||||
padding: 0.5rem;
|
padding: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
@ -686,14 +699,22 @@ select {
|
||||||
.filter {
|
.filter {
|
||||||
filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
|
filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.react-codemirror2,
|
||||||
|
.CodeMirror {
|
||||||
|
height: 100% !important;
|
||||||
|
}
|
||||||
|
|
||||||
.hover\:bg-slate-500:hover {
|
.hover\:bg-slate-500:hover {
|
||||||
--tw-bg-opacity: 1;
|
--tw-bg-opacity: 1;
|
||||||
background-color: rgb(100 116 139 / var(--tw-bg-opacity));
|
background-color: rgb(100 116 139 / var(--tw-bg-opacity));
|
||||||
}
|
}
|
||||||
|
|
||||||
.focus\:ring-red-500:focus {
|
.focus\:ring-red-500:focus {
|
||||||
--tw-ring-opacity: 1;
|
--tw-ring-opacity: 1;
|
||||||
--tw-ring-color: rgb(239 68 68 / var(--tw-ring-opacity));
|
--tw-ring-color: rgb(239 68 68 / var(--tw-ring-opacity));
|
||||||
}
|
}
|
||||||
|
|
||||||
.focus\:ring-slate-800:focus {
|
.focus\:ring-slate-800:focus {
|
||||||
--tw-ring-opacity: 1;
|
--tw-ring-opacity: 1;
|
||||||
--tw-ring-color: rgb(30 41 59 / var(--tw-ring-opacity));
|
--tw-ring-color: rgb(30 41 59 / var(--tw-ring-opacity));
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,8 @@
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<link rel="icon" href="/favicon.ico" />
|
<link rel="icon" href="/strudel/favicon.ico" />
|
||||||
<link rel="stylesheet" type="text/css" href="/global.css" />
|
<link rel="stylesheet" type="text/css" href="/strudel/global.css" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
<meta name="description" content="Strudel REPL" />
|
<meta name="description" content="Strudel REPL" />
|
||||||
<title>Strudel REPL</title>
|
<title>Strudel REPL</title>
|
||||||
|
|
@ -11,6 +11,6 @@
|
||||||
<body>
|
<body>
|
||||||
<div id="root"></div>
|
<div id="root"></div>
|
||||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||||
<script type="module" src="/dist/index.js"></script>
|
<script type="module" src="/strudel/dist/index.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
1388
package-lock.json
generated
1388
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
|
@ -1,5 +1,18 @@
|
||||||
# Strudel REPL
|
# Strudel REPL
|
||||||
|
|
||||||
|
## TODO
|
||||||
|
|
||||||
|
### mini notation ([krill docs](https://github.com/Mdashdotdashn/krill#general-principles))
|
||||||
|
|
||||||
|
- "@" aka elongation / weight: how to write in strudel?
|
||||||
|
- "%" fixed step: how to write in strudel?
|
||||||
|
- "struct" not sure how to do this
|
||||||
|
- "c3(5,8)" bjorklund algorithm
|
||||||
|
- more [mini notation features](https://tidalcycles.org/docs/patternlib/tutorials/mini_notation)
|
||||||
|
- not tested
|
||||||
|
|
||||||
|
## Default Snowpack Readme
|
||||||
|
|
||||||
> ✨ Bootstrapped with Create Snowpack App (CSA).
|
> ✨ Bootstrapped with Create Snowpack App (CSA).
|
||||||
|
|
||||||
## Available Scripts
|
## Available Scripts
|
||||||
|
|
@ -14,12 +27,7 @@ You will also see any lint errors in the console.
|
||||||
|
|
||||||
### npm run build
|
### npm run build
|
||||||
|
|
||||||
Builds a static copy of your site to the `build/` folder.
|
Builds a static copy of your site to the `docs/` folder.
|
||||||
Your app is ready to be deployed!
|
Your app is ready to be deployed!
|
||||||
|
|
||||||
**For the best production performance:** Add a build bundler plugin like "@snowpack/plugin-webpack" to your `snowpack.config.mjs` config file.
|
**For the best production performance:** Add a build bundler plugin like "@snowpack/plugin-webpack" to your `snowpack.config.mjs` config file.
|
||||||
|
|
||||||
### npm test
|
|
||||||
|
|
||||||
Launches the application test runner.
|
|
||||||
Run with the `--watch` flag (`npm test -- --watch`) to run in interactive watch mode.
|
|
||||||
|
|
|
||||||
1916
repl/krill-parser.js
Normal file
1916
repl/krill-parser.js
Normal file
File diff suppressed because it is too large
Load diff
207
repl/krill.pegjs
Normal file
207
repl/krill.pegjs
Normal file
|
|
@ -0,0 +1,207 @@
|
||||||
|
// Some terminology:
|
||||||
|
// a sequence = a serie of elements placed between quotes
|
||||||
|
// a stack = a serie of vertically aligned slices sharing the same overall length
|
||||||
|
// a slice = a serie of horizontally aligned elements
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
var PatternStub = function(source, alignment)
|
||||||
|
{
|
||||||
|
this.type_ = "pattern";
|
||||||
|
this.arguments_ = { alignment : alignment};
|
||||||
|
this.source_ = source;
|
||||||
|
}
|
||||||
|
|
||||||
|
var OperatorStub = function(name, args, source)
|
||||||
|
{
|
||||||
|
this.type_ = name;
|
||||||
|
this.arguments_ = args;
|
||||||
|
this.source_ = source;
|
||||||
|
}
|
||||||
|
|
||||||
|
var ElementStub = function(source, options)
|
||||||
|
{
|
||||||
|
this.type_ = "element";
|
||||||
|
this.source_ = source;
|
||||||
|
this.options_ = options;
|
||||||
|
}
|
||||||
|
|
||||||
|
var CommandStub = function(name, options)
|
||||||
|
{
|
||||||
|
this.type_ = "command";
|
||||||
|
this.name_ = name;
|
||||||
|
this.options_ = options;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
start = statement
|
||||||
|
|
||||||
|
// ----- Numbers -----
|
||||||
|
|
||||||
|
number "number"
|
||||||
|
= minus? int frac? exp? { return parseFloat(text()); }
|
||||||
|
|
||||||
|
decimal_point
|
||||||
|
= "."
|
||||||
|
|
||||||
|
digit1_9
|
||||||
|
= [1-9]
|
||||||
|
|
||||||
|
e
|
||||||
|
= [eE]
|
||||||
|
|
||||||
|
exp
|
||||||
|
= e (minus / plus)? DIGIT+
|
||||||
|
|
||||||
|
frac
|
||||||
|
= decimal_point DIGIT+
|
||||||
|
|
||||||
|
int
|
||||||
|
= zero / (digit1_9 DIGIT*)
|
||||||
|
|
||||||
|
minus
|
||||||
|
= "-"
|
||||||
|
|
||||||
|
plus
|
||||||
|
= "+"
|
||||||
|
|
||||||
|
zero
|
||||||
|
= "0"
|
||||||
|
|
||||||
|
DIGIT = [0-9]
|
||||||
|
|
||||||
|
// ------------------ delimiters ---------------------------
|
||||||
|
|
||||||
|
ws "whitespace" = [ \n\r\t]*
|
||||||
|
comma = ws "," ws;
|
||||||
|
quote = '"' / "'"
|
||||||
|
|
||||||
|
// ------------------ steps and cycles ---------------------------
|
||||||
|
|
||||||
|
// single step definition (e.g bd)
|
||||||
|
step_char = [0-9a-zA-Z~] / "-" / "#" / "."
|
||||||
|
step = ws chars:step_char+ ws { return chars.join("") }
|
||||||
|
|
||||||
|
// define a sub cycle e.g. [1 2, 3 [4]]
|
||||||
|
sub_cycle = ws "[" ws s:stack ws "]" ws { return s}
|
||||||
|
|
||||||
|
// define a timeline e.g <1 3 [3 5]>. We simply defer to a stack and change the alignement
|
||||||
|
timeline = ws "<" ws sc:single_cycle ws ">" ws
|
||||||
|
{ sc.arguments_.alignment = "t"; return sc;}
|
||||||
|
|
||||||
|
// a slice is either a single step or a sub cycle
|
||||||
|
slice = step / sub_cycle / timeline
|
||||||
|
|
||||||
|
// slice modifier affects the timing/size of a slice (e.g. [a b c]@3)
|
||||||
|
// at this point, we assume we can represent them as regular sequence operators
|
||||||
|
slice_modifier = slice_weight / slice_bjorklund / slice_slow / slice_fast / slice_fixed_step
|
||||||
|
|
||||||
|
slice_weight = "@" a:number
|
||||||
|
{ return { weight: a} }
|
||||||
|
|
||||||
|
slice_bjorklund = "(" ws p:number ws comma ws s:number ws")"
|
||||||
|
{ return { operator : { type_: "bjorklund", arguments_ :{ pulse: p, step:s } } } }
|
||||||
|
|
||||||
|
slice_slow = "/"a:number
|
||||||
|
{ return { operator : { type_: "stretch", arguments_ :{ amount:a } } } }
|
||||||
|
|
||||||
|
slice_fast = "*"a:number
|
||||||
|
{ return { operator : { type_: "stretch", arguments_ :{ amount:"1/"+a } } } }
|
||||||
|
|
||||||
|
slice_fixed_step = "%"a:number
|
||||||
|
{ return { operator : { type_: "fixed-step", arguments_ :{ amount:a } } } }
|
||||||
|
|
||||||
|
// a slice with an modifier applied i.e [bd@4 sd@3]@2 hh]
|
||||||
|
slice_with_modifier = s:slice o:slice_modifier?
|
||||||
|
{ return new ElementStub(s, o);}
|
||||||
|
|
||||||
|
// a single cycle is a combination of one or more successive slices (as an array). If we
|
||||||
|
// have only one element, we skip the array and return the element itself
|
||||||
|
single_cycle = s:(slice_with_modifier)+
|
||||||
|
{ return new PatternStub(s,"h"); }
|
||||||
|
|
||||||
|
// a stack is a serie of vertically aligned single cycles, separated by a comma
|
||||||
|
// if the stack contains only one element, we don't create a stack but return the
|
||||||
|
// underlying element
|
||||||
|
stack = c:single_cycle cs:(comma v:single_cycle { return v})*
|
||||||
|
{ if (cs.length == 0 && c instanceof Object) { return c;} else { cs.unshift(c); return new PatternStub(cs,"v");} }
|
||||||
|
|
||||||
|
// a sequence is a quoted stack
|
||||||
|
sequence = ws quote s:stack quote
|
||||||
|
{ return s; }
|
||||||
|
|
||||||
|
// ------------------ operators ---------------------------
|
||||||
|
|
||||||
|
operator = scale / slow / fast / target / bjorklund / struct / rotR / rotL
|
||||||
|
|
||||||
|
struct = "struct" ws s:sequence_or_operator
|
||||||
|
{ return { name: "struct", args: { sequence:s }}}
|
||||||
|
|
||||||
|
target = "target" ws quote s:step quote
|
||||||
|
{ return { name: "target", args : { name:s}}}
|
||||||
|
|
||||||
|
bjorklund = "euclid" ws p:int ws s:int
|
||||||
|
{ return { name: "bjorklund", args :{ pulse: parseInt(p), step:parseInt(s) }}}
|
||||||
|
|
||||||
|
slow = "slow" ws a:number
|
||||||
|
{ return { name: "stretch", args :{ amount: a}}}
|
||||||
|
|
||||||
|
rotL = "rotL" ws a:number
|
||||||
|
{ return { name: "shift", args :{ amount: "-"+a}}}
|
||||||
|
|
||||||
|
rotR = "rotR" ws a:number
|
||||||
|
{ return { name: "shift", args :{ amount: a}}}
|
||||||
|
|
||||||
|
fast = "fast" ws a:number
|
||||||
|
{ return { name: "stretch", args :{ amount: "1/"+a}}}
|
||||||
|
|
||||||
|
scale = "scale" ws quote s:(step_char)+ quote
|
||||||
|
{ return { name: "scale", args :{ scale: s.join("")}}}
|
||||||
|
|
||||||
|
comment = '//' p:([^\n]*)
|
||||||
|
|
||||||
|
// ---------------- grouping --------------------------------
|
||||||
|
|
||||||
|
group_operator = cat
|
||||||
|
|
||||||
|
// cat is another form of timeline
|
||||||
|
cat = "cat" ws "[" ws s:sequence_or_operator ss:(comma v:sequence_or_operator { return v})* ws "]"
|
||||||
|
{ ss.unshift(s); return new PatternStub(ss,"t"); }
|
||||||
|
|
||||||
|
// ------------------ high level sequence ---------------------------
|
||||||
|
|
||||||
|
sequence_or_group =
|
||||||
|
group_operator /
|
||||||
|
sequence
|
||||||
|
|
||||||
|
sequence_or_operator =
|
||||||
|
sg:sequence_or_group ws (comment)*
|
||||||
|
{return sg}
|
||||||
|
/ o:operator ws "$" ws soc:sequence_or_operator
|
||||||
|
{ return new OperatorStub(o.name,o.args,soc)}
|
||||||
|
|
||||||
|
sequ_or_operator_or_comment =
|
||||||
|
sc: sequence_or_operator
|
||||||
|
{ return sc }
|
||||||
|
/ comment
|
||||||
|
|
||||||
|
sequence_definition = s:sequ_or_operator_or_comment
|
||||||
|
|
||||||
|
// ---------------------- statements ----------------------------
|
||||||
|
|
||||||
|
command = ws c:(setcps / setbpm / hush) ws
|
||||||
|
{ return c }
|
||||||
|
|
||||||
|
setcps = "setcps" ws v:number
|
||||||
|
{ return new CommandStub("setcps", { value: v})}
|
||||||
|
|
||||||
|
setbpm = "setbpm" ws v:number
|
||||||
|
{ return new CommandStub("setcps", { value: (v/120/2)})}
|
||||||
|
|
||||||
|
hush = "hush"
|
||||||
|
{ return new CommandStub("hush")}
|
||||||
|
|
||||||
|
// ---------------------- statements ----------------------------
|
||||||
|
|
||||||
|
statement = sequence_definition / command
|
||||||
445
repl/package-lock.json
generated
445
repl/package-lock.json
generated
|
|
@ -5,7 +5,10 @@
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@tonaljs/tonal": "^4.6.5",
|
||||||
|
"codemirror": "^5.65.1",
|
||||||
"react": "^17.0.2",
|
"react": "^17.0.2",
|
||||||
|
"react-codemirror2": "^7.2.1",
|
||||||
"react-dom": "^17.0.2",
|
"react-dom": "^17.0.2",
|
||||||
"tone": "^14.7.77"
|
"tone": "^14.7.77"
|
||||||
},
|
},
|
||||||
|
|
@ -25,6 +28,7 @@
|
||||||
"@web/test-runner": "^0.13.3",
|
"@web/test-runner": "^0.13.3",
|
||||||
"autoprefixer": "^10.4.2",
|
"autoprefixer": "^10.4.2",
|
||||||
"chai": "^4.3.4",
|
"chai": "^4.3.4",
|
||||||
|
"peggy": "^1.2.0",
|
||||||
"postcss": "^8.4.6",
|
"postcss": "^8.4.6",
|
||||||
"prettier": "^2.2.1",
|
"prettier": "^2.2.1",
|
||||||
"snowpack": "^3.3.7",
|
"snowpack": "^3.3.7",
|
||||||
|
|
@ -1082,6 +1086,205 @@
|
||||||
"react-dom": "*"
|
"react-dom": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@tonaljs/abc-notation": {
|
||||||
|
"version": "4.6.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tonaljs/abc-notation/-/abc-notation-4.6.5.tgz",
|
||||||
|
"integrity": "sha512-1S0Jnx0NfDLgyhkQOMEHqOacELL6RUdPcWWUP+nAnsOsb9owvB9RKYLSzp5odd16FVUR7U8c/JLc2yxIRvSeJw==",
|
||||||
|
"dependencies": {
|
||||||
|
"@tonaljs/core": "^4.6.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tonaljs/array": {
|
||||||
|
"version": "4.6.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tonaljs/array/-/array-4.6.5.tgz",
|
||||||
|
"integrity": "sha512-7A3DbBQ+qIQ134FqE518b4tJ8V2a15Sn303JjHzgnqZqKrNh/s3wqwkL60F7LKcd09tcp+vIKQP/MYt4xMcRAA==",
|
||||||
|
"dependencies": {
|
||||||
|
"@tonaljs/core": "^4.6.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tonaljs/chord": {
|
||||||
|
"version": "4.6.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tonaljs/chord/-/chord-4.6.5.tgz",
|
||||||
|
"integrity": "sha512-Pjdel4aDVv4kcx9PW6Qozt5BB9nAt13AOExfzKztpgPmlBSy0SKHse7Jp1cA4MGAuLHU8dzVssTFYpCskEFw3w==",
|
||||||
|
"dependencies": {
|
||||||
|
"@tonaljs/chord-detect": "^4.6.5",
|
||||||
|
"@tonaljs/chord-type": "^4.6.5",
|
||||||
|
"@tonaljs/collection": "^4.6.2",
|
||||||
|
"@tonaljs/core": "^4.6.5",
|
||||||
|
"@tonaljs/pcset": "^4.6.5",
|
||||||
|
"@tonaljs/scale-type": "^4.6.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tonaljs/chord-detect": {
|
||||||
|
"version": "4.6.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tonaljs/chord-detect/-/chord-detect-4.6.5.tgz",
|
||||||
|
"integrity": "sha512-4xu53UP4kNTfdTNpAAVijhXcQ+ypJqmeMnsST08ZXSjoYfJUhmf5rWDWfz36KOTtNdCA6AbYgdtTYV/Xw0nd/w==",
|
||||||
|
"dependencies": {
|
||||||
|
"@tonaljs/chord-type": "^4.6.5",
|
||||||
|
"@tonaljs/core": "^4.6.5",
|
||||||
|
"@tonaljs/pcset": "^4.6.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tonaljs/chord-type": {
|
||||||
|
"version": "4.6.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tonaljs/chord-type/-/chord-type-4.6.5.tgz",
|
||||||
|
"integrity": "sha512-Ol4DDopqpZCF9odosO2i8I+plud3Ul7VWJGNvL+PPCf4Qnwuz87q3aJQDLNoRUz4VyW0u66mq3LyVh6A8kb6Ug==",
|
||||||
|
"dependencies": {
|
||||||
|
"@tonaljs/core": "^4.6.5",
|
||||||
|
"@tonaljs/pcset": "^4.6.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tonaljs/collection": {
|
||||||
|
"version": "4.6.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tonaljs/collection/-/collection-4.6.2.tgz",
|
||||||
|
"integrity": "sha512-bfPCotLJNB/tG1NrdbsQPLDKZB5jlMs7uPQ6RYKiNkaena3345ZKkbCGl5pj6YTXeDm/oblXiSbFAn7SlLRZdQ=="
|
||||||
|
},
|
||||||
|
"node_modules/@tonaljs/core": {
|
||||||
|
"version": "4.6.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tonaljs/core/-/core-4.6.5.tgz",
|
||||||
|
"integrity": "sha512-t7Vx0+L3j/ubQj2AhI1H45D/K745np4DwJjJjXNi5FlGD+TL2wyw50dCwkHKGHsrLDqup1qqP6yN7LBpC6UwNg=="
|
||||||
|
},
|
||||||
|
"node_modules/@tonaljs/duration-value": {
|
||||||
|
"version": "4.6.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tonaljs/duration-value/-/duration-value-4.6.2.tgz",
|
||||||
|
"integrity": "sha512-zrXT0L/qsDQ6251Mlqz54vcUbYUB9xb6uJhlxUzc6VauXOt8UOfrdTULubRTXTaBwWt1h8J5n9pXTQmNGzNI9A=="
|
||||||
|
},
|
||||||
|
"node_modules/@tonaljs/interval": {
|
||||||
|
"version": "4.6.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tonaljs/interval/-/interval-4.6.5.tgz",
|
||||||
|
"integrity": "sha512-7EDWhqZ7Nnh9oD4ahRYJHLc799ACGxYL4hDHwMKD16B2MgXqPvDeDvwQ31qUuO0ruGz8tMb3FDlgg0Hplowcbw==",
|
||||||
|
"dependencies": {
|
||||||
|
"@tonaljs/core": "^4.6.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tonaljs/key": {
|
||||||
|
"version": "4.6.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tonaljs/key/-/key-4.6.5.tgz",
|
||||||
|
"integrity": "sha512-ZdZWb5IStx6CLRmdEjawR66CqNpoW3EVUua2nVZBMdgnNebWxt4nvgH/ZNvGlCQGFZkUZzRhCfTwqsS6e3OmSA==",
|
||||||
|
"dependencies": {
|
||||||
|
"@tonaljs/core": "^4.6.5",
|
||||||
|
"@tonaljs/note": "^4.6.5",
|
||||||
|
"@tonaljs/roman-numeral": "^4.6.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tonaljs/midi": {
|
||||||
|
"version": "4.6.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tonaljs/midi/-/midi-4.6.5.tgz",
|
||||||
|
"integrity": "sha512-fJEZtNvV3M6yW1w+Tep60Rbv5PvuKszQcQzaJS1Loq5mHOKAzdmRfuJSpEpZBiaKEZ1WAMh1QKXYyOd+imyGQg==",
|
||||||
|
"dependencies": {
|
||||||
|
"@tonaljs/core": "^4.6.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tonaljs/mode": {
|
||||||
|
"version": "4.6.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tonaljs/mode/-/mode-4.6.5.tgz",
|
||||||
|
"integrity": "sha512-54iaON1rJ6q8fV5iuei8RGDxYhKBGGxZz3rjAxGSqdTUwBRVOdPqtzOkofThf9gRGYOMhzPp1BMbxbV+UCAPsA==",
|
||||||
|
"dependencies": {
|
||||||
|
"@tonaljs/collection": "^4.6.2",
|
||||||
|
"@tonaljs/core": "^4.6.5",
|
||||||
|
"@tonaljs/interval": "^4.6.5",
|
||||||
|
"@tonaljs/pcset": "^4.6.5",
|
||||||
|
"@tonaljs/scale-type": "^4.6.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tonaljs/note": {
|
||||||
|
"version": "4.6.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tonaljs/note/-/note-4.6.5.tgz",
|
||||||
|
"integrity": "sha512-Y0/eTzcReXzfcSLLG4k/dLLayqbvh/XYIkybG/QMDyR0BREuJq0Sw+NavbzhTtO0dadIQb/qfe0GFq4k2xS+NQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"@tonaljs/core": "^4.6.5",
|
||||||
|
"@tonaljs/midi": "^4.6.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tonaljs/pcset": {
|
||||||
|
"version": "4.6.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tonaljs/pcset/-/pcset-4.6.5.tgz",
|
||||||
|
"integrity": "sha512-oWAKflP3cREnUfScqsBzg2LLKNevxSnpDtrq8CPtwOAsrAa8PjQG07NQfhqIiFMjPUdgkDiER3qVA1n8dDwAJA==",
|
||||||
|
"dependencies": {
|
||||||
|
"@tonaljs/collection": "^4.6.2",
|
||||||
|
"@tonaljs/core": "^4.6.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tonaljs/progression": {
|
||||||
|
"version": "4.6.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tonaljs/progression/-/progression-4.6.5.tgz",
|
||||||
|
"integrity": "sha512-ijYEgMFQG4izHYUw5cRtBRNBuoYzmpGvb/tRiykhJNI6XIjekZEMiMsOMfb1u5q+EGvnVNXRmrluMRDIz2rmRw==",
|
||||||
|
"dependencies": {
|
||||||
|
"@tonaljs/chord": "^4.6.5",
|
||||||
|
"@tonaljs/core": "^4.6.5",
|
||||||
|
"@tonaljs/roman-numeral": "^4.6.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tonaljs/range": {
|
||||||
|
"version": "4.6.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tonaljs/range/-/range-4.6.5.tgz",
|
||||||
|
"integrity": "sha512-99cOvVJ3l4X0UJuTSa6qE87JriREnnWIsi3xo1/n7RoqFxnfi8YPh4SfJJyysvHcT18X4EfcTNde9ancMBVu6A==",
|
||||||
|
"dependencies": {
|
||||||
|
"@tonaljs/collection": "^4.6.2",
|
||||||
|
"@tonaljs/midi": "^4.6.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tonaljs/roman-numeral": {
|
||||||
|
"version": "4.6.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tonaljs/roman-numeral/-/roman-numeral-4.6.5.tgz",
|
||||||
|
"integrity": "sha512-bWYQNZWKmYDDcmbQQNwcWAHfTWanpzmvI0wplrMnGd4x0op5etwUEv+Yzjg0B1ef+E+zcU02Sl0WwRJhaDK3hg==",
|
||||||
|
"dependencies": {
|
||||||
|
"@tonaljs/core": "^4.6.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tonaljs/scale": {
|
||||||
|
"version": "4.6.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tonaljs/scale/-/scale-4.6.5.tgz",
|
||||||
|
"integrity": "sha512-isYDamelOBtcd5bEnJ8QV0Js7jKRwZ0FlFVE/+bUN3wsyo9u6KLL5gMyfH9RKdx74m8lE13JXYTXgKqe+AOa4A==",
|
||||||
|
"dependencies": {
|
||||||
|
"@tonaljs/chord-type": "^4.6.5",
|
||||||
|
"@tonaljs/collection": "^4.6.2",
|
||||||
|
"@tonaljs/core": "^4.6.5",
|
||||||
|
"@tonaljs/note": "^4.6.5",
|
||||||
|
"@tonaljs/pcset": "^4.6.5",
|
||||||
|
"@tonaljs/scale-type": "^4.6.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tonaljs/scale-type": {
|
||||||
|
"version": "4.6.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tonaljs/scale-type/-/scale-type-4.6.5.tgz",
|
||||||
|
"integrity": "sha512-rwcDOYf2UifjLJhmuQ8f8bJSeOCMDQJ1lB7lzlqdFxes03OeQhdOEfrT0nPtW8BhBEvq4GMM2NA6CLxX8MTwOQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"@tonaljs/core": "^4.6.5",
|
||||||
|
"@tonaljs/pcset": "^4.6.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tonaljs/time-signature": {
|
||||||
|
"version": "4.6.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tonaljs/time-signature/-/time-signature-4.6.2.tgz",
|
||||||
|
"integrity": "sha512-OlZY4gdLd21WpMeAI1nS9E9zWcYU6oAzh6ptAUndqmVnFIrIWIWKCkWapdFx8dWdqrX8jqya3m4T33wmeo7w5Q=="
|
||||||
|
},
|
||||||
|
"node_modules/@tonaljs/tonal": {
|
||||||
|
"version": "4.6.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tonaljs/tonal/-/tonal-4.6.5.tgz",
|
||||||
|
"integrity": "sha512-lmsWinI9dy7nQyzCEgDVeVAwJtsk4ey05cJZd6oa4QVuSFD+CR8ebaEiwT4/Na+W0kHrKicT3h0uYc2PJIvx5Q==",
|
||||||
|
"dependencies": {
|
||||||
|
"@tonaljs/abc-notation": "^4.6.5",
|
||||||
|
"@tonaljs/array": "^4.6.5",
|
||||||
|
"@tonaljs/chord": "^4.6.5",
|
||||||
|
"@tonaljs/chord-type": "^4.6.5",
|
||||||
|
"@tonaljs/collection": "^4.6.2",
|
||||||
|
"@tonaljs/core": "^4.6.5",
|
||||||
|
"@tonaljs/duration-value": "^4.6.2",
|
||||||
|
"@tonaljs/interval": "^4.6.5",
|
||||||
|
"@tonaljs/key": "^4.6.5",
|
||||||
|
"@tonaljs/midi": "^4.6.5",
|
||||||
|
"@tonaljs/mode": "^4.6.5",
|
||||||
|
"@tonaljs/note": "^4.6.5",
|
||||||
|
"@tonaljs/pcset": "^4.6.5",
|
||||||
|
"@tonaljs/progression": "^4.6.5",
|
||||||
|
"@tonaljs/range": "^4.6.5",
|
||||||
|
"@tonaljs/roman-numeral": "^4.6.5",
|
||||||
|
"@tonaljs/scale": "^4.6.5",
|
||||||
|
"@tonaljs/scale-type": "^4.6.5",
|
||||||
|
"@tonaljs/time-signature": "^4.6.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@tootallnate/once": {
|
"node_modules/@tootallnate/once": {
|
||||||
"version": "1.1.2",
|
"version": "1.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz",
|
||||||
|
|
@ -2688,6 +2891,11 @@
|
||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/codemirror": {
|
||||||
|
"version": "5.65.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.65.1.tgz",
|
||||||
|
"integrity": "sha512-s6aac+DD+4O2u1aBmdxhB7yz2XU7tG3snOyQ05Kxifahz7hoxnfxIRHxiCSEv3TUC38dIVH8G+lZH9UWSfGQxA=="
|
||||||
|
},
|
||||||
"node_modules/color-convert": {
|
"node_modules/color-convert": {
|
||||||
"version": "1.9.3",
|
"version": "1.9.3",
|
||||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
|
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
|
||||||
|
|
@ -6067,6 +6275,18 @@
|
||||||
"node": "*"
|
"node": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/peggy": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/peggy/-/peggy-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-PQ+NKpAobImfMprYQtc4Egmyi29bidRGEX0kKjCU5uuW09s0Cthwqhfy7mLkwcB4VcgacE5L/ZjruD/kOPCUUw==",
|
||||||
|
"dev": true,
|
||||||
|
"bin": {
|
||||||
|
"peggy": "bin/peggy"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/pend": {
|
"node_modules/pend": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
|
||||||
|
|
@ -6631,6 +6851,15 @@
|
||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/react-codemirror2": {
|
||||||
|
"version": "7.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-codemirror2/-/react-codemirror2-7.2.1.tgz",
|
||||||
|
"integrity": "sha512-t7YFmz1AXdlImgHXA9Ja0T6AWuopilub24jRaQdPVbzUJVNKIYuy3uCFZYa7CE5S3UW6SrSa5nAqVQvtzRF9gw==",
|
||||||
|
"peerDependencies": {
|
||||||
|
"codemirror": "5.x",
|
||||||
|
"react": ">=15.5 <=16.x"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/react-dom": {
|
"node_modules/react-dom": {
|
||||||
"version": "17.0.2",
|
"version": "17.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz",
|
||||||
|
|
@ -9224,6 +9453,205 @@
|
||||||
"@testing-library/dom": "^7.28.1"
|
"@testing-library/dom": "^7.28.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@tonaljs/abc-notation": {
|
||||||
|
"version": "4.6.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tonaljs/abc-notation/-/abc-notation-4.6.5.tgz",
|
||||||
|
"integrity": "sha512-1S0Jnx0NfDLgyhkQOMEHqOacELL6RUdPcWWUP+nAnsOsb9owvB9RKYLSzp5odd16FVUR7U8c/JLc2yxIRvSeJw==",
|
||||||
|
"requires": {
|
||||||
|
"@tonaljs/core": "^4.6.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@tonaljs/array": {
|
||||||
|
"version": "4.6.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tonaljs/array/-/array-4.6.5.tgz",
|
||||||
|
"integrity": "sha512-7A3DbBQ+qIQ134FqE518b4tJ8V2a15Sn303JjHzgnqZqKrNh/s3wqwkL60F7LKcd09tcp+vIKQP/MYt4xMcRAA==",
|
||||||
|
"requires": {
|
||||||
|
"@tonaljs/core": "^4.6.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@tonaljs/chord": {
|
||||||
|
"version": "4.6.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tonaljs/chord/-/chord-4.6.5.tgz",
|
||||||
|
"integrity": "sha512-Pjdel4aDVv4kcx9PW6Qozt5BB9nAt13AOExfzKztpgPmlBSy0SKHse7Jp1cA4MGAuLHU8dzVssTFYpCskEFw3w==",
|
||||||
|
"requires": {
|
||||||
|
"@tonaljs/chord-detect": "^4.6.5",
|
||||||
|
"@tonaljs/chord-type": "^4.6.5",
|
||||||
|
"@tonaljs/collection": "^4.6.2",
|
||||||
|
"@tonaljs/core": "^4.6.5",
|
||||||
|
"@tonaljs/pcset": "^4.6.5",
|
||||||
|
"@tonaljs/scale-type": "^4.6.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@tonaljs/chord-detect": {
|
||||||
|
"version": "4.6.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tonaljs/chord-detect/-/chord-detect-4.6.5.tgz",
|
||||||
|
"integrity": "sha512-4xu53UP4kNTfdTNpAAVijhXcQ+ypJqmeMnsST08ZXSjoYfJUhmf5rWDWfz36KOTtNdCA6AbYgdtTYV/Xw0nd/w==",
|
||||||
|
"requires": {
|
||||||
|
"@tonaljs/chord-type": "^4.6.5",
|
||||||
|
"@tonaljs/core": "^4.6.5",
|
||||||
|
"@tonaljs/pcset": "^4.6.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@tonaljs/chord-type": {
|
||||||
|
"version": "4.6.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tonaljs/chord-type/-/chord-type-4.6.5.tgz",
|
||||||
|
"integrity": "sha512-Ol4DDopqpZCF9odosO2i8I+plud3Ul7VWJGNvL+PPCf4Qnwuz87q3aJQDLNoRUz4VyW0u66mq3LyVh6A8kb6Ug==",
|
||||||
|
"requires": {
|
||||||
|
"@tonaljs/core": "^4.6.5",
|
||||||
|
"@tonaljs/pcset": "^4.6.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@tonaljs/collection": {
|
||||||
|
"version": "4.6.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tonaljs/collection/-/collection-4.6.2.tgz",
|
||||||
|
"integrity": "sha512-bfPCotLJNB/tG1NrdbsQPLDKZB5jlMs7uPQ6RYKiNkaena3345ZKkbCGl5pj6YTXeDm/oblXiSbFAn7SlLRZdQ=="
|
||||||
|
},
|
||||||
|
"@tonaljs/core": {
|
||||||
|
"version": "4.6.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tonaljs/core/-/core-4.6.5.tgz",
|
||||||
|
"integrity": "sha512-t7Vx0+L3j/ubQj2AhI1H45D/K745np4DwJjJjXNi5FlGD+TL2wyw50dCwkHKGHsrLDqup1qqP6yN7LBpC6UwNg=="
|
||||||
|
},
|
||||||
|
"@tonaljs/duration-value": {
|
||||||
|
"version": "4.6.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tonaljs/duration-value/-/duration-value-4.6.2.tgz",
|
||||||
|
"integrity": "sha512-zrXT0L/qsDQ6251Mlqz54vcUbYUB9xb6uJhlxUzc6VauXOt8UOfrdTULubRTXTaBwWt1h8J5n9pXTQmNGzNI9A=="
|
||||||
|
},
|
||||||
|
"@tonaljs/interval": {
|
||||||
|
"version": "4.6.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tonaljs/interval/-/interval-4.6.5.tgz",
|
||||||
|
"integrity": "sha512-7EDWhqZ7Nnh9oD4ahRYJHLc799ACGxYL4hDHwMKD16B2MgXqPvDeDvwQ31qUuO0ruGz8tMb3FDlgg0Hplowcbw==",
|
||||||
|
"requires": {
|
||||||
|
"@tonaljs/core": "^4.6.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@tonaljs/key": {
|
||||||
|
"version": "4.6.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tonaljs/key/-/key-4.6.5.tgz",
|
||||||
|
"integrity": "sha512-ZdZWb5IStx6CLRmdEjawR66CqNpoW3EVUua2nVZBMdgnNebWxt4nvgH/ZNvGlCQGFZkUZzRhCfTwqsS6e3OmSA==",
|
||||||
|
"requires": {
|
||||||
|
"@tonaljs/core": "^4.6.5",
|
||||||
|
"@tonaljs/note": "^4.6.5",
|
||||||
|
"@tonaljs/roman-numeral": "^4.6.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@tonaljs/midi": {
|
||||||
|
"version": "4.6.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tonaljs/midi/-/midi-4.6.5.tgz",
|
||||||
|
"integrity": "sha512-fJEZtNvV3M6yW1w+Tep60Rbv5PvuKszQcQzaJS1Loq5mHOKAzdmRfuJSpEpZBiaKEZ1WAMh1QKXYyOd+imyGQg==",
|
||||||
|
"requires": {
|
||||||
|
"@tonaljs/core": "^4.6.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@tonaljs/mode": {
|
||||||
|
"version": "4.6.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tonaljs/mode/-/mode-4.6.5.tgz",
|
||||||
|
"integrity": "sha512-54iaON1rJ6q8fV5iuei8RGDxYhKBGGxZz3rjAxGSqdTUwBRVOdPqtzOkofThf9gRGYOMhzPp1BMbxbV+UCAPsA==",
|
||||||
|
"requires": {
|
||||||
|
"@tonaljs/collection": "^4.6.2",
|
||||||
|
"@tonaljs/core": "^4.6.5",
|
||||||
|
"@tonaljs/interval": "^4.6.5",
|
||||||
|
"@tonaljs/pcset": "^4.6.5",
|
||||||
|
"@tonaljs/scale-type": "^4.6.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@tonaljs/note": {
|
||||||
|
"version": "4.6.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tonaljs/note/-/note-4.6.5.tgz",
|
||||||
|
"integrity": "sha512-Y0/eTzcReXzfcSLLG4k/dLLayqbvh/XYIkybG/QMDyR0BREuJq0Sw+NavbzhTtO0dadIQb/qfe0GFq4k2xS+NQ==",
|
||||||
|
"requires": {
|
||||||
|
"@tonaljs/core": "^4.6.5",
|
||||||
|
"@tonaljs/midi": "^4.6.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@tonaljs/pcset": {
|
||||||
|
"version": "4.6.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tonaljs/pcset/-/pcset-4.6.5.tgz",
|
||||||
|
"integrity": "sha512-oWAKflP3cREnUfScqsBzg2LLKNevxSnpDtrq8CPtwOAsrAa8PjQG07NQfhqIiFMjPUdgkDiER3qVA1n8dDwAJA==",
|
||||||
|
"requires": {
|
||||||
|
"@tonaljs/collection": "^4.6.2",
|
||||||
|
"@tonaljs/core": "^4.6.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@tonaljs/progression": {
|
||||||
|
"version": "4.6.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tonaljs/progression/-/progression-4.6.5.tgz",
|
||||||
|
"integrity": "sha512-ijYEgMFQG4izHYUw5cRtBRNBuoYzmpGvb/tRiykhJNI6XIjekZEMiMsOMfb1u5q+EGvnVNXRmrluMRDIz2rmRw==",
|
||||||
|
"requires": {
|
||||||
|
"@tonaljs/chord": "^4.6.5",
|
||||||
|
"@tonaljs/core": "^4.6.5",
|
||||||
|
"@tonaljs/roman-numeral": "^4.6.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@tonaljs/range": {
|
||||||
|
"version": "4.6.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tonaljs/range/-/range-4.6.5.tgz",
|
||||||
|
"integrity": "sha512-99cOvVJ3l4X0UJuTSa6qE87JriREnnWIsi3xo1/n7RoqFxnfi8YPh4SfJJyysvHcT18X4EfcTNde9ancMBVu6A==",
|
||||||
|
"requires": {
|
||||||
|
"@tonaljs/collection": "^4.6.2",
|
||||||
|
"@tonaljs/midi": "^4.6.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@tonaljs/roman-numeral": {
|
||||||
|
"version": "4.6.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tonaljs/roman-numeral/-/roman-numeral-4.6.5.tgz",
|
||||||
|
"integrity": "sha512-bWYQNZWKmYDDcmbQQNwcWAHfTWanpzmvI0wplrMnGd4x0op5etwUEv+Yzjg0B1ef+E+zcU02Sl0WwRJhaDK3hg==",
|
||||||
|
"requires": {
|
||||||
|
"@tonaljs/core": "^4.6.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@tonaljs/scale": {
|
||||||
|
"version": "4.6.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tonaljs/scale/-/scale-4.6.5.tgz",
|
||||||
|
"integrity": "sha512-isYDamelOBtcd5bEnJ8QV0Js7jKRwZ0FlFVE/+bUN3wsyo9u6KLL5gMyfH9RKdx74m8lE13JXYTXgKqe+AOa4A==",
|
||||||
|
"requires": {
|
||||||
|
"@tonaljs/chord-type": "^4.6.5",
|
||||||
|
"@tonaljs/collection": "^4.6.2",
|
||||||
|
"@tonaljs/core": "^4.6.5",
|
||||||
|
"@tonaljs/note": "^4.6.5",
|
||||||
|
"@tonaljs/pcset": "^4.6.5",
|
||||||
|
"@tonaljs/scale-type": "^4.6.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@tonaljs/scale-type": {
|
||||||
|
"version": "4.6.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tonaljs/scale-type/-/scale-type-4.6.5.tgz",
|
||||||
|
"integrity": "sha512-rwcDOYf2UifjLJhmuQ8f8bJSeOCMDQJ1lB7lzlqdFxes03OeQhdOEfrT0nPtW8BhBEvq4GMM2NA6CLxX8MTwOQ==",
|
||||||
|
"requires": {
|
||||||
|
"@tonaljs/core": "^4.6.5",
|
||||||
|
"@tonaljs/pcset": "^4.6.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@tonaljs/time-signature": {
|
||||||
|
"version": "4.6.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tonaljs/time-signature/-/time-signature-4.6.2.tgz",
|
||||||
|
"integrity": "sha512-OlZY4gdLd21WpMeAI1nS9E9zWcYU6oAzh6ptAUndqmVnFIrIWIWKCkWapdFx8dWdqrX8jqya3m4T33wmeo7w5Q=="
|
||||||
|
},
|
||||||
|
"@tonaljs/tonal": {
|
||||||
|
"version": "4.6.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tonaljs/tonal/-/tonal-4.6.5.tgz",
|
||||||
|
"integrity": "sha512-lmsWinI9dy7nQyzCEgDVeVAwJtsk4ey05cJZd6oa4QVuSFD+CR8ebaEiwT4/Na+W0kHrKicT3h0uYc2PJIvx5Q==",
|
||||||
|
"requires": {
|
||||||
|
"@tonaljs/abc-notation": "^4.6.5",
|
||||||
|
"@tonaljs/array": "^4.6.5",
|
||||||
|
"@tonaljs/chord": "^4.6.5",
|
||||||
|
"@tonaljs/chord-type": "^4.6.5",
|
||||||
|
"@tonaljs/collection": "^4.6.2",
|
||||||
|
"@tonaljs/core": "^4.6.5",
|
||||||
|
"@tonaljs/duration-value": "^4.6.2",
|
||||||
|
"@tonaljs/interval": "^4.6.5",
|
||||||
|
"@tonaljs/key": "^4.6.5",
|
||||||
|
"@tonaljs/midi": "^4.6.5",
|
||||||
|
"@tonaljs/mode": "^4.6.5",
|
||||||
|
"@tonaljs/note": "^4.6.5",
|
||||||
|
"@tonaljs/pcset": "^4.6.5",
|
||||||
|
"@tonaljs/progression": "^4.6.5",
|
||||||
|
"@tonaljs/range": "^4.6.5",
|
||||||
|
"@tonaljs/roman-numeral": "^4.6.5",
|
||||||
|
"@tonaljs/scale": "^4.6.5",
|
||||||
|
"@tonaljs/scale-type": "^4.6.5",
|
||||||
|
"@tonaljs/time-signature": "^4.6.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@tootallnate/once": {
|
"@tootallnate/once": {
|
||||||
"version": "1.1.2",
|
"version": "1.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz",
|
||||||
|
|
@ -10524,6 +10952,11 @@
|
||||||
"integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=",
|
"integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"codemirror": {
|
||||||
|
"version": "5.65.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.65.1.tgz",
|
||||||
|
"integrity": "sha512-s6aac+DD+4O2u1aBmdxhB7yz2XU7tG3snOyQ05Kxifahz7hoxnfxIRHxiCSEv3TUC38dIVH8G+lZH9UWSfGQxA=="
|
||||||
|
},
|
||||||
"color-convert": {
|
"color-convert": {
|
||||||
"version": "1.9.3",
|
"version": "1.9.3",
|
||||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
|
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
|
||||||
|
|
@ -13113,6 +13546,12 @@
|
||||||
"integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==",
|
"integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"peggy": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/peggy/-/peggy-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-PQ+NKpAobImfMprYQtc4Egmyi29bidRGEX0kKjCU5uuW09s0Cthwqhfy7mLkwcB4VcgacE5L/ZjruD/kOPCUUw==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"pend": {
|
"pend": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
|
||||||
|
|
@ -13506,6 +13945,12 @@
|
||||||
"object-assign": "^4.1.1"
|
"object-assign": "^4.1.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"react-codemirror2": {
|
||||||
|
"version": "7.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-codemirror2/-/react-codemirror2-7.2.1.tgz",
|
||||||
|
"integrity": "sha512-t7YFmz1AXdlImgHXA9Ja0T6AWuopilub24jRaQdPVbzUJVNKIYuy3uCFZYa7CE5S3UW6SrSa5nAqVQvtzRF9gw==",
|
||||||
|
"requires": {}
|
||||||
|
},
|
||||||
"react-dom": {
|
"react-dom": {
|
||||||
"version": "17.0.2",
|
"version": "17.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz",
|
||||||
|
|
|
||||||
|
|
@ -4,10 +4,14 @@
|
||||||
"build": "snowpack build && cp ./public/.nojekyll ../docs",
|
"build": "snowpack build && cp ./public/.nojekyll ../docs",
|
||||||
"test": "web-test-runner \"src/**/*.test.tsx\"",
|
"test": "web-test-runner \"src/**/*.test.tsx\"",
|
||||||
"format": "prettier --write \"src/**/*.{js,jsx,ts,tsx}\"",
|
"format": "prettier --write \"src/**/*.{js,jsx,ts,tsx}\"",
|
||||||
"lint": "prettier --check \"src/**/*.{js,jsx,ts,tsx}\""
|
"lint": "prettier --check \"src/**/*.{js,jsx,ts,tsx}\"",
|
||||||
|
"peggy": "peggy -o krill-parser.js --format es ./krill.pegjs"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@tonaljs/tonal": "^4.6.5",
|
||||||
|
"codemirror": "^5.65.1",
|
||||||
"react": "^17.0.2",
|
"react": "^17.0.2",
|
||||||
|
"react-codemirror2": "^7.2.1",
|
||||||
"react-dom": "^17.0.2",
|
"react-dom": "^17.0.2",
|
||||||
"tone": "^14.7.77"
|
"tone": "^14.7.77"
|
||||||
},
|
},
|
||||||
|
|
@ -27,6 +31,7 @@
|
||||||
"@web/test-runner": "^0.13.3",
|
"@web/test-runner": "^0.13.3",
|
||||||
"autoprefixer": "^10.4.2",
|
"autoprefixer": "^10.4.2",
|
||||||
"chai": "^4.3.4",
|
"chai": "^4.3.4",
|
||||||
|
"peggy": "^1.2.0",
|
||||||
"postcss": "^8.4.6",
|
"postcss": "^8.4.6",
|
||||||
"prettier": "^2.2.1",
|
"prettier": "^2.2.1",
|
||||||
"snowpack": "^3.3.7",
|
"snowpack": "^3.3.7",
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,8 @@
|
||||||
@tailwind base;
|
@tailwind base;
|
||||||
@tailwind components;
|
@tailwind components;
|
||||||
@tailwind utilities;
|
@tailwind utilities;
|
||||||
|
|
||||||
|
.react-codemirror2,
|
||||||
|
.CodeMirror {
|
||||||
|
height: 100% !important;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,16 +5,15 @@ import cx from './cx';
|
||||||
import * as Tone from 'tone';
|
import * as Tone from 'tone';
|
||||||
import useCycle from './useCycle';
|
import useCycle from './useCycle';
|
||||||
import type { Hap, Pattern } from './types';
|
import type { Hap, Pattern } from './types';
|
||||||
import { tetris } from './tunes';
|
import * as tunes from './tunes';
|
||||||
|
import * as krill from './parse';
|
||||||
|
import CodeMirror from './CodeMirror';
|
||||||
|
|
||||||
const { Fraction, TimeSpan } = strudel;
|
const { tetris, tetrisMini, tetrisHaskell } = tunes;
|
||||||
|
|
||||||
const fr = (v: number) => new Fraction(v);
|
const { sequence, pure, reify, slowcat, fastcat, cat, stack, silence } = strudel; // make available to eval
|
||||||
const ts = (start: number, end: number) => new TimeSpan(fr(start), fr(end));
|
const { mini, h } = krill; // for eval (direct import wont work somehow)
|
||||||
const parse = (code: string): Pattern => {
|
const parse = (code: string): Pattern => eval(code);
|
||||||
const { sequence, pure, reify, slowcat, fastcat, cat, stack, silence } = strudel; // make available to eval
|
|
||||||
return eval(code);
|
|
||||||
};
|
|
||||||
|
|
||||||
const synth = new Tone.PolySynth().toDestination();
|
const synth = new Tone.PolySynth().toDestination();
|
||||||
synth.set({
|
synth.set({
|
||||||
|
|
@ -25,7 +24,8 @@ synth.set({
|
||||||
});
|
});
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
const [code, setCode] = useState<string>(tetris);
|
const [mode, setMode] = useState<string>('javascript');
|
||||||
|
const [code, setCode] = useState<string>(tetrisHaskell);
|
||||||
const [log, setLog] = useState('');
|
const [log, setLog] = useState('');
|
||||||
const logBox = useRef<any>();
|
const logBox = useRef<any>();
|
||||||
const [error, setError] = useState<Error>();
|
const [error, setError] = useState<Error>();
|
||||||
|
|
@ -65,11 +65,22 @@ function App() {
|
||||||
// parse pattern when code changes
|
// parse pattern when code changes
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
try {
|
try {
|
||||||
const _pattern = parse(code);
|
let _pattern;
|
||||||
|
try {
|
||||||
|
_pattern = h(code);
|
||||||
|
setMode('pegjs'); // haskell mode does not recognize quotes, pegjs looks ok by accident..
|
||||||
|
// console.log('h _pattern', _pattern);
|
||||||
|
} catch (err) {
|
||||||
|
setMode('javascript');
|
||||||
|
// code is not haskell like
|
||||||
|
_pattern = parse(code);
|
||||||
|
// console.log('not haskell..', _pattern);
|
||||||
|
}
|
||||||
setPattern(_pattern);
|
setPattern(_pattern);
|
||||||
// cycle.query(cycle.activeCycle()); // reschedule active cycle
|
// cycle.query(cycle.activeCycle()); // reschedule active cycle
|
||||||
setError(undefined);
|
setError(undefined);
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
|
console.warn(err);
|
||||||
setError(err);
|
setError(err);
|
||||||
}
|
}
|
||||||
}, [code]);
|
}, [code]);
|
||||||
|
|
@ -77,38 +88,51 @@ function App() {
|
||||||
useLayoutEffect(() => {
|
useLayoutEffect(() => {
|
||||||
logBox.current.scrollTop = logBox.current?.scrollHeight;
|
logBox.current.scrollTop = logBox.current?.scrollHeight;
|
||||||
}, [log]);
|
}, [log]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="h-[100vh] bg-slate-900 flex-row">
|
<div className="h-screen bg-slate-900 flex flex-col">
|
||||||
<header className="px-2 flex items-center space-x-2 border-b border-gray-200 bg-white">
|
<header className="flex-none w-full h-16 px-2 flex items-center space-x-2 border-b border-gray-200 bg-white">
|
||||||
<img src={logo} className="Tidal-logo w-16 h-16" alt="logo" />
|
<img src={logo} className="Tidal-logo w-16 h-16" alt="logo" />
|
||||||
<h1 className="text-2xl">Strudel REPL</h1>
|
<h1 className="text-2xl">Strudel REPL</h1>
|
||||||
</header>
|
</header>
|
||||||
<section className="grow p-2 text-gray-100">
|
<section className="grow flex flex-col p-2 text-gray-100">
|
||||||
<div className="relative">
|
<div className="grow relative">
|
||||||
<div className="absolute right-2 bottom-2 text-red-500">{error?.message}</div>
|
<div className={cx('h-full bg-slate-600', error ? 'focus:ring-red-500' : 'focus:ring-slate-800')}>
|
||||||
<textarea
|
<CodeMirror
|
||||||
|
value={code}
|
||||||
|
options={{
|
||||||
|
mode,
|
||||||
|
theme: 'material',
|
||||||
|
lineNumbers: true,
|
||||||
|
}}
|
||||||
|
onChange={(_: any, __: any, value: any) => {
|
||||||
|
setLog((log) => log + `${log ? '\n\n' : ''}✏️ edit\n${code}\n${value}`);
|
||||||
|
setCode(value);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{error && <div className="absolute right-2 bottom-2 text-red-500">{error?.message || 'unknown error'}</div>}
|
||||||
|
{/* <textarea
|
||||||
className={cx('w-full h-64 bg-slate-600', error ? 'focus:ring-red-500' : 'focus:ring-slate-800')}
|
className={cx('w-full h-64 bg-slate-600', error ? 'focus:ring-red-500' : 'focus:ring-slate-800')}
|
||||||
value={code}
|
value={code}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
setLog((log) => log + `${log ? '\n\n' : ''}✏️ edit\n${code}\n${e.target.value}`);
|
setLog((log) => log + `${log ? '\n\n' : ''}✏️ edit\n${code}\n${e.target.value}`);
|
||||||
setCode(e.target.value);
|
setCode(e.target.value);
|
||||||
}}
|
}}
|
||||||
/>
|
/> */}
|
||||||
</div>
|
</div>
|
||||||
|
<button
|
||||||
|
className="flex-none w-full border border-gray-700 p-2 bg-slate-700 hover:bg-slate-500"
|
||||||
|
onClick={() => cycle.toggle()}
|
||||||
|
>
|
||||||
|
{cycle.started ? 'pause' : 'play'}
|
||||||
|
</button>
|
||||||
<textarea
|
<textarea
|
||||||
className="w-full h-64 bg-slate-600"
|
className="grow bg-[#283237] border-0"
|
||||||
value={log}
|
value={log}
|
||||||
readOnly
|
readOnly
|
||||||
ref={logBox}
|
ref={logBox}
|
||||||
style={{ fontFamily: 'monospace' }}
|
style={{ fontFamily: 'monospace' }}
|
||||||
/>
|
/>
|
||||||
<button
|
|
||||||
className="w-full border border-gray-700 p-2 bg-slate-700 hover:bg-slate-500"
|
|
||||||
onClick={() => cycle.toggle()}
|
|
||||||
>
|
|
||||||
{cycle.started ? 'pause' : 'play'}
|
|
||||||
</button>
|
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
15
repl/src/CodeMirror.tsx
Normal file
15
repl/src/CodeMirror.tsx
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { Controlled as CodeMirror2 } from 'react-codemirror2';
|
||||||
|
import 'codemirror/mode/javascript/javascript.js';
|
||||||
|
import 'codemirror/mode/pegjs/pegjs.js';
|
||||||
|
import 'codemirror/theme/material.css';
|
||||||
|
import 'codemirror/lib/codemirror.css';
|
||||||
|
|
||||||
|
export default function CodeMirror({ value, onChange, options }: any) {
|
||||||
|
options = options || {
|
||||||
|
mode: 'javascript',
|
||||||
|
theme: 'material',
|
||||||
|
lineNumbers: true,
|
||||||
|
};
|
||||||
|
return <CodeMirror2 value={value} options={options} onBeforeChange={onChange} />;
|
||||||
|
}
|
||||||
18
repl/src/parse.d.ts
vendored
Normal file
18
repl/src/parse.d.ts
vendored
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
/*
|
||||||
|
TODO:
|
||||||
|
export interface Arguments {
|
||||||
|
alignment: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ElementStub {
|
||||||
|
type_: string;
|
||||||
|
source_: string;
|
||||||
|
options_?: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface PatternStub {
|
||||||
|
type_: string; // pattern
|
||||||
|
arguments_: Arguments;
|
||||||
|
source_: ElementStub[];
|
||||||
|
}
|
||||||
|
*/
|
||||||
101
repl/src/parse.ts
Normal file
101
repl/src/parse.ts
Normal file
|
|
@ -0,0 +1,101 @@
|
||||||
|
import * as krill from '../krill-parser';
|
||||||
|
import * as strudel from '../../strudel.mjs';
|
||||||
|
import { Scale, Note, Interval } from '@tonaljs/tonal';
|
||||||
|
|
||||||
|
const { sequence, stack, silence, Fraction, pure } = strudel;
|
||||||
|
|
||||||
|
function reify(thing: any) {
|
||||||
|
if (thing?.constructor?.name === 'Pattern') {
|
||||||
|
return thing;
|
||||||
|
}
|
||||||
|
return pure(thing);
|
||||||
|
}
|
||||||
|
|
||||||
|
const applyOptions = (parent: any) => (pat: any, i: number) => {
|
||||||
|
const ast = parent.source_[i];
|
||||||
|
const options = ast.options_;
|
||||||
|
const operator = options?.operator;
|
||||||
|
if (operator) {
|
||||||
|
switch (operator.type_) {
|
||||||
|
case 'stretch':
|
||||||
|
const speed = new Fraction(operator.arguments_.amount).inverse().valueOf();
|
||||||
|
return reify(pat).fast(speed);
|
||||||
|
// TODO: case 'fixed-step': "%"
|
||||||
|
}
|
||||||
|
console.warn(`operator "${operator.type_}" not implemented`);
|
||||||
|
}
|
||||||
|
// TODO: options.weight = "@"
|
||||||
|
// TODO: bjorklund e.g. "c3(5,8)"
|
||||||
|
const unimplemented = Object.keys(options || {}).filter((key) => key !== 'operator');
|
||||||
|
if (unimplemented.length) {
|
||||||
|
console.warn(
|
||||||
|
`option${unimplemented.length > 1 ? 's' : ''} ${unimplemented.map((o) => `"${o}"`).join(', ')} not implemented`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return pat;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function patternifyAST(ast: any): any {
|
||||||
|
switch (ast.type_) {
|
||||||
|
case 'pattern':
|
||||||
|
const children = ast.source_.map(patternifyAST).map(applyOptions(ast));
|
||||||
|
if (ast.arguments_.alignment === 'v') {
|
||||||
|
return stack(...children);
|
||||||
|
}
|
||||||
|
return sequence(...children);
|
||||||
|
case 'element':
|
||||||
|
if (ast.source_ === '~') {
|
||||||
|
return silence;
|
||||||
|
}
|
||||||
|
if (typeof ast.source_ !== 'object') {
|
||||||
|
return ast.source_;
|
||||||
|
}
|
||||||
|
return patternifyAST(ast.source_);
|
||||||
|
case 'stretch':
|
||||||
|
return patternifyAST(ast.source_).slow(ast.arguments_.amount);
|
||||||
|
case 'scale':
|
||||||
|
let [tonic, scale] = Scale.tokenize(ast.arguments_.scale);
|
||||||
|
const intervals = Scale.get(scale).intervals;
|
||||||
|
const pattern = patternifyAST(ast.source_);
|
||||||
|
tonic = tonic || 'C4';
|
||||||
|
// console.log('scale', ast, pattern, tonic, scale);
|
||||||
|
console.log('tonic', tonic);
|
||||||
|
return pattern.fmap((step: any) => {
|
||||||
|
step = Number(step);
|
||||||
|
if (isNaN(step)) {
|
||||||
|
console.warn(`scale step "${step}" not a number`);
|
||||||
|
return step;
|
||||||
|
}
|
||||||
|
const octaves = Math.floor(step / intervals.length);
|
||||||
|
const mod = (n: number, m: number): number => (n < 0 ? mod(n + m, m) : n % m);
|
||||||
|
const index = mod(step, intervals.length); // % with negative numbers. e.g. -1 % 3 = 2
|
||||||
|
const interval = Interval.add(intervals[index], Interval.fromSemitones(octaves * 12));
|
||||||
|
return Note.transpose(tonic, interval || '1P');
|
||||||
|
});
|
||||||
|
/* case 'struct':
|
||||||
|
// TODO:
|
||||||
|
return silence; */
|
||||||
|
default:
|
||||||
|
console.warn(`node type "${ast.type_}" not implemented -> returning silence`);
|
||||||
|
return silence;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// mini notation only (wraps in "")
|
||||||
|
export const mini = (...strings: string[]) => {
|
||||||
|
const pattern = sequence(
|
||||||
|
...strings.map((str) => {
|
||||||
|
const ast = krill.parse(`"${str}"`);
|
||||||
|
// console.log('ast', ast);
|
||||||
|
return patternifyAST(ast);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
return pattern;
|
||||||
|
};
|
||||||
|
|
||||||
|
// includes haskell style (raw krill parsing)
|
||||||
|
export const h = (string: string) => {
|
||||||
|
const ast = krill.parse(string);
|
||||||
|
// console.log('ast', ast);
|
||||||
|
return patternifyAST(ast);
|
||||||
|
};
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
export const tetris = `stack(sequence(
|
export const tetrisWithFunctions = `stack(sequence(
|
||||||
'e5', sequence('b4', 'c5'), 'd5', sequence('c5', 'b4'),
|
'e5', sequence('b4', 'c5'), 'd5', sequence('c5', 'b4'),
|
||||||
'a4', sequence('a4', 'c5'), 'e5', sequence('d5', 'c5'),
|
'a4', sequence('a4', 'c5'), 'e5', sequence('d5', 'c5'),
|
||||||
'b4', sequence(silence, 'c5'), 'd5', 'e5',
|
'b4', sequence(silence, 'c5'), 'd5', 'e5',
|
||||||
|
|
@ -19,6 +19,91 @@ export const tetris = `stack(sequence(
|
||||||
)
|
)
|
||||||
)._slow(16)`;
|
)._slow(16)`;
|
||||||
|
|
||||||
|
export const tetris = `stack(
|
||||||
|
sequence(
|
||||||
|
mini(
|
||||||
|
'e5 [b4 c5] d5 [c5 b4]',
|
||||||
|
'a4 [a4 c5] e5 [d5 c5]',
|
||||||
|
'b4 [~ c5] d5 e5',
|
||||||
|
'c5 a4 a4 ~',
|
||||||
|
'[~ d5] [~ f5] a5 [g5 f5]',
|
||||||
|
'e5 [~ c5] e5 [d5 c5]',
|
||||||
|
'b4 [b4 c5] d5 e5',
|
||||||
|
'c5 a4 a4 ~'
|
||||||
|
)
|
||||||
|
),
|
||||||
|
sequence(
|
||||||
|
mini(
|
||||||
|
'e2 e3 e2 e3 e2 e3 e2 e3',
|
||||||
|
'a2 a3 a2 a3 a2 a3 a2 a3',
|
||||||
|
'g#2 g#3 g#2 g#3 e2 e3 e2 e3',
|
||||||
|
'a2 a3 a2 a3 a2 a3 b1 c2',
|
||||||
|
'd2 d3 d2 d3 d2 d3 d2 d3',
|
||||||
|
'c2 c3 c2 c3 c2 c3 c2 c3',
|
||||||
|
'b1 b2 b1 b2 e2 e3 e2 e3',
|
||||||
|
'a1 a2 a1 a2 a1 a2 a1 a2'
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)._slow(16);`;
|
||||||
|
|
||||||
|
export const tetrisMini1 = `mini('[[e5 [b4 c5] d5 [c5 b4]] [a4 [a4 c5] e5 [d5 c5]] [b4 [~ c5] d5 e5] [c5 a4 a4 ~] [[~ d5] [~ f5] a5 [g5 f5]] [e5 [~ c5] e5 [d5 c5]] [b4 [b4 c5] d5 e5] [c5 a4 a4 ~]],[[e2 e3 e2 e3 e2 e3 e2 e3] [a2 a3 a2 a3 a2 a3 a2 a3] [g#2 g#3 g#2 g#3 e2 e3 e2 e3] [a2 a3 a2 a3 a2 a3 b1 c2] [d2 d3 d2 d3 d2 d3 d2 d3] [c2 c3 c2 c3 c2 c3 c2 c3] [b1 b2 b1 b2 e2 e3 e2 e3] [a1 a2 a1 a2 a1 a2 a1 a2]]')._slow(16);`;
|
||||||
|
export const tetrisMini = `mini(\`[[e5 [b4 c5] d5 [c5 b4]]
|
||||||
|
[a4 [a4 c5] e5 [d5 c5]]
|
||||||
|
[b4 [~ c5] d5 e5]
|
||||||
|
[c5 a4 a4 ~]
|
||||||
|
[[~ d5] [~ f5] a5 [g5 f5]]
|
||||||
|
[e5 [~ c5] e5 [d5 c5]]
|
||||||
|
[b4 [b4 c5] d5 e5]
|
||||||
|
[c5 a4 a4 ~]],
|
||||||
|
[[e2 e3]*4]
|
||||||
|
[[a2 a3]*4]
|
||||||
|
[[g#2 g#3]*2 [e2 e3]*2]
|
||||||
|
[a2 a3 a2 a3 a2 a3 b1 c2]
|
||||||
|
[[d2 d3]*4]
|
||||||
|
[[c2 c3]*4]
|
||||||
|
[[b1 b2]*2 [e2 e3]*2]
|
||||||
|
[[a1 a2]*4]\`)._slow(16);
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const tetrisHaskellH = `h(\`slow 16 $ "[[e5 [b4 c5] d5 [c5 b4]]
|
||||||
|
[a4 [a4 c5] e5 [d5 c5]]
|
||||||
|
[b4 [~ c5] d5 e5]
|
||||||
|
[c5 a4 a4 ~]
|
||||||
|
[[~ d5] [~ f5] a5 [g5 f5]]
|
||||||
|
[e5 [~ c5] e5 [d5 c5]]
|
||||||
|
[b4 [b4 c5] d5 e5]
|
||||||
|
[c5 a4 a4 ~]],
|
||||||
|
[[e2 e3]*4]
|
||||||
|
[[a2 a3]*4]
|
||||||
|
[[g#2 g#3]*2 [e2 e3]*2]
|
||||||
|
[a2 a3 a2 a3 a2 a3 b1 c2]
|
||||||
|
[[d2 d3]*4]
|
||||||
|
[[c2 c3]*4]
|
||||||
|
[[b1 b2]*2 [e2 e3]*2]
|
||||||
|
[[a1 a2]*4]"\`)
|
||||||
|
`;
|
||||||
|
export const tetrisHaskell = `slow 16 $ "[[e5 [b4 c5] d5 [c5 b4]]
|
||||||
|
[a4 [a4 c5] e5 [d5 c5]]
|
||||||
|
[b4 [~ c5] d5 e5]
|
||||||
|
[c5 a4 a4 ~]
|
||||||
|
[[~ d5] [~ f5] a5 [g5 f5]]
|
||||||
|
[e5 [~ c5] e5 [d5 c5]]
|
||||||
|
[b4 [b4 c5] d5 e5]
|
||||||
|
[c5 a4 a4 ~]],
|
||||||
|
[[e2 e3]*4]
|
||||||
|
[[a2 a3]*4]
|
||||||
|
[[g#2 g#3]*2 [e2 e3]*2]
|
||||||
|
[a2 a3 a2 a3 a2 a3 b1 c2]
|
||||||
|
[[d2 d3]*4]
|
||||||
|
[[c2 c3]*4]
|
||||||
|
[[b1 b2]*2 [e2 e3]*2]
|
||||||
|
[[a1 a2]*4]"
|
||||||
|
`;
|
||||||
|
|
||||||
|
/*
|
||||||
|
export const tetrisHaskell = `h(\`slow 16 $ "[[e5 [b4 c5] d5 [c5 b4]] [a4 [a4 c5] e5 [d5 c5]] [b4 [~ c5] d5 e5] [c5 a4 a4 ~] [[~ d5] [~ f5] a5 [g5 f5]] [e5 [~ c5] e5 [d5 c5]] [b4 [b4 c5] d5 e5] [c5 a4 a4 ~]], [[e2 e3]*4] [[a2 a3]*4] [[g#2 g#3]*2 [e2 e3]*2] [a2 a3 a2 a3 a2 a3 b1 c2] [[d2 d3]*4] [[c2 c3]*4] [[b1 b2]*2 [e2 e3]*2] [[a1 a2]*4]"\`)`;
|
||||||
|
*/
|
||||||
|
|
||||||
// "sequence('c3', 'eb3', sequence('g3', 'f3'))" //
|
// "sequence('c3', 'eb3', sequence('g3', 'f3'))" //
|
||||||
/* `sequence(
|
/* `sequence(
|
||||||
stack('c4','eb4','g4'),
|
stack('c4','eb4','g4'),
|
||||||
|
|
|
||||||
1
repl/src/types.d.ts
vendored
1
repl/src/types.d.ts
vendored
|
|
@ -19,4 +19,5 @@ export declare interface Hap<T = any> {
|
||||||
}
|
}
|
||||||
export declare interface Pattern<T = any> {
|
export declare interface Pattern<T = any> {
|
||||||
query: (span: TimeSpan) => Hap<T>[];
|
query: (span: TimeSpan) => Hap<T>[];
|
||||||
|
fmap: (v: T) => T;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -47,16 +47,18 @@ function useCycle(props: UseCycleProps) {
|
||||||
}, queryNextTime);
|
}, queryNextTime);
|
||||||
}
|
}
|
||||||
// schedule events for next cycle
|
// schedule events for next cycle
|
||||||
events?.forEach((event) => {
|
events
|
||||||
Tone.Transport.schedule((time) => {
|
?.filter((event) => event.part.begin.valueOf() === event.whole.begin.valueOf())
|
||||||
const toneEvent = {
|
.forEach((event) => {
|
||||||
time: event.part.begin.valueOf(),
|
Tone.Transport.schedule((time) => {
|
||||||
duration: event.part.end.valueOf() - event.part.begin.valueOf(),
|
const toneEvent = {
|
||||||
value: event.value,
|
time: event.part.begin.valueOf(),
|
||||||
};
|
duration: event.whole.end.valueOf() - event.whole.begin.valueOf(),
|
||||||
onEvent(time, toneEvent);
|
value: event.value,
|
||||||
}, event.part.begin.valueOf());
|
};
|
||||||
});
|
onEvent(time, toneEvent);
|
||||||
|
}, event.part.begin.valueOf());
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,9 @@ import { strict as assert } from 'assert';
|
||||||
|
|
||||||
import {TimeSpan, Hap, Pattern, pure, stack, fastcat, slowcat, cat, sequence, polyrhythm} from "../strudel.mjs";
|
import {TimeSpan, Hap, Pattern, pure, stack, fastcat, slowcat, cat, sequence, polyrhythm} from "../strudel.mjs";
|
||||||
|
|
||||||
|
const ts = (begin, end) => new TimeSpan(Fraction(begin), Fraction(end));
|
||||||
|
const hap = (whole, part, value) => new Hap(whole, part, value)
|
||||||
|
|
||||||
describe('TimeSpan', function() {
|
describe('TimeSpan', function() {
|
||||||
describe('equals()', function() {
|
describe('equals()', function() {
|
||||||
it('Should be equal to the same value', function() {
|
it('Should be equal to the same value', function() {
|
||||||
|
|
@ -99,6 +102,21 @@ describe('Pattern', function() {
|
||||||
describe('_slow()', function () {
|
describe('_slow()', function () {
|
||||||
it('Makes things slower', function () {
|
it('Makes things slower', function () {
|
||||||
assert.deepStrictEqual(pure("a")._slow(2).firstCycle[0], new Hap(new TimeSpan(Fraction(0),Fraction(2)), new TimeSpan(Fraction(0), Fraction(1)), "a"))
|
assert.deepStrictEqual(pure("a")._slow(2).firstCycle[0], new Hap(new TimeSpan(Fraction(0),Fraction(2)), new TimeSpan(Fraction(0), Fraction(1)), "a"))
|
||||||
|
|
||||||
|
const pat = sequence(pure('c3'), pure('eb3')._slow(2)); // => try mini('c3 eb3/2') in repl
|
||||||
|
assert.deepStrictEqual(
|
||||||
|
pat.query(ts(0,1))[1],
|
||||||
|
hap(ts(0,1), ts(1/2,1), "eb3")
|
||||||
|
)
|
||||||
|
// the following test fails
|
||||||
|
/* assert.deepStrictEqual(
|
||||||
|
pat.query(ts(1,2))[1], undefined
|
||||||
|
) */
|
||||||
|
// expecting [c3 eb3] [c3 ~]
|
||||||
|
// what happens [c3 eb3] [c3 eb3]
|
||||||
|
// notable examples:
|
||||||
|
// mini('[c3 g3]/2 eb3') always plays [c3 eb3]
|
||||||
|
// mini('eb3 [c3 g3]/2 ') always plays [c3 g3]
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
describe('_filterValues()', function () {
|
describe('_filterValues()', function () {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue