Skip to content

Commit

Permalink
Add features for embedded editors for Wasm from the Ground Up
Browse files Browse the repository at this point in the history
  • Loading branch information
pdubroy committed Apr 26, 2023
1 parent 5bf185f commit 3233731
Show file tree
Hide file tree
Showing 5 changed files with 135 additions and 12 deletions.
24 changes: 22 additions & 2 deletions public/style/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
--color-failure-3: #e53935;

--editor-font: Menlo, Monaco, sans-serif;

--grey-text-color: #666;
}

html,
Expand Down Expand Up @@ -102,6 +104,10 @@ body {
position: fixed;
right: 15px;
}
body.embedded #optionPanel {
display: none;
}

#options input[type='checkbox'] {
position: relative;
margin: 0 4px 0 0;
Expand Down Expand Up @@ -206,7 +212,8 @@ h2 {
}

.editorWrapper .CodeMirror,
.externalRules pre {
.externalRules pre,
.fakeJsDecl pre {
font-family: var(--editor-font);
font-size: 12px;
}
Expand Down Expand Up @@ -266,6 +273,7 @@ h2 {
}

.externalRules pre,
.fakeJsDecl pre,
.CodeMirror pre.CodeMirror-line {
padding-left: 20px;
}
Expand Down Expand Up @@ -299,9 +307,21 @@ h2 {
outline: none;
}

.fakeJsDecl pre {
color: var(--grey-text-color);
margin: 0;
}

.externalRules {
color: #999;
color: var(--grey-text-color);
margin: 0;
}

.noExternalRules .externalRules {
display: none;
}

.externalRules {
padding-top: 14px;
}
.externalRules .content {
Expand Down
8 changes: 8 additions & 0 deletions src/components/main-layout.vue
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,14 @@ export default {
exampleList.collapsed = false;
}
},
toggleExamplesCollapsed(collapsed = undefined) {
const {exampleList} = this.$refs;
if (collapsed === undefined) {
collapsed = !exampleList.collapsed;
}
exampleList.collapsed = collapsed;
this.onToggleExamplesCollapsed(collapsed);
},
},
};
</script>
111 changes: 103 additions & 8 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
/* eslint-env browser */
/* global CodeMirror, ohm */

import {$, $$} from './domUtil.js';
import {$, $$, createElement} from './domUtil.js';
import ohmEditor from './ohmEditor.js';

// TODO: Ideally these modules wouldn't do all their work as side effects.
import './editorErrors.js';
import './mainLayout.js';
import {mainLayout} from './mainLayout.js';
import './externalRules.js';
import './parseTree.js';
import './ruleHyperlinks.js';
Expand All @@ -19,6 +19,8 @@ let showFailuresImplicitly = true;

let grammarMatcher = ohm.ohmGrammar.matcher();

const urlParams = new URLSearchParams(window.location.search);

// Helpers
// -------

Expand Down Expand Up @@ -123,16 +125,107 @@ ohmEditor.saveState = function (editor, key) {
};

function initializeLayout() {
const params = new URLSearchParams(window.location.search);
const isEmbedded = params.get('embed') === 'true';

if (!isEmbedded) {
const {body} = document;

// When embedded:
// - examples pane is closed by default
// - don't enable persistence features.
if (urlParams.get('embed') === 'true') {
mainLayout.toggleExamplesCollapsed(true);
body.classList.add('embedded');
} else {
const scriptEl = document.createElement('script');
scriptEl.src = 'assets/persistence-bundle.js';
document.body.appendChild(scriptEl);
body.appendChild(scriptEl);
}

// Allow the grammar to be specified in the URL.
if (urlParams.has('jsGrammar')) {
const {prefix, grammar, suffix} = extractJsGrammar(
urlParams.get('jsGrammar')
);

ohmEditor.setGrammar(grammar);

const {grammarEditor} = ohmEditor.ui;
const topWidget = createElement('.fakeJsDecl');
topWidget.appendChild(createElement('pre', prefix));
grammarEditor.addLineWidget(0, topWidget, {above: true});

const bottomWidget = createElement('.fakeJsDecl');
bottomWidget.appendChild(createElement('pre', suffix));
grammarEditor.addLineWidget(grammarEditor.doc.size - 1, bottomWidget, {
insertAt: 0,
});
}

if (urlParams.has('readOnly')) {
let readOnly = urlParams.get('readOnly');
if (readOnly === 'true') {
readOnly = true; // Convert to boolean
}
ohmEditor.ui.grammarEditor.setOption('readOnly', readOnly);
}

if (urlParams.get('showExternalRules') === 'false') {
body.classList.add('noExternalRules');
}
}

// To support grammars that are directly embedded in JS code, this function
// can extract a grammar from a string literal. For example:
//
// const g = String.raw`
// G {
// ...
// }
// `;
const extractJsGrammar = (() => {
const g = ohm.grammar(
String.raw`
GrammarInStringLiteral <: Ohm {
Declaration
= LetOrConst ident "=" "String.raw"? backtickStringLiteral sc?
LetOrConst = let | const
backtickStringLiteral = openTick rawStringChar* closeTick
openTick = "\x60" "\n"?
closeTick = "\n"? "\x60"
rawStringChar = ~closeTick any
const = "const" &space
let = "let" &space
sc = ";"
}
`,
{Ohm: ohm.ohmGrammar}
);

const semantics = g.createSemantics().addOperation('extract', {
Declaration(letOrConst, ident, eq, raw, stringLiteral, sc) {
return {
grammar: stringLiteral.extract(),
prefix:
[letOrConst, ident, eq, raw].map(n => n.sourceString).join(' ') +
'`',
suffix: '`;',
};
},
backtickStringLiteral(_open, rawStringCharIter, _close) {
return rawStringCharIter.sourceString;
},
});

return code => {
const m = g.match(code, 'Declaration');
if (!m.succeeded()) {
throw new Error(m.message);
}
return semantics(m).extract();
};
})();

// Main
// ----

Expand Down Expand Up @@ -164,7 +257,9 @@ checkboxes.forEach(cb => {
});
});

ohmEditor.setGrammar(null /* restore local storage */);
if (!urlParams.has('jsGrammar')) {
ohmEditor.setGrammar(null /* restore local storage */);
}

ohmEditor.ui.inputEditor.on('change', cm => {
inputChanged = true;
Expand Down
2 changes: 1 addition & 1 deletion src/mainLayout.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import mainLayoutConfig from './components/main-layout.vue';

const MainLayout = Vue.component('main-layout', mainLayoutConfig);

new MainLayout({
export const mainLayout = new MainLayout({
el: '#mainLayout',
propsData: {},
});
2 changes: 1 addition & 1 deletion src/ohmMode.js
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ export function createModeFactory(ohm) {
});
};

const handleMultiLineRuleStart = (input, nextLine='') => {
const handleMultiLineRuleStart = (input, nextLine = '') => {
const tokens = [];
for (const [pos, tok] of withTokenPos(getTokens(input + nextLine))) {
if (pos > input.length) break;
Expand Down

0 comments on commit 3233731

Please sign in to comment.