import * as $ from 'jquery';
import exampleOrigin from './examples/index';
import locale from '../common/locale';
import {
getNameByLanguage,
ALL_PAGE_LANGUAGES, DEFAULT_PAGE_LANGUAGE,
getPageLanguage, setPageLanguage, initPageLanguage, changePageLanguage,
generateHashtag, getFolderAndItem,
} from '../common/utils';
import './index.scss';
import Vue from 'vue';
import ViserVue from 'viser-vue'
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
// store Vue Instance globally;
let vm;
Vue.use(ViserVue);
// store Ng Instance globally;
let ngRef;
const navTpl = require('./nav.tpl');
const ALL_FRAMEWORKS = ['react', 'vue', 'angular'];
const DEFAULT_FOLDER = 'line';
const DEFAULT_ITEM = 'basic-line';
class Demo {
framework: string = 'react';
editor: any;
constructor() {
initPageLanguage();
this.initEditor();
this.render();
this.bindEvent();
}
initEditor() {
this.editor = (window as any).monaco.editor.create(document.getElementById('monaco-editor'), {
value: '',
language: 'javascript',
lineNumbers: false,
scrollBeyondLastLine: false,
automaticLayout: true,
renderLineHighlight: 'none',
readOnly: true,
theme: 'vs',
minimap: {
enabled: false,
}
});
}
getCode() {
const { folder, item } = this.getDemoFolderAndItem();
const examples = exampleOrigin[folder].examples;
const filterExamples = examples.filter((ex) => {
const itemKey = this.getDemoItemKey(ex);
if (item === itemKey) {
return true;
}
return false;
})
if (!filterExamples || !filterExamples.length) {
return {};
}
const { path, cnName, enName } = filterExamples[0];
let reactCode = '';
let vueCode = '';
let angularCode = '';
let reactPath = '';
let vuePath = '';
let angularPath = '';
try {
reactCode = require(`!!raw-loader!./examples/${folder}/${path}/react.tsx`);
vueCode = require(`!!raw-loader!./examples/${folder}/${path}/vue.vue`);
angularCode = require(`!!raw-loader!./examples/${folder}/${path}/angular.ts`);
reactPath = `./examples/${folder}/${path}/react.tsx`;
vuePath = `./examples/${folder}/${path}/vue.vue`;
angularPath = `./examples/${folder}/${path}/angular.ts`;
} catch(err) {
console.error(err);
}
return {
reactCode, vueCode, angularCode,
reactPath, vuePath, angularPath,
cnName, enName,
};
}
getDemoFolderAndItem() {
const { folder, item } = getFolderAndItem();
return {
folder: folder || DEFAULT_FOLDER,
item: item || DEFAULT_ITEM,
};
}
getDemoItemKey(example) {
return example.enName.toLowerCase().replace(/\s/g, '-');
}
runCode(framework) {
const code = this.getCode();
const mount = document.getElementById('mount');
// Unmount React;
ReactDOM.unmountComponentAtNode(mount);
// Unmount Vue
if (vm && vm.existed) {
vm.existed = false;
}
// Unmount Angular
if (ngRef) {
const mountParent = mount.parentNode;
ngRef.destroy();
ngRef = undefined;
const newMount = document.createElement('div');
newMount.setAttribute('id', 'mount');
mountParent.appendChild(newMount);
}
// Remove Dom
mount.innerHTML = '';
const codePath = code[`${framework}Path`];
if (framework === 'react') {
delete require.cache[require.resolve(`${codePath}`)];
const App = require(`${codePath}`).default;
ReactDOM.render(, document.getElementById('mount'));
}
if (framework === 'angular') {
delete require.cache[require.resolve(`${codePath}`)];
const AppModule = require(`${codePath}`).default;
platformBrowserDynamic().bootstrapModule(AppModule).then((ref) => { ngRef = ref; });
}
if (framework === 'vue') {
const VueApp = require(`${codePath}`).default;
const container = document.createElement('div');
document.getElementById('mount').appendChild(container);
vm = new Vue({
data: {
existed: true
},
el: container,
template: '',
components: { VueApp }
});
}
}
renderCase() {
const self = this;
// change top framework switch
$('.case-box .case-code-switch-item').each(function () {
$(this).removeClass('active');
if (self.framework === $(this).attr('data-framework')) {
$(this).addClass('active');
}
});
this.runCode(self.framework);
}
renderCodeEditor() {
const code = this.getCode();
const codeValue = code[`${this.framework}Code`];
const language = this.framework === 'vue' ? 'html' : 'typescript';
this.editor.setValue(codeValue);
(window as any).monaco.editor.setModelLanguage(this.editor.getModel(), language);
}
renderLanguage() {
const language = getPageLanguage();
$('.common-header .page-language-switch')
.removeClass('en').removeClass('cn')
.addClass(language);
if (locale && locale[language] && locale[language].length) {
locale[language].forEach((o) => {
$(o.selector).html(o.text);
});
}
}
renderDemoTitle() {
const code = this.getCode();
$('.case-type').html(getNameByLanguage(code));
}
renderLeftMenu() {
const { folder, item } = this.getDemoFolderAndItem();
const menuList = [];
Object.keys(exampleOrigin).forEach((key) => {
const folderKey = key;
const folderMatched = folderKey === folder;
menuList.push({
...exampleOrigin[key],
folderKey,
folderDisplayName: getNameByLanguage(exampleOrigin[key]),
examples: exampleOrigin[key].examples.map((example) => {
const itemKey = this.getDemoItemKey(example);
const itemMatched = itemKey === item;
return {
...example,
linkName: generateHashtag(folderKey, itemKey),
itemKey,
itemDisplayName: getNameByLanguage(example),
activeClass: folderMatched && itemMatched ? 'active' : '',
};
}),
expanded: folderMatched ? 'expanded' : '',
});
});
$('.left-panel').html(navTpl({ menuList }));
}
bindEvent() {
const self = this;
// TODO: bind JSFiddle event
// $('.case-box .op .run').on('click', function() {
// const index = $(this).attr('data-index');
// });
$('.left-panel').on('click', '.common-nav-item', function () {
setTimeout(() => {
self.refresh();
}, 0);
});
// bind code-switch event
$('.case-box .case-code-switch .case-code-switch-item').on('click', function () {
const framework = $(this).attr('data-framework');
self.framework = framework;
self.renderCodeEditor();
self.renderCase();
});
// bind framework switch event
$('.left-panel .common-nav-folder.expandable .common-nav-title').on('click', function () {
if ($(this).parent().hasClass('expanded')) {
$('.left-panel .common-nav-folder.expandable').each(function () {
$(this).removeClass('expanded');
});
} else {
$('.left-panel .common-nav-folder.expandable').each(function () {
$(this).removeClass('expanded');
});
$(this).parent().addClass('expanded');
}
});
// bind page language switch event
$('.page-language-switch').on('click', function () {
changePageLanguage();
self.refresh();
});
}
unbindEvent() {
$('.left-panel').off('click', '.common-nav-item');
$('.case-box .case-code-switch .case-code-switch-item').off('click');
$('.left-panel .common-nav-folder.expandable .common-nav-title').off('click');
$('.page-language-switch').off('click');
}
render() {
this.renderLeftMenu();
this.renderLanguage();
this.renderDemoTitle();
this.renderCodeEditor();
this.renderCase();
}
refresh() {
this.unbindEvent();
this.render();
this.bindEvent();
}
}
// load monaco editor
const load = require('load-script');
const loadEditor = () => {
const self = this;
return new Promise((resolve, reject) => {
load('/lib/monaco-editor/min/vs/loader.js', (err) => {
if (!err) {
window['require'].config({
paths: { vs: '/lib/monaco-editor/min/vs' }
});
window['require'](['vs/editor/editor.main'], function () {
resolve(this);
});
} else {
reject(err);
}
});
});
};
loadEditor().then(
monaco => {
new Demo();
},
err => {
console.error(err);
}
)