Skip to content

Commit ea0beb1

Browse files
committed
setup
1 parent 2114b9a commit ea0beb1

17 files changed

+5529
-0
lines changed

editor/.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
node_modules/
2+
dist/
3+
.DS_Store
4+
.vscode

editor/client/app.scss

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
2+
3+
html, body {
4+
width: 100%; height: 100%; padding: 0; margin: 0;
5+
}
6+
7+
* {
8+
box-sizing: border-box;
9+
}
10+
11+
#app {
12+
width: 100%; height: 100%; padding: 0; margin: 0;
13+
background-color: rgba(65, 132, 244, 0.05);
14+
background-color: #E7EBED;
15+
background-color: #F1F2F4;
16+
}

editor/client/app.tsx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import * as React from 'react';
2+
import * as ReactDOM from 'react-dom';
3+
import Editor from './editor';
4+
import './app.scss'
5+
6+
ReactDOM.render(
7+
<Editor />,
8+
document.getElementById('app') as HTMLElement
9+
);

editor/client/convertor.ts

Lines changed: 207 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,207 @@
1+
2+
import MarkdownIt from 'markdown-it'
3+
import Renderer from 'markdown-it/lib/renderer'
4+
import Token from 'markdown-it/lib/token'
5+
import _ from 'underscore'
6+
import htmlTemplate from './template.html'
7+
8+
let stateObj: any = {}
9+
let templatesObj: any = {}
10+
let allVariables: any = []
11+
let codeBlocks: any = []
12+
13+
const generateInputHTML = (data: any) => {
14+
let htmlInput = ``
15+
16+
if (data.type !== 'button') {
17+
stateObj[data.variableName] = data.defaultValue
18+
allVariables.push(data.variableName)
19+
}
20+
21+
const onChangeText = `updateState(this); ${data.onChange + ';'}`
22+
23+
if (data.type === 'text') {
24+
htmlInput = `<input id="rd-${data.variableName}" class="rd-text-input rd-input" type="text" oninput="${onChangeText}" value="${data.defaultValue}" />`
25+
} else if (data.type === 'multiline-text') {
26+
htmlInput = `<textarea id="rd-${data.variableName}" class="rd-ml-text-input rd-input" type="text" oninput="${onChangeText}">${data.defaultValue}</textarea>`
27+
} else if (data.type === 'number') {
28+
htmlInput = `<input id="rd-${data.variableName}" class="rd-text-input rd-input" type="number" oninput="${onChangeText}" value="${data.defaultValue}" />`
29+
} else if (data.type === 'password') {
30+
htmlInput = `<input id="rd-${data.variableName}" class="rd-text-input rd-input" type="password" oninput="${onChangeText}" />`
31+
} else if (data.type === 'list') {
32+
htmlInput = `<select id="rd-${data.variableName}" class="rd-text-input rd-input" onchange="${onChangeText}" value="${data.defaultValue}" >
33+
${data.values.map((v: any) => '<option value="'+v+'" '+(data.defaultValue === v ? 'selected' : '')+'>'+v+'</option>').join('\n')}
34+
</select>`
35+
} else if (data.type === 'color') {
36+
htmlInput = `<input id="rd-${data.variableName}" class="rd-color-input rd-input" type="color" oninput="${onChangeText}" value="${data.defaultValue}" />`
37+
} else if (data.type === 'date') {
38+
htmlInput = `<input id="rd-${data.variableName}" class="rd-text-input rd-input" type="date" oninput="${onChangeText}" value="${data.defaultValue}" />`
39+
} else if (data.type === 'button') {
40+
htmlInput = `<button id="rd-${data.variableName}" class="rd-button rd-input" onclick="${data.trigger}">${data.label}</button>`
41+
}
42+
43+
let html = `
44+
<div class="rd-input-block">
45+
<div class="rd-input-block-label">
46+
${data.label}
47+
</div>
48+
<div class="rd-input-block-row">
49+
${htmlInput}
50+
<button class="copy-button" onclick="copyInput('rd-${data.variableName}')">
51+
<svg width="16px" height="16px" version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 100.56 122.88" style="enable-background:new 0 0 100.56 122.88" xml:space="preserve"><g><path d="M72.15,112.2L90.4,93H72.15V112.2L72.15,112.2z M81.75,9.2c0,1.69-1.37,3.05-3.05,3.05c-1.69,0-3.05-1.37-3.05-3.05V6.11 H6.11v92.24h3.01c1.69,0,3.05,1.37,3.05,3.05c0,1.69-1.37,3.05-3.05,3.05H5.48c-1.51,0-2.88-0.61-3.87-1.61l0.01-0.01 c-1-1-1.61-2.37-1.61-3.87V5.48C0,3.97,0.61,2.6,1.61,1.61C2.6,0.61,3.97,0,5.48,0h70.79c1.5,0,2.87,0.62,3.86,1.61l0,0l0.01,0.01 c0.99,0.99,1.61,2.36,1.61,3.86V9.2L81.75,9.2z M100.56,90.55c0,1.4-0.94,2.58-2.22,2.94l-26.88,28.27 c-0.56,0.68-1.41,1.11-2.36,1.11c-0.06,0-0.12,0-0.19-0.01c-0.06,0-0.12,0.01-0.18,0.01H24.29c-1.51,0-2.88-0.61-3.87-1.61 l0.01-0.01l-0.01-0.01c-0.99-0.99-1.61-2.36-1.61-3.86v-93.5c0-1.51,0.62-2.88,1.61-3.87l0.01,0.01c1-0.99,2.37-1.61,3.86-1.61 h70.79c1.5,0,2.87,0.62,3.86,1.61l0,0l0.01,0.01c0.99,0.99,1.61,2.36,1.61,3.86V90.55L100.56,90.55z M94.45,86.9V24.54H24.92v92.24 h41.13V89.95c0-1.69,1.37-3.05,3.05-3.05H94.45L94.45,86.9z"/></g></svg>
52+
</button>
53+
</div>
54+
</div>
55+
`
56+
if (data.type === 'button') {
57+
html = `
58+
<div class="rd-input-block">
59+
<div class="rd-input-block-row">
60+
${htmlInput}
61+
</div>
62+
</div>
63+
`
64+
}
65+
return html
66+
}
67+
68+
const generateTemplateHTML = (data: any, type = '') => {
69+
const id = `template-${Math.floor(Math.random()*1000000000)}`
70+
let html = `
71+
<div class="rd-template">
72+
<pre id="${id}" class="rd-template-content ${type.length > 0 ? 'rd-' + type : ''}">${data}</pre>
73+
<div class="rd-template-menu"><button class="copy-button" onclick="copyTemplate('${id}')">
74+
<svg width="16px" height="16px" version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 100.56 122.88" style="enable-background:new 0 0 100.56 122.88" xml:space="preserve"><g><path d="M72.15,112.2L90.4,93H72.15V112.2L72.15,112.2z M81.75,9.2c0,1.69-1.37,3.05-3.05,3.05c-1.69,0-3.05-1.37-3.05-3.05V6.11 H6.11v92.24h3.01c1.69,0,3.05,1.37,3.05,3.05c0,1.69-1.37,3.05-3.05,3.05H5.48c-1.51,0-2.88-0.61-3.87-1.61l0.01-0.01 c-1-1-1.61-2.37-1.61-3.87V5.48C0,3.97,0.61,2.6,1.61,1.61C2.6,0.61,3.97,0,5.48,0h70.79c1.5,0,2.87,0.62,3.86,1.61l0,0l0.01,0.01 c0.99,0.99,1.61,2.36,1.61,3.86V9.2L81.75,9.2z M100.56,90.55c0,1.4-0.94,2.58-2.22,2.94l-26.88,28.27 c-0.56,0.68-1.41,1.11-2.36,1.11c-0.06,0-0.12,0-0.19-0.01c-0.06,0-0.12,0.01-0.18,0.01H24.29c-1.51,0-2.88-0.61-3.87-1.61 l0.01-0.01l-0.01-0.01c-0.99-0.99-1.61-2.36-1.61-3.86v-93.5c0-1.51,0.62-2.88,1.61-3.87l0.01,0.01c1-0.99,2.37-1.61,3.86-1.61 h70.79c1.5,0,2.87,0.62,3.86,1.61l0,0l0.01,0.01c0.99,0.99,1.61,2.36,1.61,3.86V90.55L100.56,90.55z M94.45,86.9V24.54H24.92v92.24 h41.13V89.95c0-1.69,1.37-3.05,3.05-3.05H94.45L94.45,86.9z"/></g></svg>
75+
</button></div>
76+
</div>
77+
`
78+
templatesObj[id] = data
79+
80+
return html
81+
}
82+
83+
const generateInlineTemplateHTML = (data: any) => {
84+
const id = `template-${Math.floor(Math.random()*1000000000)}`
85+
86+
let html = `
87+
<span class="rd-inline-template">
88+
<span id="${id}" class="rd-inline-template-content">${data}</span>
89+
</span>
90+
`
91+
templatesObj[id] = data
92+
93+
return html
94+
}
95+
96+
const createGenericBlock = (content: string, type = '') => {
97+
return `
98+
<pre class="rd-generic-block ${type.length > 0 ? 'rd-' + type : ''}">${content}</pre>
99+
`
100+
}
101+
102+
/////
103+
/////
104+
/////
105+
/////
106+
107+
const RDConvertor = (mdContent: string) => {
108+
109+
110+
stateObj = {}
111+
templatesObj = {}
112+
allVariables = []
113+
codeBlocks = []
114+
115+
// const md = new MDIT({
116+
// html: true, // Enable HTML tags in source
117+
// xhtmlOut: false, // Use '/' to close single tags (<br />).
118+
// // This is only for full CommonMark compatibility.
119+
// breaks: true, // Convert '\n' in paragraphs into <br>
120+
// langPrefix: 'language-', // CSS language prefix for fenced blocks. Can be
121+
// // useful for external highlighters.
122+
// linkify: true, // Autoconvert URL-like text to links
123+
// typographer: false,
124+
// })
125+
126+
const md = MarkdownIt().set({ html: true, breaks: true, xhtmlOut: false, typographer: false, linkify: true })
127+
128+
129+
md.renderer.rules.code_inline = (tokens: Token[],
130+
idx: number,
131+
options: MarkdownIt.Options,
132+
env: any,
133+
self: Renderer,) => {
134+
135+
const token = tokens[idx]
136+
const content = token.content.trim()
137+
return generateInlineTemplateHTML(content)
138+
}
139+
140+
141+
md.renderer.rules.fence = (tokens: Token[],
142+
idx: number,
143+
options: MarkdownIt.Options,
144+
env: any,
145+
self: Renderer,) => {
146+
// a code block
147+
const token = tokens[idx]
148+
149+
if (token.tag === 'code') {
150+
const parts = token.info.split(/\s+/)
151+
let tokenName = token.info
152+
if (parts.length > 1) {
153+
tokenName = parts[0]
154+
}
155+
156+
if (tokenName === '@input') {
157+
const content = token.content.trim()
158+
try {
159+
const jsonContent = JSON.parse(content)
160+
const html = generateInputHTML(jsonContent)
161+
return html
162+
} catch (error) {
163+
return content
164+
}
165+
} else if (tokenName === '@template') {
166+
const content = token.content.trim()
167+
try {
168+
const html = generateTemplateHTML(content, parts[1])
169+
return html
170+
} catch (error) {
171+
return content
172+
}
173+
} else if (tokenName === '@code') {
174+
const content = token.content.trim()
175+
codeBlocks.push(content)
176+
return ''
177+
} else {
178+
const content = token.content.trim()
179+
return createGenericBlock(content, tokenName)
180+
}
181+
}
182+
183+
return token.content
184+
}
185+
186+
187+
const html = md.render(mdContent)
188+
let templateFileContent = htmlTemplate.replace('REPLACE_HTML', html)
189+
190+
const stateStr = `var state = ${JSON.stringify(stateObj)}`
191+
templateFileContent = templateFileContent.replace('REPLACE_STATE', stateStr)
192+
193+
const templatesStr = `var templates = ${JSON.stringify(templatesObj)}`
194+
templateFileContent = templateFileContent.replace('REPLACE_TEMPLATES', templatesStr)
195+
196+
const codeBlocksStr = codeBlocks.join('\n\n')
197+
templateFileContent = templateFileContent.replace('REPLACE_CODE', codeBlocksStr)
198+
199+
const mdLines = mdContent.split('\n')
200+
const mdHtmlLines = mdLines.map(e => `<!--${_.escape(e)}-->`)
201+
const mdLinesStr = mdHtmlLines.join('\n')
202+
templateFileContent = templateFileContent.replace('REPLACE_MD', mdLinesStr)
203+
204+
return {templateFileContent, allVariables}
205+
}
206+
207+
export default RDConvertor

0 commit comments

Comments
 (0)