diff --git a/README.md b/README.md index fc0d35bc..66023efd 100644 --- a/README.md +++ b/README.md @@ -209,11 +209,6 @@ Create a Monarch tokenizer [here](https://microsoft.github.io/monaco-editor/mona * run `$/src/monaco-editor> npm run release` * open http://localhost:8080/monaco-editor/website/ -### Generating the playground samples - -* edit `$/src/monaco-editor/website/playground/playground.mdoc` -* run `$/src/monaco-editor> gulp playground-samples` - ### Publishing the website * run `$/src/monaco-editor> npm run website` diff --git a/gulpfile.js b/gulpfile.js index a314f968..83949c81 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -8,8 +8,7 @@ var rimraf = require('rimraf'); var cp = require('child_process'); var httpServer = require('http-server'); -var SAMPLES_MDOC_PATH = path.join(__dirname, 'website/playground/playground.mdoc'); -var WEBSITE_GENERATED_PATH = path.join(__dirname, 'website/playground/samples'); +var WEBSITE_GENERATED_PATH = path.join(__dirname, 'website/playground/new-samples'); var MONACO_EDITOR_VERSION = (function() { var packageJsonPath = path.join(__dirname, 'package.json'); var packageJson = JSON.parse(fs.readFileSync(packageJsonPath).toString()); @@ -206,144 +205,8 @@ function addPluginThirdPartyNotices() { // --- website -gulp.task('clean-playground-samples', function(cb) { rimraf(WEBSITE_GENERATED_PATH, { maxBusyTries: 1 }, cb); }); -gulp.task('playground-samples', ['clean-playground-samples'], function() { - function toFolderName(name) { - var result = name.toLowerCase().replace(/[^a-z0-9\-_]/g, '-'); - - while (result.indexOf('--') >= 0) { - result = result.replace(/--/, '-'); - } - - while (result.charAt(result.length - 1) === '-') { - result = result.substring(result, result.length - 1); - } - - return result; - } - - function parse(txt) { - function startsWith(haystack, needle) { - return haystack.substring(0, needle.length) === needle; - } - - var CHAPTER_MARKER = "="; - var SAMPLE_MARKER = "=="; - var SNIPPET_MARKER = "======================="; - - var lines = txt.split(/\r\n|\n|\r/); - var result = []; - var currentChapter = null; - var currentSample = null; - var currentSnippet = null; - - for (var i = 0; i < lines.length; i++) { - var line = lines[i]; - - if (startsWith(line, SNIPPET_MARKER)) { - var snippetType = line.substring(SNIPPET_MARKER.length).trim(); - - if (snippetType === 'HTML' || snippetType === 'JS' || snippetType === 'CSS') { - currentSnippet = currentSample[snippetType]; - } else { - currentSnippet = null; - } - continue; - } - - if (startsWith(line, SAMPLE_MARKER)) { - currentSnippet = null; - currentSample = { - name: line.substring(SAMPLE_MARKER.length).trim(), - JS: [], - HTML: [], - CSS: [] - }; - currentChapter.samples.push(currentSample); - continue; - } - - if (startsWith(line, CHAPTER_MARKER)) { - currentSnippet = null; - currentSample = null; - currentChapter = { - name: line.substring(CHAPTER_MARKER.length).trim(), - samples: [] - }; - result.push(currentChapter); - continue; - } - - if (currentSnippet) { - currentSnippet.push(line); - continue; - } - - if (line === '') { - continue; - } - - // ignore inter-sample content - console.warn('IGNORING INTER-SAMPLE CONTENT: ' + line); - } - - return result; - } - - var chapters = parse(fs.readFileSync(SAMPLES_MDOC_PATH).toString()); - - var allSamples = []; - - fs.mkdirSync(WEBSITE_GENERATED_PATH); - - chapters.forEach(function(chapter) { - var chapterFolderName = toFolderName(chapter.name); - - chapter.samples.forEach(function(sample) { - var sampleId = toFolderName(chapter.name + '-' + sample.name); - - sample.sampleId = sampleId; - - var js = [ - '//---------------------------------------------------', - '// ' + chapter.name + ' > ' + sample.name, - '//---------------------------------------------------', - '', - ].concat(sample.JS) - var sampleOut = { - id: sampleId, - js: js.join('\n'), - html: sample.HTML.join('\n'), - css: sample.CSS.join('\n') - }; - - allSamples.push({ - chapter: chapter.name, - name: sample.name, - sampleId: sampleId - }); - - var content = -`// This is a generated file. Please do not edit directly. -var SAMPLES = this.SAMPLES || []; -SAMPLES.push(${JSON.stringify(sampleOut)}); -` - - fs.writeFileSync(path.join(WEBSITE_GENERATED_PATH, sampleId + '.js'), content); - }); - }); - - var content = -`// This is a generated file. Please do not edit directly. -this.SAMPLES = []; -this.ALL_SAMPLES = ${JSON.stringify(allSamples)};` - - fs.writeFileSync(path.join(WEBSITE_GENERATED_PATH, 'all.js'), content); - -}); - gulp.task('clean-website', function(cb) { rimraf('../monaco-editor-website', { maxBusyTries: 1 }, cb); }); -gulp.task('website', ['clean-website', 'playground-samples'], function() { +gulp.task('website', ['clean-website'], function() { return ( gulp.src('website/**/*', { dot: true }) @@ -408,6 +271,87 @@ gulp.task('generate-test-samples', function() { var prefix = '//This is a generated file via gulp generate-test-samples\ndefine([], function() { return'; var suffix = '; });' fs.writeFileSync(path.join(__dirname, 'test/samples-all.js'), prefix + JSON.stringify(samples, null, '\t') + suffix ); + + var PLAY_SAMPLES = require(path.join(WEBSITE_GENERATED_PATH, 'all.js')).PLAY_SAMPLES; + var locations = []; + for (var i = 0; i < PLAY_SAMPLES.length; i++) { + var sample = PLAY_SAMPLES[i]; + var sampleId = sample.id; + var samplePath = path.join(WEBSITE_GENERATED_PATH, sample.path); + + var html = fs.readFileSync(path.join(samplePath, 'sample.html')); + var js = fs.readFileSync(path.join(samplePath, 'sample.js')); + var css = fs.readFileSync(path.join(samplePath, 'sample.css')); + + var result = [ + '', + '', + '', + '
', + '
-/* Some example CSS */
-
-@import url("something.css");
-
-body {
- margin: 0;
- padding: 3em 6em;
- font-family: tahoma, arial, sans-serif;
- color: #000;
-}
-
-#navigation a {
- font-weight: bold;
- text-decoration: none !important;
-}
-
-h1 {
- font-size: 2.5em;
-}
-
-h2 {
- font-size: 1.7em;
-}
-
-h1:before, h2:before {
- content: "some contents";
-}
-
-code {
- font-family: courier, monospace;
- font-size: 80%;
- color: #418A8A;
-}
-
-
-=======================CSS
-
-
-=======================END
-
-
-
-
-
-
-
-
-= Interacting with the editor
-
-== Adding a command to an editor instance
-
-=======================JS
-var jsCode = [
- '"use strict";',
- 'function Person(age) {',
- ' if (age) {',
- ' this.age = age;',
- ' }',
- '}',
- 'Person.prototype.getAge = function () {',
- ' return this.age;',
- '};'
-].join('\n');
-
-var editor = monaco.editor.create(document.getElementById("container"), {
- value: jsCode,
- language: "javascript"
-});
-
-var myCondition1 = editor.createContextKey(/*key name*/'myCondition1', /*default value*/false);
-var myCondition2 = editor.createContextKey(/*key name*/'myCondition2', /*default value*/false);
-
-editor.addCommand(monaco.KeyCode.Tab, function() {
- // services available in `ctx`
- alert('my command is executing!');
-
-}, 'myCondition1 && myCondition2')
-
-myCondition1.set(true);
-
-setTimeout(function() {
- alert('now enabling also myCondition2, try pressing Tab!');
- myCondition2.set(true);
- // you can use myCondition2.reset() to go back to the default
-}, 2000);
-=======================HTML
-
-
-=======================END
-
-== Adding an action to an editor instance
-
-=======================JS
-var editor = monaco.editor.create(document.getElementById("container"), {
- value: [
- '',
- 'class Example {',
- '\tprivate m:number;',
- '',
- '\tpublic met(): string {',
- '\t\treturn "Hello world!";',
- '\t}',
- '}'
- ].join('\n'),
- language: "typescript"
-});
-
-// Explanation:
-// Try right clicking on an identifier or keyword => the action will be enabled (due to `tokensAtPosition`)
-// Try right clicking on a string => the action will be disabled (due to `tokensAtPosition`)
-// Try right clicking on whitespace => the action will be disabled (due to `wordAtPosition`)
-// Press F1 (Alt-F1 in IE) => the action will appear and run if it is enabled
-// Press Ctrl-F10 => the action will run if it is enabled
-
-editor.addAction({
- // An unique identifier of the contributed action.
- id: 'my-unique-id',
-
- // A label of the action that will be presented to the user.
- label: 'My Label!!!',
-
- // An optional array of keybindings for the action.
- keybindings: [monaco.KeyMod.CtrlCmd | monaco.KeyCode.F10],
-
- keybindingContext: null,
-
- // Control if the action should show up in the context menu and where.
- // Built-in groups:
- // 1_goto/* => e.g. 1_goto/1_peekDefinition
- // 2_change/* => e.g. 2_change/2_format
- // 3_edit/* => e.g. 3_edit/1_copy
- // 4_tools/* => e.g. 4_tools/1_commands
- // You can also create your own group.
- // Defaults to null (don't show in context menu).
- contextMenuGroupId: '2_change/2_bla',
-
- // Method that will be executed when the action is triggered.
- // @param editor The editor instance is passed in as a convinience
- run: function(ed) {
- alert("i'm running => " + ed.getPosition());
- return null;
- },
-
- // Optional enablement conditions. All members are optional
- enablement: {
- // The action is enabled only if text in the editor is focused (e.g. blinking cursor).
- // Warning: This condition will be disabled if the action is marked to be displayed in the context menu
- // Defaults to false.
- textFocus: true,
-
- // The action is enabled only if the editor or its widgets have focus (e.g. focus is in find widget).
- // Defaults to false.
- //widgetFocus: true,
-
- // The action is enabled only if the editor is not in read only mode.
- // Defaults to false.
- //writeableEditor: true,
-
- // The action is enabled only if the cursor position is over a word (i.e. not whitespace).
- // Defaults to false.
- wordAtPosition: true,
-
- // The action is enabled only if the cursor position is over tokens of a certain kind.
- // Defaults to no tokens required.
- tokensAtPosition: ['identifier', '', 'keyword'],
- }
-});
-
-=======================HTML
-
-
-=======================END
-
-
-
-
-== Revealing a position
-
-=======================JS
-var jsCodeArr = [
- '// ------------------------------',
- '// ------------------------------',
- 'function Person(age) {',
- ' if (age) {',
- ' this.age = age;',
- ' }',
- '}',
- 'Person.prototype.getAge = function () {',
- ' return this.age;',
- '};',
- '',
- ''
-];
-
-jsCodeArr = jsCodeArr.concat(jsCodeArr.slice(0));
-jsCodeArr = jsCodeArr.concat(jsCodeArr.slice(0));
-jsCodeArr = jsCodeArr.concat(jsCodeArr.slice(0));
-
-jsCodeArr[49] += 'And this is some long line. And this is some long line. And this is some long line. And this is some long line. And this is some long line. ';
-
-var editor = monaco.editor.create(document.getElementById("container"), {
- value: jsCodeArr.join('\n'),
- language: "javascript"
-});
-
-editor.revealPositionInCenter({ lineNumber: 50, column: 120 });
-// Also see:
-// - editor.revealLine
-// - editor.revealLineInCenter
-// - editor.revealLineInCenterIfOutsideViewport
-// - editor.revealLines
-// - editor.revealLinesInCenter
-// - editor.revealLinesInCenterIfOutsideViewport
-// - editor.revealPosition
-// - editor.revealPositionInCenter
-// - editor.revealPositionInCenterIfOutsideViewport
-// - editor.revealRange
-// - editor.revealRangeInCenter
-// - editor.revealRangeInCenterIfOutsideViewport
-
-=======================HTML
-
-
-=======================END
-
-
-
-
-== Rendering glyphs in the margin
-
-=======================JS
-var jsCode = [
- '"use strict";',
- 'function Person(age) {',
- ' if (age) {',
- ' this.age = age;',
- ' }',
- '}',
- 'Person.prototype.getAge = function () {',
- ' return this.age;',
- '};'
-].join('\n');
-
-var editor = monaco.editor.create(document.getElementById("container"), {
- value: jsCode,
- language: "javascript",
- glyphMargin: true
-});
-
-var decorations = editor.deltaDecorations([], [
- {
- range: new monaco.Range(3,1,3,1),
- options: {
- isWholeLine: true,
- className: 'myContentClass',
- glyphMarginClassName: 'myGlyphMarginClass'
- }
- }
-]);
-
-// You can now use `decorations` to change or remove the decoration
-
-=======================HTML
-
-
-=======================CSS
-.myGlyphMarginClass {
- background: red;
-}
-.myContentClass {
- background: lightblue;
-}
-
-=======================END
-
-
-
-
-== Line and Inline decorations
-
-=======================JS
-var jsCode = [
- '"use strict";',
- 'function Person(age) {',
- ' if (age) {',
- ' this.age = age;',
- ' }',
- '}',
- 'Person.prototype.getAge = function () {',
- ' return this.age;',
- '};'
-].join('\n');
-
-var editor = monaco.editor.create(document.getElementById("container"), {
- value: jsCode,
- language: "javascript"
-});
-
-var decorations = editor.deltaDecorations([], [
- { range: new monaco.Range(3,1,5,1), options: { isWholeLine: true, linesDecorationsClassName: 'myLineDecoration' }},
- { range: new monaco.Range(7,1,7,24), options: { inlineClassName: 'myInlineDecoration' }},
-]);
-
-=======================HTML
-
-
-=======================CSS
-.myInlineDecoration {
- color: red !important;
- cursor: pointer;
- text-decoration: underline;
- font-weight: bold;
- font-style: oblique;
-}
-.myLineDecoration {
- background: lightblue;
- width: 5px !important;
- left: 3px;
-}
-
-=======================END
-
-
-
-
-== Customizing the line numbers
-
-=======================JS
-function lineNumbersFunc(originalLineNumber) {
- var map = [ 'O', 'I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII', 'IX', 'X'];
- if (originalLineNumber < map.length) {
- return map[originalLineNumber];
- }
- return originalLineNumber;
-}
-
-var jsCode = [
- '"use strict";',
- 'function Person(age) {',
- ' if (age) {',
- ' this.age = age;',
- ' }',
- '}',
- 'Person.prototype.getAge = function () {',
- ' return this.age;',
- '};'
-].join('\n');
-
-var editor = monaco.editor.create(document.getElementById("container"), {
- value: jsCode,
- language: "javascript",
- lineNumbers: lineNumbersFunc
-});
-
-=======================HTML
-
-
-=======================CSS
-
-
-=======================END
-
-
-
-
-== Listening to mouse events
-
-=======================JS
-var jsCode = [
- '"use strict";',
- 'function Person(age) {',
- ' if (age) {',
- ' this.age = age;',
- ' }',
- '}',
- 'Person.prototype.getAge = function () {',
- ' return this.age;',
- '};'
-].join('\n');
-
-var editor = monaco.editor.create(document.getElementById("container"), {
- value: jsCode,
- language: "javascript",
- glyphMargin: true,
- nativeContextMenu: false
-});
-
-var decorations = editor.deltaDecorations([], [
- {
- range: new monaco.Range(3,1,3,1),
- options: {
- isWholeLine: true,
- className: 'myContentClass',
- glyphMarginClassName: 'myGlyphMarginClass'
- }
- }
-]);
-
-// Add a zone to make hit testing more interesting
-var viewZoneId = null;
-editor.changeViewZones(function(changeAccessor) {
- var domNode = document.createElement('div');
- domNode.style.background = 'lightgreen';
- viewZoneId = changeAccessor.addZone({
- afterLineNumber: 3,
- heightInLines: 3,
- domNode: domNode
- });
-});
-
-// Add a content widget (scrolls inline with text)
-var contentWidget = {
- domNode: null,
- getId: function() {
- return 'my.content.widget';
- },
- getDomNode: function() {
- if (!this.domNode) {
- this.domNode = document.createElement('div');
- this.domNode.innerHTML = 'My content widget';
- this.domNode.style.background = 'grey';
- }
- return this.domNode;
- },
- getPosition: function() {
- return {
- position: {
- lineNumber: 7,
- column: 8
- },
- preference: [monaco.editor.ContentWidgetPositionPreference.ABOVE, monaco.editor.ContentWidgetPositionPreference.BELOW]
- };
- }
-};
-editor.addContentWidget(contentWidget);
-
-// Add an overlay widget
-var overlayWidget = {
- domNode: null,
- getId: function() {
- return 'my.overlay.widget';
- },
- getDomNode: function() {
- if (!this.domNode) {
- this.domNode = document.createElement('div');
- this.domNode.innerHTML = 'My overlay widget';
- this.domNode.style.background = 'grey';
- this.domNode.style.right = '30px';
- this.domNode.style.top = '50px';
- }
- return this.domNode;
- },
- getPosition: function() {
- return null;
- }
-};
-editor.addOverlayWidget(overlayWidget);
-
-var output = document.getElementById('output');
-function showEvent(str) {
- while(output.childNodes.length > 6) {
- output.removeChild(output.firstChild.nextSibling.nextSibling);
- }
- output.appendChild(document.createTextNode(str));
- output.appendChild(document.createElement('br'));
-}
-
-
-
-editor.onMouseMove(function (e) {
- showEvent('mousemove - ' + e.target.toString());
-});
-editor.onMouseDown(function (e) {
- showEvent('mousedown - ' + e.target.toString());
-});
-editor.onContextMenu(function (e) {
- showEvent('contextmenu - ' + e.target.toString());
-});
-editor.onMouseLeave(function (e) {
- showEvent('mouseleave');
-});
-
-=======================HTML
-