mirror of
https://github.com/chinchang/web-maker.git
synced 2025-05-05 18:15:58 +02:00
commit
5c6f93a927
25
gulpfile.js
25
gulpfile.js
@ -22,8 +22,8 @@ function minifyJs(fileName) {
|
||||
).code;
|
||||
fs.writeFileSync(fileName, minifiedContent);
|
||||
console.log(
|
||||
`[${fileName}]: ${content.length / 1024}M -> ${minifiedContent.length /
|
||||
1024}M`
|
||||
`[${fileName}]: ${content.length / 1024}K -> ${minifiedContent.length /
|
||||
1024}K`
|
||||
);
|
||||
}
|
||||
gulp.task('runWebpack', function() {
|
||||
@ -41,6 +41,9 @@ gulp.task('copyFiles', function() {
|
||||
gulp.src('src/lib/transpilers/*').pipe(gulp.dest('app/lib/transpilers')),
|
||||
gulp.src('src/lib/prettier-worker.js').pipe(gulp.dest('app/lib/')),
|
||||
gulp.src('src/lib/prettier/*').pipe(gulp.dest('app/lib/prettier')),
|
||||
gulp
|
||||
.src(['!src/lib/monaco/monaco.bundle.js', 'src/lib/monaco/**/*'])
|
||||
.pipe(gulp.dest('app/lib/monaco')),
|
||||
gulp.src('src/lib/screenlog.js').pipe(gulp.dest('app/lib')),
|
||||
gulp.src('icons/*').pipe(gulp.dest('app/icons')),
|
||||
gulp.src('src/assets/*').pipe(gulp.dest('app/assets')),
|
||||
@ -63,6 +66,7 @@ gulp.task('copyFiles', function() {
|
||||
.src('build/vendor.*.js')
|
||||
.pipe(rename('vendor.js'))
|
||||
.pipe(gulp.dest('app')),
|
||||
gulp.src('build/monaco.*.js').pipe(gulp.dest('app')),
|
||||
|
||||
// Following CSS are copied to build/ folder where they'll be referenced by
|
||||
// useRef plugin to concat into one.
|
||||
@ -120,8 +124,11 @@ gulp.task('minify', function() {
|
||||
debug: true
|
||||
},
|
||||
details => {
|
||||
console.log(`${details.name}: ${details.stats.originalSize}`);
|
||||
console.log(`${details.name}: ${details.stats.minifiedSize}`);
|
||||
console.log(
|
||||
`${details.name}: ${details.stats.originalSize} 👉🏼 ${
|
||||
details.stats.minifiedSize
|
||||
}`
|
||||
);
|
||||
}
|
||||
)
|
||||
)
|
||||
@ -138,7 +145,7 @@ gulp.task('fixIndex', function() {
|
||||
|
||||
// vendor.hash.js gets created outside our markers, so remove it
|
||||
contents = contents.replace(
|
||||
/\<script src="\/vendor\.[\S\s]*?\<\/script\>/,
|
||||
/\<script src="[\S\s]*?vendor\.[\S\s]*?\<\/script\>/,
|
||||
''
|
||||
);
|
||||
|
||||
@ -171,18 +178,12 @@ gulp.task('packageExtension', function() {
|
||||
child_process.execSync('cp src/options.html extension');
|
||||
child_process.execSync('cp src/eventPage.js extension');
|
||||
child_process.execSync('cp src/icon-16.png extension');
|
||||
child_process.execSync(
|
||||
'rm -rf extension/service-worker.js extension/partials'
|
||||
);
|
||||
child_process.execSync('rm -rf extension/service-worker.js');
|
||||
return merge(
|
||||
gulp
|
||||
.src('build/bundle.*.js')
|
||||
.pipe(rename('script.js'))
|
||||
.pipe(gulp.dest('extension')),
|
||||
gulp
|
||||
.src('build/vendor.*.js')
|
||||
.pipe(rename('vendor.js'))
|
||||
.pipe(gulp.dest('extension')),
|
||||
|
||||
gulp
|
||||
.src('extension/**/*')
|
||||
|
@ -1,4 +1,3 @@
|
||||
import CopyWebpackPlugin from 'copy-webpack-plugin';
|
||||
var CommonsChunkPlugin = require('webpack/lib/optimize/CommonsChunkPlugin');
|
||||
|
||||
/**
|
||||
@ -29,6 +28,12 @@ export default function(config, env, helpers) {
|
||||
if (env.isProd) {
|
||||
config.devtool = false; // disable sourcemaps
|
||||
|
||||
// To support chunk loading in root and also /app path
|
||||
config.output.publicPath = './';
|
||||
|
||||
// Remove the default hash append in chunk name
|
||||
config.output.chunkFilename = '[name].chunk.js';
|
||||
|
||||
config.plugins.push(
|
||||
new CommonsChunkPlugin({
|
||||
name: 'vendor',
|
||||
|
390
src/components/CodeEditor.jsx
Normal file
390
src/components/CodeEditor.jsx
Normal file
@ -0,0 +1,390 @@
|
||||
import { h, Component } from 'preact';
|
||||
import CodeMirror from '../CodeMirror';
|
||||
|
||||
import 'codemirror/addon/edit/matchbrackets.js';
|
||||
import 'codemirror/addon/edit/matchtags.js';
|
||||
import 'codemirror/addon/edit/closebrackets.js';
|
||||
import 'codemirror/addon/edit/closetag.js';
|
||||
import 'codemirror/addon/comment/comment.js';
|
||||
import 'codemirror/addon/fold/foldcode.js';
|
||||
import 'codemirror/addon/fold/foldgutter.js';
|
||||
import 'codemirror/addon/fold/xml-fold.js';
|
||||
import 'codemirror/addon/fold/indent-fold.js';
|
||||
import 'codemirror/addon/fold/comment-fold.js';
|
||||
import 'codemirror/addon/fold/brace-fold.js';
|
||||
import 'codemirror/addon/hint/show-hint.js';
|
||||
import 'codemirror/addon/hint/javascript-hint.js';
|
||||
import 'codemirror/addon/hint/xml-hint.js';
|
||||
import 'codemirror/addon/hint/html-hint.js';
|
||||
import 'codemirror/addon/hint/css-hint.js';
|
||||
import 'codemirror/addon/selection/active-line.js';
|
||||
import 'codemirror/addon/search/searchcursor.js';
|
||||
import 'codemirror/addon/search/search.js';
|
||||
import 'codemirror/addon/dialog/dialog.js';
|
||||
import 'codemirror/addon/search/jump-to-line.js';
|
||||
|
||||
import 'codemirror/mode/xml/xml.js';
|
||||
import 'codemirror/mode/css/css.js';
|
||||
import 'codemirror/mode/javascript/javascript.js';
|
||||
import 'codemirror/mode/htmlmixed/htmlmixed.js';
|
||||
import 'codemirror/keymap/sublime.js';
|
||||
import 'codemirror/keymap/vim.js';
|
||||
import 'code-blast-codemirror/code-blast.js';
|
||||
|
||||
import emmet from '@emmetio/codemirror-plugin';
|
||||
import { prettify, loadCss } from '../utils';
|
||||
import { modes } from '../codeModes';
|
||||
import { deferred } from '../deferred';
|
||||
|
||||
emmet(CodeMirror);
|
||||
let monacoDepsDeferred;
|
||||
|
||||
window.MonacoEnvironment = {
|
||||
getWorkerUrl(moduleId, label) {
|
||||
switch (label) {
|
||||
case 'html':
|
||||
return 'lib/monaco/workers/html.worker.bundle.js';
|
||||
case 'json':
|
||||
return 'lib/monaco/workers/json.worker.bundle.js';
|
||||
case 'css':
|
||||
case 'scss':
|
||||
case 'less':
|
||||
return 'lib/monaco/workers/css.worker.bundle.js';
|
||||
case 'typescript':
|
||||
case 'javascript':
|
||||
return 'lib/monaco/workers/ts.worker.bundle.js';
|
||||
default:
|
||||
return 'lib/monaco/workers/editor.worker.bundle.js';
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export default class CodeEditor extends Component {
|
||||
componentDidMount() {
|
||||
this.initEditor();
|
||||
}
|
||||
shouldComponentUpdate(nextProps) {
|
||||
if (nextProps.prefs !== this.props.prefs) {
|
||||
const { prefs } = nextProps;
|
||||
|
||||
if (this.props.type === 'monaco') {
|
||||
this.instance.updateOptions({ fontSize: prefs.fontSize });
|
||||
} else {
|
||||
this.instance.setOption(
|
||||
'indentWithTabs',
|
||||
prefs.indentWith !== 'spaces'
|
||||
);
|
||||
this.instance.setOption(
|
||||
'blastCode',
|
||||
prefs.isCodeBlastOn ? { effect: 2, shake: false } : false
|
||||
);
|
||||
this.instance.setOption('theme', prefs.editorTheme);
|
||||
|
||||
this.instance.setOption('indentUnit', +prefs.indentSize);
|
||||
this.instance.setOption('tabSize', +prefs.indentSize);
|
||||
|
||||
this.instance.setOption('keyMap', prefs.keymap);
|
||||
this.instance.setOption('lineWrapping', prefs.lineWrap);
|
||||
this.instance.setOption('lineWrapping', prefs.autoCloseTags);
|
||||
|
||||
this.instance.refresh();
|
||||
}
|
||||
}
|
||||
|
||||
// Only condition when this component updates is when prop.type changes
|
||||
if (nextProps.type !== this.props.type) {
|
||||
if (
|
||||
this.node.parentElement.querySelector('.monaco-editor, .CodeMirror')
|
||||
) {
|
||||
this.node.parentElement
|
||||
.querySelector('.monaco-editor, .CodeMirror')
|
||||
.remove();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
componentDidUpdate(prevProps) {
|
||||
// prop.type changed, reinit the editor
|
||||
this.initEditor();
|
||||
}
|
||||
setModel(model) {
|
||||
this.instance.swapDoc
|
||||
? this.instance.swapDoc(model)
|
||||
: this.instance.setModel(model);
|
||||
}
|
||||
setValue(value) {
|
||||
// HACK: We set a flag on window for an ultra-short duration, which 'change'
|
||||
// listener uses to set the change.origin to 'setValue', otherwise it's
|
||||
// '+input'
|
||||
if (this.props.type === 'monaco') {
|
||||
window.monacoSetValTriggered = true;
|
||||
setTimeout(() => {
|
||||
window.monacoSetValTriggered = false;
|
||||
}, 1);
|
||||
}
|
||||
this.instance.setValue(value);
|
||||
// We save last set value so that when editor type changes, we can
|
||||
// populate that last value
|
||||
this.lastSetValue = value;
|
||||
}
|
||||
getValue() {
|
||||
return this.instance.getValue();
|
||||
}
|
||||
saveViewState() {
|
||||
if (this.props.type === 'monaco') {
|
||||
return this.instance.saveViewState();
|
||||
}
|
||||
}
|
||||
restoreViewState(state) {
|
||||
if (this.props.type === 'monaco') {
|
||||
this.instance.restoreViewState(state);
|
||||
}
|
||||
}
|
||||
setOption(option, value) {
|
||||
if (this.props.type === 'monaco') {
|
||||
this.monacoEditorReadyDeferred.promise.then(() => {
|
||||
this.instance.updateOptions({ [option]: value });
|
||||
});
|
||||
} else {
|
||||
this.instance.setOption(option, value);
|
||||
}
|
||||
}
|
||||
setLanguage(value) {
|
||||
if (!window.monaco) return;
|
||||
|
||||
if (this.props.type === 'monaco') {
|
||||
monaco.editor.setModelLanguage(
|
||||
this.instance.getModel(),
|
||||
this.getMonacoLanguageFromMode(modes[value].cmMode)
|
||||
);
|
||||
} else {
|
||||
this.instance.setOption('mode', modes[value].cmMode);
|
||||
CodeMirror.autoLoadMode(
|
||||
this.instance,
|
||||
modes[value].cmPath || modes[value].cmMode
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
clearGutter(gutterName) {
|
||||
if (this.instance.clearGutter) {
|
||||
this.instance.clearGutter(gutterName);
|
||||
}
|
||||
}
|
||||
|
||||
showErrors(errors) {
|
||||
if (this.props.type === 'codemirror') {
|
||||
errors.forEach(function(error) {
|
||||
this.instance.operation(function() {
|
||||
var n = document.createElement('div');
|
||||
n.setAttribute('data-title', error.message);
|
||||
n.classList.add('gutter-error-marker');
|
||||
editor.setGutterMarker(error.lineNumber, 'error-gutter', n);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
refresh() {
|
||||
this.instance.refresh ? this.instance.refresh() : this.instance.layout();
|
||||
}
|
||||
focus() {
|
||||
this.instance.focus();
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts codemirror mode value to monaco language values.
|
||||
* TODO: Refactor to not be codemirror related.
|
||||
* @param {string} mode Codemirror mode value
|
||||
*/
|
||||
getMonacoLanguageFromMode(mode) {
|
||||
if (['htmlmixed'].includes(mode)) {
|
||||
return 'html';
|
||||
}
|
||||
if (['css', 'sass', 'scss', 'less', 'stylus'].includes(mode)) {
|
||||
return 'css';
|
||||
}
|
||||
if (['javascript', 'text/typescript-jsx', 'jsx'].includes(mode)) {
|
||||
return 'javascript';
|
||||
}
|
||||
return mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the asynchronous deps according to the editor type.
|
||||
*/
|
||||
async loadDeps() {
|
||||
if (this.props.type === 'monaco') {
|
||||
if (!monacoDepsDeferred) {
|
||||
monacoDepsDeferred = deferred();
|
||||
loadCss({ url: 'lib/monaco/monaco.css', id: 'monaco-css' });
|
||||
import(/* webpackChunkName: "monaco" */ '../lib/monaco/monaco.bundle.js').then(
|
||||
() => {
|
||||
monacoDepsDeferred.resolve();
|
||||
}
|
||||
);
|
||||
}
|
||||
return monacoDepsDeferred.promise;
|
||||
}
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
async initEditor() {
|
||||
this.monacoEditorReadyDeferred = deferred();
|
||||
await this.loadDeps();
|
||||
|
||||
const { options, prefs } = this.props;
|
||||
if (this.props.type === 'monaco') {
|
||||
this.instance = monaco.editor.create(this.node, {
|
||||
language: this.getMonacoLanguageFromMode(options.mode),
|
||||
value: this.lastSetValue || '',
|
||||
roundedSelection: false,
|
||||
scrollBeyondLastLine: false,
|
||||
theme: 'vs-dark',
|
||||
fontSize: prefs.fontSize,
|
||||
minimap: {
|
||||
enabled: false
|
||||
},
|
||||
wordWrap: 'on',
|
||||
renderWhitespace: 'all',
|
||||
fontLigatures: true,
|
||||
automaticLayout: true
|
||||
});
|
||||
window.monacoInstance = this.instance;
|
||||
this.instance.onDidChangeModelContent(change => {
|
||||
this.props.onChange(this.instance, {
|
||||
...change,
|
||||
origin: window.monacoSetValTriggered ? 'setValue' : '+input'
|
||||
});
|
||||
});
|
||||
this.instance.addCommand(
|
||||
monaco.KeyMod.WinCtrl | monaco.KeyMod.Shift | monaco.KeyCode.KEY_F,
|
||||
() => {
|
||||
if (options.prettier) {
|
||||
prettify({
|
||||
content: this.instance.getValue(),
|
||||
type: options.prettierParser
|
||||
}).then(formattedCode => this.instance.setValue(formattedCode));
|
||||
}
|
||||
}
|
||||
);
|
||||
this.monacoEditorReadyDeferred.resolve();
|
||||
} else {
|
||||
this.instance = CodeMirror.fromTextArea(this.node, {
|
||||
mode: options.mode,
|
||||
value: this.lastSetValue || '',
|
||||
lineNumbers: true,
|
||||
lineWrapping: !!prefs.lineWrap,
|
||||
autofocus: options.autofocus || false,
|
||||
autoCloseBrackets: true,
|
||||
autoCloseTags: !!prefs.autoCloseTags,
|
||||
matchBrackets: true,
|
||||
matchTags: options.matchTags || false,
|
||||
tabMode: 'indent',
|
||||
keyMap: prefs.keyMap || 'sublime',
|
||||
theme: prefs.editorTheme || 'monokai',
|
||||
lint: !!options.lint,
|
||||
tabSize: +prefs.indentSize || 2,
|
||||
indentWithTabs: prefs.indentWith !== 'spaces',
|
||||
indentUnit: +prefs.indentSize,
|
||||
foldGutter: true,
|
||||
styleActiveLine: true,
|
||||
gutters: options.gutters || [],
|
||||
// cursorScrollMargin: '20', has issue with scrolling
|
||||
profile: options.profile || '',
|
||||
extraKeys: {
|
||||
Up: function(editor) {
|
||||
// Stop up/down keys default behavior when saveditempane is open
|
||||
// if (isSavedItemsPaneOpen) {
|
||||
// return;
|
||||
// }
|
||||
CodeMirror.commands.goLineUp(editor);
|
||||
},
|
||||
Down: function(editor) {
|
||||
// if (isSavedItemsPaneOpen) {
|
||||
// return;
|
||||
// }
|
||||
CodeMirror.commands.goLineDown(editor);
|
||||
},
|
||||
'Shift-Tab': function(editor) {
|
||||
CodeMirror.commands.indentAuto(editor);
|
||||
},
|
||||
'Shift-Ctrl-F': function(editor) {
|
||||
if (options.prettier) {
|
||||
prettify({
|
||||
content: editor.getValue(),
|
||||
type: options.prettierParser
|
||||
}).then(formattedCode => editor.setValue(formattedCode));
|
||||
}
|
||||
},
|
||||
Tab: function(editor) {
|
||||
if (options.emmet) {
|
||||
const didEmmetWork = editor.execCommand(
|
||||
'emmetExpandAbbreviation'
|
||||
);
|
||||
if (didEmmetWork === true) {
|
||||
return;
|
||||
}
|
||||
const input = $('[data-setting=indentWith]:checked');
|
||||
if (
|
||||
!editor.somethingSelected() &&
|
||||
(!prefs.indentWith || prefs.indentWith === 'spaces')
|
||||
) {
|
||||
// softtabs adds spaces. This is required because by default tab key will put tab, but we want
|
||||
// to indent with spaces if `spaces` is preferred mode of indentation.
|
||||
// `somethingSelected` needs to be checked otherwise, all selected code is replaced with softtab.
|
||||
CodeMirror.commands.insertSoftTab(editor);
|
||||
} else {
|
||||
CodeMirror.commands.defaultTab(editor);
|
||||
}
|
||||
}
|
||||
},
|
||||
Enter: 'emmetInsertLineBreak'
|
||||
}
|
||||
});
|
||||
this.instance.on('focus', editor => {
|
||||
if (typeof this.props.onFocus === 'function')
|
||||
this.props.onFocus(editor);
|
||||
});
|
||||
this.instance.on('change', this.props.onChange);
|
||||
this.instance.addKeyMap({
|
||||
'Ctrl-Space': 'autocomplete'
|
||||
});
|
||||
this.instance.on('inputRead', (editor, input) => {
|
||||
// Process further If this has autocompletition on and also the global
|
||||
// autocomplete setting is on.
|
||||
if (
|
||||
!this.props.options.noAutocomplete &&
|
||||
this.props.prefs.autoComplete
|
||||
) {
|
||||
if (
|
||||
input.origin !== '+input' ||
|
||||
input.text[0] === ';' ||
|
||||
input.text[0] === ',' ||
|
||||
input.text[0] === ' '
|
||||
) {
|
||||
return;
|
||||
}
|
||||
CodeMirror.commands.autocomplete(editor, null, {
|
||||
completeSingle: false
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// this.props.onCreation(this.instance);
|
||||
}
|
||||
|
||||
render() {
|
||||
const node =
|
||||
this.props.type === 'monaco' ? (
|
||||
<div ref={el => (this.node = el)} style="width:100%;height:100%;" />
|
||||
) : (
|
||||
<textarea ref={el => (this.node = el)} />
|
||||
);
|
||||
return node;
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
import { h, Component } from 'preact';
|
||||
import UserCodeMirror from './UserCodeMirror.jsx';
|
||||
import CodeEditor from './CodeEditor.jsx';
|
||||
import { computeHtml, computeCss, computeJs } from '../computes';
|
||||
import { modes, HtmlModes, CssModes, JsModes } from '../codeModes';
|
||||
import { log, writeFile, loadJS, getCompleteHtml } from '../utils';
|
||||
@ -13,7 +13,7 @@ import { PreviewDimension } from './PreviewDimension.jsx';
|
||||
const minCodeWrapSize = 33;
|
||||
|
||||
/* global htmlCodeEl
|
||||
*/
|
||||
*/
|
||||
|
||||
export default class ContentWrap extends Component {
|
||||
constructor(props) {
|
||||
@ -173,15 +173,7 @@ export default class ContentWrap extends Component {
|
||||
}
|
||||
|
||||
showErrors(lang, errors) {
|
||||
var editor = this.cm[lang];
|
||||
errors.forEach(function(e) {
|
||||
editor.operation(function() {
|
||||
var n = document.createElement('div');
|
||||
n.setAttribute('data-title', e.message);
|
||||
n.classList.add('gutter-error-marker');
|
||||
editor.setGutterMarker(e.lineNumber, 'error-gutter', n);
|
||||
});
|
||||
});
|
||||
this.cm[lang].showErrors(errors);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -488,35 +480,23 @@ export default class ContentWrap extends Component {
|
||||
updateHtmlMode(value) {
|
||||
this.props.onCodeModeChange('html', value);
|
||||
this.props.currentItem.htmlMode = value;
|
||||
this.cm.html.setOption('mode', modes[value].cmMode);
|
||||
CodeMirror.autoLoadMode(
|
||||
this.cm.html,
|
||||
modes[value].cmPath || modes[value].cmMode
|
||||
);
|
||||
this.cm.html.setLanguage(value);
|
||||
return this.handleModeRequirements(value);
|
||||
}
|
||||
updateCssMode(value) {
|
||||
this.props.onCodeModeChange('css', value);
|
||||
this.props.currentItem.cssMode = value;
|
||||
this.cm.css.setOption('mode', modes[value].cmMode);
|
||||
this.cm.css.setOption('readOnly', modes[value].cmDisable);
|
||||
window.cssSettingsBtn.classList[
|
||||
modes[value].hasSettings ? 'remove' : 'add'
|
||||
]('hide');
|
||||
CodeMirror.autoLoadMode(
|
||||
this.cm.css,
|
||||
modes[value].cmPath || modes[value].cmMode
|
||||
);
|
||||
this.cm.css.setLanguage(value);
|
||||
return this.handleModeRequirements(value);
|
||||
}
|
||||
updateJsMode(value) {
|
||||
this.props.onCodeModeChange('js', value);
|
||||
this.props.currentItem.jsMode = value;
|
||||
this.cm.js.setOption('mode', modes[value].cmMode);
|
||||
CodeMirror.autoLoadMode(
|
||||
this.cm.js,
|
||||
modes[value].cmPath || modes[value].cmMode
|
||||
);
|
||||
this.cm.js.setLanguage(value);
|
||||
return this.handleModeRequirements(value);
|
||||
}
|
||||
codeModeChangeHandler(e) {
|
||||
@ -708,7 +688,8 @@ export default class ContentWrap extends Component {
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<UserCodeMirror
|
||||
<CodeEditor
|
||||
type={this.props.prefs.isMonacoEditorOn ? 'monaco' : 'codemirror'}
|
||||
options={{
|
||||
mode: 'htmlmixed',
|
||||
profile: 'xhtml',
|
||||
@ -721,7 +702,7 @@ export default class ContentWrap extends Component {
|
||||
}}
|
||||
prefs={this.props.prefs}
|
||||
onChange={this.onHtmlCodeChange.bind(this)}
|
||||
onCreation={el => (this.cm.html = el)}
|
||||
ref={editor => (this.cm.html = editor)}
|
||||
onFocus={this.editorFocusHandler.bind(this)}
|
||||
/>
|
||||
</div>
|
||||
@ -775,7 +756,8 @@ export default class ContentWrap extends Component {
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<UserCodeMirror
|
||||
<CodeEditor
|
||||
type={this.props.prefs.isMonacoEditorOn ? 'monaco' : 'codemirror'}
|
||||
options={{
|
||||
mode: 'css',
|
||||
gutters: [
|
||||
@ -789,7 +771,7 @@ export default class ContentWrap extends Component {
|
||||
}}
|
||||
prefs={this.props.prefs}
|
||||
onChange={this.onCssCodeChange.bind(this)}
|
||||
onCreation={el => (this.cm.css = el)}
|
||||
ref={editor => (this.cm.css = editor)}
|
||||
onFocus={this.editorFocusHandler.bind(this)}
|
||||
/>
|
||||
</div>
|
||||
@ -830,7 +812,8 @@ export default class ContentWrap extends Component {
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<UserCodeMirror
|
||||
<CodeEditor
|
||||
type={this.props.prefs.isMonacoEditorOn ? 'monaco' : 'codemirror'}
|
||||
options={{
|
||||
mode: 'javascript',
|
||||
gutters: [
|
||||
@ -844,7 +827,7 @@ export default class ContentWrap extends Component {
|
||||
prefs={this.props.prefs}
|
||||
autoComplete={this.props.prefs.autoComplete}
|
||||
onChange={this.onJsCodeChange.bind(this)}
|
||||
onCreation={el => (this.cm.js = el)}
|
||||
ref={editor => (this.cm.js = editor)}
|
||||
onFocus={this.editorFocusHandler.bind(this)}
|
||||
/>
|
||||
{/* Inlet(scope.cm.js); */}
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { h, Component } from 'preact';
|
||||
import UserCodeMirror from './UserCodeMirror';
|
||||
import CodeEditor from './CodeEditor';
|
||||
import { modes, HtmlModes, CssModes, JsModes } from '../codeModes';
|
||||
import { log, loadJS } from '../utils';
|
||||
|
||||
@ -24,7 +24,7 @@ import { PreviewDimension } from './PreviewDimension';
|
||||
const minCodeWrapSize = 33;
|
||||
|
||||
/* global htmlCodeEl
|
||||
*/
|
||||
*/
|
||||
export default class ContentWrapFiles extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
@ -86,7 +86,7 @@ export default class ContentWrapFiles extends Component {
|
||||
this.state.selectedFile &&
|
||||
this.fileBuffers[this.state.selectedFile.path]
|
||||
) {
|
||||
this.fileBuffers[this.state.selectedFile.path].setValue(
|
||||
this.fileBuffers[this.state.selectedFile.path].model.setValue(
|
||||
getFileFromPath(
|
||||
nextProps.currentItem.files,
|
||||
this.state.selectedFile.path
|
||||
@ -168,12 +168,23 @@ export default class ContentWrapFiles extends Component {
|
||||
CodeMirror.autoLoadMode(this.cm, mode);
|
||||
}
|
||||
if (mime === 'application/json') {
|
||||
mime = 'application/ld+json';
|
||||
mime = this.props.prefs.isMonacoEditorOn ? 'json' : 'application/ld+json';
|
||||
}
|
||||
if (!this.props.prefs.isMonacoEditorOn) {
|
||||
this.fileBuffers[file.path] = {
|
||||
model: CodeMirror.Doc(
|
||||
file.content || '',
|
||||
detectedMode ? mime : 'text/plain'
|
||||
)
|
||||
};
|
||||
} else {
|
||||
this.fileBuffers[file.path] = {
|
||||
model: monaco.editor.createModel(
|
||||
file.content || '',
|
||||
mime || 'javascript'
|
||||
)
|
||||
};
|
||||
}
|
||||
this.fileBuffers[file.path] = CodeMirror.Doc(
|
||||
file.content || '',
|
||||
detectedMode ? mime : 'text/plain'
|
||||
);
|
||||
}
|
||||
|
||||
onHtmlCodeChange(editor, change) {
|
||||
@ -184,10 +195,10 @@ export default class ContentWrapFiles extends Component {
|
||||
this.cmCodes.html,
|
||||
change.origin !== 'setValue'
|
||||
);
|
||||
this.onCodeChange(editor, change);
|
||||
this.onCodeChange(change);
|
||||
}
|
||||
|
||||
onCodeChange(editor, change) {
|
||||
onCodeChange(change) {
|
||||
clearTimeout(this.updateTimer);
|
||||
|
||||
this.updateTimer = setTimeout(() => {
|
||||
@ -249,19 +260,11 @@ export default class ContentWrapFiles extends Component {
|
||||
}
|
||||
}
|
||||
cleanupErrors() {
|
||||
this.cm.clearGutter('error-gutter');
|
||||
this.editor.clearGutter('error-gutter');
|
||||
}
|
||||
|
||||
showErrors(lang, errors) {
|
||||
var editor = this.cm;
|
||||
errors.forEach(function(e) {
|
||||
editor.operation(function() {
|
||||
var n = document.createElement('div');
|
||||
n.setAttribute('data-title', e.message);
|
||||
n.classList.add('gutter-error-marker');
|
||||
editor.setGutterMarker(e.lineNumber, 'error-gutter', n);
|
||||
});
|
||||
});
|
||||
showErrors(errors) {
|
||||
this.editor.showErrors(errors);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -305,9 +308,11 @@ export default class ContentWrapFiles extends Component {
|
||||
}
|
||||
refreshEditor() {
|
||||
if (this.state.selectedFile) {
|
||||
this.cm.setValue(this.state.selectedFile.content);
|
||||
this.editor.setValue(this.state.selectedFile.content);
|
||||
}
|
||||
if (this.editor) {
|
||||
this.editor.refresh();
|
||||
}
|
||||
this.cm.refresh();
|
||||
window.cm = this.cm;
|
||||
|
||||
this.clearConsole();
|
||||
@ -498,25 +503,26 @@ export default class ContentWrapFiles extends Component {
|
||||
this.props.onFolderSelect(file);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.fileBuffers[file.path]) {
|
||||
this.createEditorDoc(file);
|
||||
}
|
||||
|
||||
const currentState = this.editor.saveViewState();
|
||||
if (currentState && this.state.selectedFile) {
|
||||
this.fileBuffers[this.state.selectedFile.path].state = currentState;
|
||||
}
|
||||
this.setState({
|
||||
editorOptions: this.getEditorOptions(file.name),
|
||||
selectedFile: file
|
||||
});
|
||||
if (!this.fileBuffers[file.path]) {
|
||||
this.createEditorDoc(file);
|
||||
}
|
||||
this.cm.swapDoc(this.fileBuffers[file.path]);
|
||||
|
||||
// var cmMode = 'html';
|
||||
// if (file.name.match(/\.css$/)) {
|
||||
// this.updateCssMode('css');
|
||||
// } else if (file.name.match(/\.js$/)) {
|
||||
// this.updateCssMode('js');
|
||||
// } else {
|
||||
// this.updateCssMode('html');
|
||||
// }
|
||||
// this.cm.setValue(file.content || '');
|
||||
this.cm.focus();
|
||||
this.editor.setModel(this.fileBuffers[file.path].model);
|
||||
if (this.fileBuffers[file.path].state) {
|
||||
this.editor.restoreViewState(this.fileBuffers[file.path].state);
|
||||
}
|
||||
|
||||
this.editor.focus();
|
||||
}
|
||||
|
||||
onMessageFromConsole() {
|
||||
@ -637,14 +643,15 @@ export default class ContentWrapFiles extends Component {
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<UserCodeMirror
|
||||
<CodeEditor
|
||||
type={this.props.prefs.isMonacoEditorOn ? 'monaco' : 'codemirror'}
|
||||
value={
|
||||
this.state.selectedFile ? this.state.selectedFile.content : ''
|
||||
}
|
||||
options={this.state.editorOptions}
|
||||
prefs={this.props.prefs}
|
||||
onChange={this.onHtmlCodeChange.bind(this)}
|
||||
onCreation={editor => (this.cm = editor)}
|
||||
ref={editor => (this.editor = editor)}
|
||||
onFocus={this.editorFocusHandler.bind(this)}
|
||||
/>
|
||||
</div>
|
||||
|
@ -11,6 +11,10 @@ function CheckboxSetting({ label, onChange, pref }) {
|
||||
</Switch>
|
||||
);
|
||||
}
|
||||
function HelpText({ children }) {
|
||||
return <p class="help-text">{children}</p>;
|
||||
}
|
||||
|
||||
export default class Settings extends Component {
|
||||
updateSetting(e, settingName) {
|
||||
const value =
|
||||
@ -34,47 +38,45 @@ export default class Settings extends Component {
|
||||
pref={prefs.preserveLastCode}
|
||||
onChange={e => this.updateSetting(e, 'preserveLastCode')}
|
||||
/>
|
||||
<p class="help-text">
|
||||
Loads the last open creation when app starts
|
||||
</p>
|
||||
<HelpText>Loads the last open creation when app starts</HelpText>
|
||||
<Divider />
|
||||
<CheckboxSetting
|
||||
label="Fast/light version"
|
||||
pref={prefs.lightVersion}
|
||||
onChange={e => this.updateSetting(e, 'lightVersion')}
|
||||
/>
|
||||
<p class="help-text">
|
||||
<HelpText>
|
||||
Switch to lighter version for better performance. Removes things
|
||||
like blur etc.
|
||||
</p>
|
||||
</HelpText>
|
||||
<Divider />
|
||||
<CheckboxSetting
|
||||
label="Auto-preview"
|
||||
pref={prefs.autoPreview}
|
||||
onChange={e => this.updateSetting(e, 'autoPreview')}
|
||||
/>
|
||||
<p class="help-text">
|
||||
<HelpText>
|
||||
Refreshes the preview as you code. Otherwise use the 'Run' button
|
||||
</p>
|
||||
</HelpText>
|
||||
<Divider />
|
||||
<CheckboxSetting
|
||||
label="Auto-save"
|
||||
pref={prefs.autoSave}
|
||||
onChange={e => this.updateSetting(e, 'autoSave')}
|
||||
/>
|
||||
<p class="help-text">
|
||||
<HelpText>
|
||||
Auto-save keeps saving your code at regular intervals after you
|
||||
hit save manually the first time
|
||||
</p>
|
||||
</HelpText>
|
||||
<Divider />
|
||||
<CheckboxSetting
|
||||
label="Refresh preview on resize"
|
||||
pref={prefs.refreshOnResize}
|
||||
onChange={e => this.updateSetting(e, 'refreshOnResize')}
|
||||
/>
|
||||
<p class="help-text">
|
||||
<HelpText>
|
||||
Preview will refresh when you resize the preview pane
|
||||
</p>
|
||||
</HelpText>
|
||||
<div class="show-when-extension">
|
||||
<Divider />
|
||||
<CheckboxSetting
|
||||
@ -83,10 +85,10 @@ export default class Settings extends Component {
|
||||
onChange={e => this.updateSetting(e, 'replaceNewTab')}
|
||||
showWhenExtension
|
||||
/>
|
||||
<p class="help-text">
|
||||
<HelpText>
|
||||
Turning this on will start showing Web Maker in every new tab
|
||||
you open
|
||||
</p>
|
||||
</HelpText>
|
||||
</div>
|
||||
<Divider />
|
||||
<CheckboxSetting
|
||||
@ -94,9 +96,9 @@ export default class Settings extends Component {
|
||||
pref={prefs.preserveConsoleLogs}
|
||||
onChange={e => this.updateSetting(e, 'preserveConsoleLogs')}
|
||||
/>
|
||||
<p class="help-text">
|
||||
<HelpText>
|
||||
Preserves the console logs across your preview refreshes
|
||||
</p>
|
||||
</HelpText>
|
||||
</TabPanel>
|
||||
<TabPanel label="Indentation">
|
||||
<div class="line">
|
||||
@ -151,6 +153,17 @@ export default class Settings extends Component {
|
||||
<TabPanel label="Editor">
|
||||
<div>
|
||||
<div>
|
||||
<CheckboxSetting
|
||||
title="Use experimental Monaco editor"
|
||||
label="Use Monaco Editor"
|
||||
pref={prefs.isMonacoEditorOn}
|
||||
onChange={e => this.updateSetting(e, 'isMonacoEditorOn')}
|
||||
/>
|
||||
<HelpText>
|
||||
(Experimental) Switches from CodeMirror to Monaco. Many other
|
||||
settings might not be available in Monaco.
|
||||
</HelpText>
|
||||
<Divider />
|
||||
<div class="line">
|
||||
<span>Default Preprocessors</span>
|
||||
<div class="flex">
|
||||
@ -308,21 +321,20 @@ export default class Settings extends Component {
|
||||
pref={prefs.isCodeBlastOn}
|
||||
onChange={e => this.updateSetting(e, 'isCodeBlastOn')}
|
||||
/>
|
||||
<p class="help-text">
|
||||
Enjoy wonderful particle blasts while you type
|
||||
</p>
|
||||
<HelpText>Enjoy wonderful particle blasts while you type</HelpText>
|
||||
<Divider />
|
||||
<CheckboxSetting
|
||||
label="Js13kGames Mode"
|
||||
pref={prefs.isJs13kModeOn}
|
||||
onChange={e => this.updateSetting(e, 'isJs13kModeOn')}
|
||||
/>
|
||||
<p class="help-text">
|
||||
<HelpText>
|
||||
Make the app ready to build some games for{' '}
|
||||
<a href="https://js13kgames.com/" target="_blank" rel="noopener">
|
||||
Js13kGames
|
||||
</a>.
|
||||
</p>
|
||||
</a>
|
||||
.
|
||||
</HelpText>
|
||||
</TabPanel>
|
||||
<TabPanel label="Advanced">
|
||||
<div>
|
||||
@ -338,11 +350,11 @@ export default class Settings extends Component {
|
||||
ms
|
||||
</div>
|
||||
</label>
|
||||
<p class="help-text">
|
||||
<HelpText>
|
||||
If any loop iteration takes more than the defined time, it is
|
||||
detected as a potential infinite loop and further iterations are
|
||||
stopped.
|
||||
</p>
|
||||
</HelpText>
|
||||
</div>
|
||||
<Divider />
|
||||
|
||||
|
@ -5,7 +5,11 @@ export class SplitPane extends Component {
|
||||
componentDidMount() {
|
||||
this.updateSplit();
|
||||
}
|
||||
|
||||
componentWillUpdate() {
|
||||
if (this.splitInstance) {
|
||||
this.splitInstance.destroy();
|
||||
}
|
||||
}
|
||||
componentDidUpdate(prevProps) {
|
||||
if (this.hasGutter() && !this.hasPropsChanged(prevProps, this.props)) {
|
||||
return;
|
||||
@ -33,13 +37,8 @@ export class SplitPane extends Component {
|
||||
const { children, ...options } = this.props;
|
||||
options.gutterSize = 6;
|
||||
|
||||
if (this.splitInstance && this.hasGutter()) {
|
||||
this.splitInstance.destroy();
|
||||
}
|
||||
|
||||
/* eslint-disable new-cap */
|
||||
this.splitInstance = Split([...this.parent.children], options);
|
||||
console.log('recreating split');
|
||||
|
||||
/* eslint-enable new-cap */
|
||||
|
||||
|
@ -1,176 +0,0 @@
|
||||
import { h, Component } from 'preact';
|
||||
import CodeMirror from '../CodeMirror';
|
||||
|
||||
import 'codemirror/addon/edit/matchbrackets.js';
|
||||
import 'codemirror/addon/edit/matchtags.js';
|
||||
import 'codemirror/addon/edit/closebrackets.js';
|
||||
import 'codemirror/addon/edit/closetag.js';
|
||||
import 'codemirror/addon/comment/comment.js';
|
||||
import 'codemirror/addon/fold/foldcode.js';
|
||||
import 'codemirror/addon/fold/foldgutter.js';
|
||||
import 'codemirror/addon/fold/xml-fold.js';
|
||||
import 'codemirror/addon/fold/indent-fold.js';
|
||||
import 'codemirror/addon/fold/comment-fold.js';
|
||||
import 'codemirror/addon/fold/brace-fold.js';
|
||||
import 'codemirror/addon/hint/show-hint.js';
|
||||
import 'codemirror/addon/hint/javascript-hint.js';
|
||||
import 'codemirror/addon/hint/xml-hint.js';
|
||||
import 'codemirror/addon/hint/html-hint.js';
|
||||
import 'codemirror/addon/hint/css-hint.js';
|
||||
import 'codemirror/addon/selection/active-line.js';
|
||||
import 'codemirror/addon/search/searchcursor.js';
|
||||
import 'codemirror/addon/search/search.js';
|
||||
import 'codemirror/addon/dialog/dialog.js';
|
||||
import 'codemirror/addon/search/jump-to-line.js';
|
||||
|
||||
import 'codemirror/mode/xml/xml.js';
|
||||
import 'codemirror/mode/css/css.js';
|
||||
import 'codemirror/mode/javascript/javascript.js';
|
||||
import 'codemirror/mode/htmlmixed/htmlmixed.js';
|
||||
import 'codemirror/keymap/sublime.js';
|
||||
import 'codemirror/keymap/vim.js';
|
||||
import 'code-blast-codemirror/code-blast.js';
|
||||
|
||||
import emmet from '@emmetio/codemirror-plugin';
|
||||
import { prettify } from '../utils';
|
||||
|
||||
emmet(CodeMirror);
|
||||
|
||||
export default class UserCodeMirror extends Component {
|
||||
componentDidMount() {
|
||||
this.initEditor();
|
||||
}
|
||||
shouldComponentUpdate(nextProps) {
|
||||
if (nextProps.prefs !== this.props.prefs) {
|
||||
const { prefs } = nextProps;
|
||||
|
||||
this.cm.setOption('indentWithTabs', prefs.indentWith !== 'spaces');
|
||||
this.cm.setOption(
|
||||
'blastCode',
|
||||
prefs.isCodeBlastOn ? { effect: 2, shake: false } : false
|
||||
);
|
||||
this.cm.setOption('theme', prefs.editorTheme);
|
||||
|
||||
this.cm.setOption('indentUnit', +prefs.indentSize);
|
||||
this.cm.setOption('tabSize', +prefs.indentSize);
|
||||
|
||||
this.cm.setOption('keyMap', prefs.keymap);
|
||||
this.cm.setOption('lineWrapping', prefs.lineWrap);
|
||||
this.cm.setOption('lineWrapping', prefs.autoCloseTags);
|
||||
|
||||
this.cm.refresh();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
initEditor() {
|
||||
const { options, prefs } = this.props;
|
||||
this.cm = CodeMirror.fromTextArea(this.textarea, {
|
||||
mode: options.mode,
|
||||
lineNumbers: true,
|
||||
lineWrapping: !!prefs.lineWrap,
|
||||
autofocus: options.autofocus || false,
|
||||
autoCloseBrackets: true,
|
||||
autoCloseTags: !!prefs.autoCloseTags,
|
||||
matchBrackets: true,
|
||||
matchTags: options.matchTags || false,
|
||||
tabMode: 'indent',
|
||||
keyMap: prefs.keyMap || 'sublime',
|
||||
theme: prefs.editorTheme || 'monokai',
|
||||
lint: !!options.lint,
|
||||
tabSize: +prefs.indentSize || 2,
|
||||
indentWithTabs: prefs.indentWith !== 'spaces',
|
||||
indentUnit: +prefs.indentSize,
|
||||
foldGutter: true,
|
||||
styleActiveLine: true,
|
||||
gutters: options.gutters || [],
|
||||
// cursorScrollMargin: '20', has issue with scrolling
|
||||
profile: options.profile || '',
|
||||
extraKeys: {
|
||||
Up: function(editor) {
|
||||
// Stop up/down keys default behavior when saveditempane is open
|
||||
// if (isSavedItemsPaneOpen) {
|
||||
// return;
|
||||
// }
|
||||
CodeMirror.commands.goLineUp(editor);
|
||||
},
|
||||
Down: function(editor) {
|
||||
// if (isSavedItemsPaneOpen) {
|
||||
// return;
|
||||
// }
|
||||
CodeMirror.commands.goLineDown(editor);
|
||||
},
|
||||
'Shift-Tab': function(editor) {
|
||||
CodeMirror.commands.indentAuto(editor);
|
||||
},
|
||||
'Shift-Ctrl-F': function(editor) {
|
||||
if (options.prettier) {
|
||||
prettify({
|
||||
content: editor.getValue(),
|
||||
type: options.prettierParser
|
||||
}).then(formattedCode => editor.setValue(formattedCode));
|
||||
}
|
||||
},
|
||||
Tab: function(editor) {
|
||||
if (options.emmet) {
|
||||
const didEmmetWork = editor.execCommand('emmetExpandAbbreviation');
|
||||
if (didEmmetWork === true) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
const input = $('[data-setting=indentWith]:checked');
|
||||
if (
|
||||
!editor.somethingSelected() &&
|
||||
(!prefs.indentWith || prefs.indentWith === 'spaces')
|
||||
) {
|
||||
// softtabs adds spaces. This is required because by default tab key will put tab, but we want
|
||||
// to indent with spaces if `spaces` is preferred mode of indentation.
|
||||
// `somethingSelected` needs to be checked otherwise, all selected code is replaced with softtab.
|
||||
CodeMirror.commands.insertSoftTab(editor);
|
||||
} else {
|
||||
CodeMirror.commands.defaultTab(editor);
|
||||
}
|
||||
},
|
||||
Enter: 'emmetInsertLineBreak'
|
||||
}
|
||||
});
|
||||
this.cm.on('focus', editor => {
|
||||
if (typeof this.props.onFocus === 'function') this.props.onFocus(editor);
|
||||
});
|
||||
this.cm.on('change', this.props.onChange);
|
||||
this.cm.addKeyMap({
|
||||
'Ctrl-Space': 'autocomplete'
|
||||
});
|
||||
this.cm.on('inputRead', (editor, input) => {
|
||||
// Process further If this has autocompletition on and also the global
|
||||
// autocomplete setting is on.
|
||||
if (!this.props.options.noAutocomplete && this.props.prefs.autoComplete) {
|
||||
if (
|
||||
input.origin !== '+input' ||
|
||||
input.text[0] === ';' ||
|
||||
input.text[0] === ',' ||
|
||||
input.text[0] === ' '
|
||||
) {
|
||||
return;
|
||||
}
|
||||
CodeMirror.commands.autocomplete(this.cm, null, {
|
||||
completeSingle: false
|
||||
});
|
||||
}
|
||||
});
|
||||
this.props.onCreation(this.cm);
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<textarea
|
||||
ref={el => (this.textarea = el)}
|
||||
name=""
|
||||
id=""
|
||||
cols="30"
|
||||
rows="10"
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
@ -133,7 +133,8 @@ export default class App extends Component {
|
||||
layoutMode: 2,
|
||||
isJs13kModeOn: false,
|
||||
autoCloseTags: true,
|
||||
lang: 'en'
|
||||
lang: 'en',
|
||||
isMonacoEditorOn: false
|
||||
};
|
||||
this.prefs = {};
|
||||
|
||||
@ -1527,20 +1528,6 @@ export default class App extends Component {
|
||||
|
||||
<Alerts />
|
||||
|
||||
<form
|
||||
style="display:none;"
|
||||
action="https://codepen.io/pen/define"
|
||||
method="POST"
|
||||
target="_blank"
|
||||
id="js-codepen-form"
|
||||
>
|
||||
<input
|
||||
type="hidden"
|
||||
name="data"
|
||||
value="{"title": "New Pen!", "html": "<div>Hello, World!</div>"}"
|
||||
/>
|
||||
</form>
|
||||
|
||||
<Modal
|
||||
show={this.state.isAddLibraryModalOpen}
|
||||
closeHandler={() => this.setState({ isAddLibraryModalOpen: false })}
|
||||
@ -1674,7 +1661,7 @@ export default class App extends Component {
|
||||
<input
|
||||
type="hidden"
|
||||
name="data"
|
||||
value="{"title": "New Pen!", "html": "<div>Hello, World!</div>"}"
|
||||
value='{"title": "New Pen!", "html": "<div>Hello, World!</div>"}'
|
||||
/>
|
||||
</form>
|
||||
</div>
|
||||
|
@ -55,9 +55,9 @@ import { log } from './utils';
|
||||
if (db) {
|
||||
return resolve(db);
|
||||
}
|
||||
const _firestore = firebase.firestore();
|
||||
_firestore.settings({ timestampsInSnapshots: true });
|
||||
return _firestore
|
||||
const firestoreInstance = firebase.firestore();
|
||||
firestoreInstance.settings({ timestampsInSnapshots: true });
|
||||
return firestoreInstance
|
||||
.enablePersistence({ experimentalTabSynchronization: true })
|
||||
.then(function() {
|
||||
// Initialize Cloud Firestore through firebase
|
||||
|
6
src/lib/monaco/monaco.bundle.js
Normal file
6
src/lib/monaco/monaco.bundle.js
Normal file
File diff suppressed because one or more lines are too long
3843
src/lib/monaco/monaco.css
Normal file
3843
src/lib/monaco/monaco.css
Normal file
File diff suppressed because one or more lines are too long
2
src/lib/monaco/workers/css.worker.bundle.js
Normal file
2
src/lib/monaco/workers/css.worker.bundle.js
Normal file
File diff suppressed because one or more lines are too long
2
src/lib/monaco/workers/editor.worker.bundle.js
Normal file
2
src/lib/monaco/workers/editor.worker.bundle.js
Normal file
File diff suppressed because one or more lines are too long
8
src/lib/monaco/workers/html.worker.bundle.js
Normal file
8
src/lib/monaco/workers/html.worker.bundle.js
Normal file
File diff suppressed because one or more lines are too long
2
src/lib/monaco/workers/json.worker.bundle.js
Normal file
2
src/lib/monaco/workers/json.worker.bundle.js
Normal file
File diff suppressed because one or more lines are too long
17
src/lib/monaco/workers/ts.worker.bundle.js
Normal file
17
src/lib/monaco/workers/ts.worker.bundle.js
Normal file
File diff suppressed because one or more lines are too long
@ -49,6 +49,11 @@ if (
|
||||
// It's the perfect time to display a "New content is available; please refresh."
|
||||
// message in the page's interface.
|
||||
console.log('New or updated content is available.');
|
||||
if (window.alertsService) {
|
||||
window.alertsService.add(
|
||||
'New version available. Please refresh the page.'
|
||||
);
|
||||
}
|
||||
} else {
|
||||
// At this point, everything has been precached.
|
||||
// It's the perfect time to display a "Content is cached for offline use." message.
|
||||
|
15
src/utils.js
15
src/utils.js
@ -305,6 +305,21 @@ export function loadJS(src) {
|
||||
return d.promise;
|
||||
}
|
||||
|
||||
export function loadCss({ url, id }) {
|
||||
var d = deferred();
|
||||
var style = window.document.createElement('link');
|
||||
style.setAttribute('href', url);
|
||||
style.setAttribute('rel', 'stylesheet');
|
||||
if (id) {
|
||||
style.setAttribute('id', id);
|
||||
}
|
||||
document.head.appendChild(style);
|
||||
style.onload = function() {
|
||||
d.resolve();
|
||||
};
|
||||
return d.promise;
|
||||
}
|
||||
|
||||
/* eslint-disable max-params */
|
||||
export function getCompleteHtml(html, css, js, item, isForExport) {
|
||||
/* eslint-enable max-params */
|
||||
|
Loading…
x
Reference in New Issue
Block a user