@tenjuu99/blog 0.2.13 → 0.2.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/dir.js +11 -4
- package/package.json +1 -1
- package/src-sample/packages/editor/css/editor.css +0 -252
- package/src-sample/packages/editor/js/editor.js +0 -123
- package/src-sample/packages/editor/js/error.js +0 -8
- package/src-sample/packages/editor/pages/editor.md +0 -7
- package/src-sample/packages/editor/server/editor.js +0 -37
- package/src-sample/packages/editor/server/get_editor_target.js +0 -32
- package/src-sample/packages/editor/server/preview.js +0 -33
- package/src-sample/packages/editor/template/editor.html +0 -58
package/lib/dir.js
CHANGED
|
@@ -2,6 +2,8 @@ import config from './config.js'
|
|
|
2
2
|
import { watchers } from './watcher.js'
|
|
3
3
|
import fs from 'node:fs'
|
|
4
4
|
import { styleText } from 'node:util'
|
|
5
|
+
import path from 'path'
|
|
6
|
+
import { fileURLToPath } from 'url';
|
|
5
7
|
|
|
6
8
|
const rootDir = process.cwd()
|
|
7
9
|
const srcDir = `${rootDir}/${config.src_dir}`
|
|
@@ -21,6 +23,8 @@ const watch = {
|
|
|
21
23
|
helperDir: `${srcDir}/helper`,
|
|
22
24
|
jsDir: `${srcDir}/js`,
|
|
23
25
|
}
|
|
26
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
27
|
+
const packageDirCore = path.dirname(__filename) + '/../packages'
|
|
24
28
|
|
|
25
29
|
let alreadyCached = false
|
|
26
30
|
|
|
@@ -31,11 +35,14 @@ const cache = () => {
|
|
|
31
35
|
if (config.packages) {
|
|
32
36
|
const packages = config.packages.split(',')
|
|
33
37
|
packages.forEach(dir => {
|
|
34
|
-
if (
|
|
35
|
-
|
|
38
|
+
if (fs.existsSync(`${packageDirCore}/${dir}`)) {
|
|
39
|
+
console.log(styleText('blue', `[cache] enable core package: ${dir}`))
|
|
40
|
+
fs.cpSync(`${packageDirCore}/${dir}`, cacheDir, { recursive: true })
|
|
41
|
+
}
|
|
42
|
+
if (fs.existsSync(`${packageDir}/${dir}`)) {
|
|
43
|
+
console.log(styleText('blue', `[cache] enable package: ${dir}`))
|
|
44
|
+
fs.cpSync(`${packageDir}/${dir}`, cacheDir, { recursive: true })
|
|
36
45
|
}
|
|
37
|
-
console.log(styleText('blue', `[cache] enable package: ${dir}`))
|
|
38
|
-
fs.cpSync(`${packageDir}/${dir}`, cacheDir, { recursive: true })
|
|
39
46
|
})
|
|
40
47
|
}
|
|
41
48
|
fs.cpSync(srcDir, cacheDir, {
|
package/package.json
CHANGED
|
@@ -1,252 +0,0 @@
|
|
|
1
|
-
body {
|
|
2
|
-
background: #fafafa;
|
|
3
|
-
height: 100vh;
|
|
4
|
-
display: flex;
|
|
5
|
-
flex-direction: column;
|
|
6
|
-
}
|
|
7
|
-
header {
|
|
8
|
-
text-align: center;
|
|
9
|
-
border-bottom: .1px solid #eee;
|
|
10
|
-
box-shadow: 1px 1px 3px #999;
|
|
11
|
-
}
|
|
12
|
-
main {
|
|
13
|
-
height: 100%;
|
|
14
|
-
/*margin: 0 auto;*/
|
|
15
|
-
display: flex;
|
|
16
|
-
flex-direction: row;
|
|
17
|
-
justify-content: flex-start;
|
|
18
|
-
}
|
|
19
|
-
main.container {
|
|
20
|
-
padding: 0;
|
|
21
|
-
}
|
|
22
|
-
.textareaAndPreview {
|
|
23
|
-
display: flex;
|
|
24
|
-
margin: 0;
|
|
25
|
-
border: 1px solid #666;
|
|
26
|
-
border-radius: 5px;
|
|
27
|
-
height: 100%;
|
|
28
|
-
}
|
|
29
|
-
.textareaAndPreview>* {
|
|
30
|
-
flex-basis: 50%;
|
|
31
|
-
}
|
|
32
|
-
.editor {
|
|
33
|
-
display: flex;
|
|
34
|
-
flex-direction: column;
|
|
35
|
-
padding: 5px;
|
|
36
|
-
justify-content:center;
|
|
37
|
-
height: 100%;
|
|
38
|
-
/* width: 100%; */
|
|
39
|
-
margin: 0;
|
|
40
|
-
position: relative;
|
|
41
|
-
width: 100%;
|
|
42
|
-
left: 0;
|
|
43
|
-
flex-basis: 100%;
|
|
44
|
-
}
|
|
45
|
-
.sidebar-close .editor {
|
|
46
|
-
/*flex-basis: 90%;*/
|
|
47
|
-
margin-left: 20px;
|
|
48
|
-
}
|
|
49
|
-
.editor-options {
|
|
50
|
-
display: flex;
|
|
51
|
-
justify-content: space-between;
|
|
52
|
-
}
|
|
53
|
-
#editorTextArea {
|
|
54
|
-
resize: none;
|
|
55
|
-
background: #cccccc;
|
|
56
|
-
color: #333;
|
|
57
|
-
padding: 5px;
|
|
58
|
-
border-radius: 5px 0 0 5px;
|
|
59
|
-
border: 0;
|
|
60
|
-
transition: background 0.2s;
|
|
61
|
-
}
|
|
62
|
-
#editorTextArea:focus {
|
|
63
|
-
background: #eee;
|
|
64
|
-
transition: background 0.2s;
|
|
65
|
-
outline: none;
|
|
66
|
-
}
|
|
67
|
-
form select {
|
|
68
|
-
padding: 5px;
|
|
69
|
-
border-radius: 5px;
|
|
70
|
-
}
|
|
71
|
-
#previewContent {
|
|
72
|
-
flex-basis: 100%;
|
|
73
|
-
height: 100%;
|
|
74
|
-
min-height: 90%;
|
|
75
|
-
display: block;
|
|
76
|
-
width: 100%;
|
|
77
|
-
}
|
|
78
|
-
#previewContent iframe {
|
|
79
|
-
width: 100%;
|
|
80
|
-
height: 100%;
|
|
81
|
-
border: none;
|
|
82
|
-
border-radius: 0 5px 5px 0;
|
|
83
|
-
}
|
|
84
|
-
.sidebar {
|
|
85
|
-
display: flex;
|
|
86
|
-
justify-content: space-between;
|
|
87
|
-
width: 300px;
|
|
88
|
-
overflow: hidden;
|
|
89
|
-
left: 0;
|
|
90
|
-
background: rgb(192, 198, 217);
|
|
91
|
-
height: 100%;
|
|
92
|
-
padding: 0;
|
|
93
|
-
overflow-y: hidden;
|
|
94
|
-
flex-basis: 300px;
|
|
95
|
-
position: relative;
|
|
96
|
-
z-index: 3;
|
|
97
|
-
word-break: break-all;
|
|
98
|
-
}
|
|
99
|
-
.sidebar-close .sidebar {
|
|
100
|
-
left: -290px;
|
|
101
|
-
flex-basis: 0;
|
|
102
|
-
}
|
|
103
|
-
.sidebar ul {
|
|
104
|
-
padding: 0;
|
|
105
|
-
margin: 0;
|
|
106
|
-
}
|
|
107
|
-
.sidebar-close .sidebar ul {
|
|
108
|
-
position: absolute;
|
|
109
|
-
left: -290px;
|
|
110
|
-
transition: left 0.3s;
|
|
111
|
-
}
|
|
112
|
-
.sidebar li {
|
|
113
|
-
list-style: none;
|
|
114
|
-
padding-left: 20px;
|
|
115
|
-
}
|
|
116
|
-
.sidebar a {
|
|
117
|
-
color: #666;
|
|
118
|
-
text-decoration: none;
|
|
119
|
-
}
|
|
120
|
-
.sidebar li:hover {
|
|
121
|
-
background: rgba(104, 117, 154, .3);
|
|
122
|
-
}
|
|
123
|
-
.sidebar-toggle {
|
|
124
|
-
cursor: pointer;
|
|
125
|
-
width: 20px;
|
|
126
|
-
height: 100%;
|
|
127
|
-
position: absolute;
|
|
128
|
-
right: 0;
|
|
129
|
-
}
|
|
130
|
-
.sidebar-close .sidebar-toggle {
|
|
131
|
-
position: fixed;
|
|
132
|
-
left: 0;
|
|
133
|
-
background: rgb(192, 198, 217);
|
|
134
|
-
}
|
|
135
|
-
.sidebar-toggle:hover:after {
|
|
136
|
-
position: absolute;
|
|
137
|
-
right: 0;
|
|
138
|
-
content: '';
|
|
139
|
-
height: 100%;
|
|
140
|
-
width: 20px;
|
|
141
|
-
background: rgba(255, 255,255, 0.3);
|
|
142
|
-
}
|
|
143
|
-
@media screen and (max-width: 600px) {
|
|
144
|
-
main {
|
|
145
|
-
width: 100%;
|
|
146
|
-
display: block;
|
|
147
|
-
}
|
|
148
|
-
main.container {
|
|
149
|
-
padding: 0 5px;
|
|
150
|
-
}
|
|
151
|
-
.sidebar {
|
|
152
|
-
position: fixed;
|
|
153
|
-
width: 80vw;
|
|
154
|
-
z-index: 3;
|
|
155
|
-
right: 0;
|
|
156
|
-
left: unset;
|
|
157
|
-
transition: right .3s, width .3s;
|
|
158
|
-
}
|
|
159
|
-
.sidebar-close .sidebar {
|
|
160
|
-
width: 0;
|
|
161
|
-
position: fixed;
|
|
162
|
-
right: -300px;
|
|
163
|
-
left: unset;
|
|
164
|
-
transition: right .3s, width .3s;
|
|
165
|
-
}
|
|
166
|
-
.editor {
|
|
167
|
-
padding: 15px 0;
|
|
168
|
-
}
|
|
169
|
-
.preview {
|
|
170
|
-
display: none;
|
|
171
|
-
}
|
|
172
|
-
#editorTextArea {
|
|
173
|
-
flex-basis: 100%;
|
|
174
|
-
}
|
|
175
|
-
.sidebar-toggle {
|
|
176
|
-
display: none;
|
|
177
|
-
}
|
|
178
|
-
.sidebar {
|
|
179
|
-
flex-basis: 80%;
|
|
180
|
-
}
|
|
181
|
-
.sidebar.close {
|
|
182
|
-
flex-basis: 5%;
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
/**
|
|
186
|
-
* hamburger
|
|
187
|
-
*/
|
|
188
|
-
.hamburger-menu {
|
|
189
|
-
display: none;
|
|
190
|
-
}
|
|
191
|
-
@media screen and (max-width: 600px) {
|
|
192
|
-
.sidebar-close .editor {
|
|
193
|
-
margin-left: 0;
|
|
194
|
-
margin: 0;
|
|
195
|
-
}
|
|
196
|
-
.editor-options {
|
|
197
|
-
margin-right: 50px;
|
|
198
|
-
}
|
|
199
|
-
.editor-options * {
|
|
200
|
-
display: flex;
|
|
201
|
-
flex-direction: column;
|
|
202
|
-
}
|
|
203
|
-
.hamburger-menu {
|
|
204
|
-
display: block;
|
|
205
|
-
}
|
|
206
|
-
.menu-btn {
|
|
207
|
-
position: fixed;
|
|
208
|
-
top: 10px;
|
|
209
|
-
right: 10px;
|
|
210
|
-
display: flex;
|
|
211
|
-
height: 40px;
|
|
212
|
-
width: 40px;
|
|
213
|
-
justify-content: center;
|
|
214
|
-
align-items: center;
|
|
215
|
-
z-index: 90;
|
|
216
|
-
/* background-color: #3584bb; */
|
|
217
|
-
}
|
|
218
|
-
.menu-btn span,
|
|
219
|
-
.menu-btn span:before,
|
|
220
|
-
.menu-btn span:after {
|
|
221
|
-
content: '';
|
|
222
|
-
display: block;
|
|
223
|
-
height: 3px;
|
|
224
|
-
width: 25px;
|
|
225
|
-
border-radius: 3px;
|
|
226
|
-
background-color: #666666;
|
|
227
|
-
position: absolute;
|
|
228
|
-
transition: transform 0.3s, background-color 0.3s;
|
|
229
|
-
}
|
|
230
|
-
.menu-btn span:before {
|
|
231
|
-
bottom: 8px;
|
|
232
|
-
}
|
|
233
|
-
.menu-btn span:after {
|
|
234
|
-
top: 8px;
|
|
235
|
-
}
|
|
236
|
-
#menu-btn-check:checked ~ .menu-btn span {
|
|
237
|
-
background-color: rgba(255, 255, 255, 0);/*メニューオープン時は真ん中の線を透明にする*/
|
|
238
|
-
}
|
|
239
|
-
#menu-btn-check:checked ~ .menu-btn span::before {
|
|
240
|
-
bottom: 0;
|
|
241
|
-
transform: rotate(45deg);
|
|
242
|
-
transition: transform 0.3s, background-color 0.3s;
|
|
243
|
-
}
|
|
244
|
-
#menu-btn-check:checked ~ .menu-btn span::after {
|
|
245
|
-
top: 0;
|
|
246
|
-
transform: rotate(-45deg);
|
|
247
|
-
transition: transform 0.3s, background-color 0.3s;
|
|
248
|
-
}
|
|
249
|
-
#menu-btn-check {
|
|
250
|
-
display: none;
|
|
251
|
-
}
|
|
252
|
-
}
|
|
@@ -1,123 +0,0 @@
|
|
|
1
|
-
const sleep = waitTime => new Promise( resolve => setTimeout(resolve, waitTime) );
|
|
2
|
-
|
|
3
|
-
const fetchData = (target) => {
|
|
4
|
-
return fetch(`/get_editor_target?md=${target}`)
|
|
5
|
-
.then(async res => {
|
|
6
|
-
if (!res.ok) {
|
|
7
|
-
document.querySelector('#inputFileName').value = target
|
|
8
|
-
document.querySelector('#editorTextArea').value = `---
|
|
9
|
-
title: ${target.split('.')[0].split('/').pop()}
|
|
10
|
-
---
|
|
11
|
-
${target.split('.')[0].split('/').pop()} についての記事を作成しましょう`
|
|
12
|
-
// submit('/preview', form)
|
|
13
|
-
throw new Error(`${target} does not exist.`)
|
|
14
|
-
} else {
|
|
15
|
-
const json = await res.json()
|
|
16
|
-
return json
|
|
17
|
-
}
|
|
18
|
-
})
|
|
19
|
-
}
|
|
20
|
-
const onloadFunction = async (e) => {
|
|
21
|
-
const form = document.querySelector('#editor')
|
|
22
|
-
const textarea = form.querySelector('#editorTextArea')
|
|
23
|
-
const select = form.querySelector('#selectDataFile')
|
|
24
|
-
const inputFileName = form.querySelector('#inputFileName')
|
|
25
|
-
const preview = document.querySelector('#previewContent')
|
|
26
|
-
const url = new URL(location)
|
|
27
|
-
const target = url.searchParams.get('md')
|
|
28
|
-
if (target) {
|
|
29
|
-
fetchData(target).then(json => {
|
|
30
|
-
textarea.value = json.content
|
|
31
|
-
select.value = json.filename
|
|
32
|
-
inputFileName.value = json.filename
|
|
33
|
-
inputFileName.setAttribute('disabled', true)
|
|
34
|
-
submit('/preview', form)
|
|
35
|
-
}).catch(e => {
|
|
36
|
-
console.log('error!!!')
|
|
37
|
-
console.log(e)
|
|
38
|
-
})
|
|
39
|
-
}
|
|
40
|
-
select.addEventListener('change', async (event) => {
|
|
41
|
-
if (select.value) {
|
|
42
|
-
const json = await fetchData(select.value)
|
|
43
|
-
textarea.value = json.content
|
|
44
|
-
inputFileName.value = json.filename
|
|
45
|
-
inputFileName.setAttribute('disabled', true)
|
|
46
|
-
url.searchParams.set('md', select.value)
|
|
47
|
-
submit('/preview', form)
|
|
48
|
-
} else {
|
|
49
|
-
inputFileName.value = ""
|
|
50
|
-
inputFileName.removeAttribute('disabled')
|
|
51
|
-
textarea.value = ''
|
|
52
|
-
url.searchParams.set('md', "")
|
|
53
|
-
const iframe = preview.querySelector('iframe')
|
|
54
|
-
if (iframe) {
|
|
55
|
-
iframe.srcdoc = ''
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
history.pushState({}, "", url)
|
|
59
|
-
})
|
|
60
|
-
|
|
61
|
-
const submit = (fetchUrl, form) => {
|
|
62
|
-
const formData = new FormData(form)
|
|
63
|
-
const obj = {}
|
|
64
|
-
formData.forEach((v, k) => {
|
|
65
|
-
obj[k] = v
|
|
66
|
-
})
|
|
67
|
-
return fetch(fetchUrl, {
|
|
68
|
-
method: 'post',
|
|
69
|
-
body: JSON.stringify(obj)
|
|
70
|
-
}).then(async response => {
|
|
71
|
-
const json = await response.json()
|
|
72
|
-
if (!response.ok) {
|
|
73
|
-
alert(json.message)
|
|
74
|
-
return
|
|
75
|
-
}
|
|
76
|
-
if (json.href) {
|
|
77
|
-
await sleep(300)
|
|
78
|
-
location.href = json.href
|
|
79
|
-
}
|
|
80
|
-
if (json.preview) {
|
|
81
|
-
const iframe = document.createElement('iframe')
|
|
82
|
-
iframe.setAttribute('srcdoc', json.preview)
|
|
83
|
-
iframe.setAttribute('sandbox', 'allow-same-origin allow-scripts')
|
|
84
|
-
const old = preview.querySelector('iframe')
|
|
85
|
-
if (!old) {
|
|
86
|
-
preview.appendChild(iframe)
|
|
87
|
-
}
|
|
88
|
-
old.setAttribute('srcdoc', json.preview)
|
|
89
|
-
}
|
|
90
|
-
}).catch(e => {
|
|
91
|
-
console.log(e.message)
|
|
92
|
-
})
|
|
93
|
-
}
|
|
94
|
-
form.addEventListener('submit', (event) => {
|
|
95
|
-
event.preventDefault()
|
|
96
|
-
const fetchUrl = event.submitter.dataset.url
|
|
97
|
-
submit(fetchUrl, event.target)
|
|
98
|
-
})
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
const sidebarToggle = (e) => {
|
|
102
|
-
const sidebar = document.querySelector('.sidebar')
|
|
103
|
-
const main = document.querySelector('main')
|
|
104
|
-
const toggle = sidebar.querySelector('.sidebar-toggle')
|
|
105
|
-
toggle.addEventListener('click', (e) => {
|
|
106
|
-
e.preventDefault()
|
|
107
|
-
main.classList.toggle('sidebar-close')
|
|
108
|
-
localStorage.setItem('sidebar-is-open', !main.classList.contains('sidebar-close'))
|
|
109
|
-
})
|
|
110
|
-
if (localStorage.getItem('sidebar-is-open') === 'true') {
|
|
111
|
-
main.classList.remove('sidebar-close')
|
|
112
|
-
} else {
|
|
113
|
-
main.classList.add('sidebar-close')
|
|
114
|
-
}
|
|
115
|
-
const hamburger = document.querySelector('.hamburger-menu input[type="checkbox"]')
|
|
116
|
-
hamburger.addEventListener('change', (e) => {
|
|
117
|
-
main.classList.toggle('sidebar-close')
|
|
118
|
-
})
|
|
119
|
-
}
|
|
120
|
-
document.addEventListener('DOMContentLoaded', (event) => {
|
|
121
|
-
onloadFunction(event)
|
|
122
|
-
sidebarToggle(event)
|
|
123
|
-
})
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
document.addEventListener('DOMContentLoaded', (e) => {
|
|
2
|
-
})
|
|
3
|
-
const url = new URL(location)
|
|
4
|
-
if (url.pathname !== '/editor') {
|
|
5
|
-
const link = document.querySelector('.editor_link')
|
|
6
|
-
link.href = `/editor?md=${url.pathname.replace('/', '')}.md`
|
|
7
|
-
link.innerHTML = `[${decodeURI(url.pathname).replace('/', '')}]のページを作成する`
|
|
8
|
-
}
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import { IncomingMessage, ServerResponse } from 'http'
|
|
2
|
-
import fs from 'node:fs/promises'
|
|
3
|
-
import { styleText } from 'node:util'
|
|
4
|
-
import config from '@tenjuu99/blog/lib/config.js'
|
|
5
|
-
import { watch } from '@tenjuu99/blog/lib/dir.js'
|
|
6
|
-
|
|
7
|
-
export const path = '/editor'
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* @param {IncomingMessage} req
|
|
11
|
-
* @param {ServerResponse} res
|
|
12
|
-
*/
|
|
13
|
-
export const post = async (req, res) => {
|
|
14
|
-
const chunks = []
|
|
15
|
-
req
|
|
16
|
-
.on('data', (chunk) => chunks.push(chunk))
|
|
17
|
-
.on('end', async () => {
|
|
18
|
-
const json = JSON.parse(chunks.join())
|
|
19
|
-
const file = json.inputFileName ? json.inputFileName : json.selectDataFile
|
|
20
|
-
if (!file) {
|
|
21
|
-
res.writeHead(400, { 'content-type': 'application/json' })
|
|
22
|
-
res.end(JSON.stringify({
|
|
23
|
-
'message': 'ファイル名がありません'
|
|
24
|
-
}))
|
|
25
|
-
return
|
|
26
|
-
}
|
|
27
|
-
await fs.writeFile(`${watch.pageDir}/${file}`, json.content)
|
|
28
|
-
console.log(styleText('blue', '[editor/post] finished'))
|
|
29
|
-
|
|
30
|
-
const href = file.split('.')[0]
|
|
31
|
-
res.writeHead(200, { 'content-type': 'application/json' })
|
|
32
|
-
res.end(JSON.stringify({
|
|
33
|
-
'href': `/${href}`
|
|
34
|
-
}))
|
|
35
|
-
})
|
|
36
|
-
return true
|
|
37
|
-
}
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { IncomingMessage, ServerResponse } from 'http'
|
|
2
|
-
import fs from 'node:fs'
|
|
3
|
-
import config from '@tenjuu99/blog/lib/config.js'
|
|
4
|
-
import { pageDir } from '@tenjuu99/blog/lib/dir.js'
|
|
5
|
-
|
|
6
|
-
export const path = '/get_editor_target'
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* @param {IncomingMessage} req
|
|
10
|
-
* @param {ServerResponse} res
|
|
11
|
-
*/
|
|
12
|
-
export const get = async (req, res) => {
|
|
13
|
-
const url = new URL(`${config.url_base}${req.url}`)
|
|
14
|
-
const target = url.searchParams.get('md')
|
|
15
|
-
if (!target) {
|
|
16
|
-
return
|
|
17
|
-
}
|
|
18
|
-
const file = `${pageDir}/${target}`
|
|
19
|
-
if (!fs.existsSync(`${file}`)) {
|
|
20
|
-
return {
|
|
21
|
-
status: 404,
|
|
22
|
-
contentType: 'application/json',
|
|
23
|
-
body: JSON.stringify({ content: '', filename: target })
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
const f = fs.readFileSync(`${file}`, 'utf8')
|
|
27
|
-
return {
|
|
28
|
-
status: 200,
|
|
29
|
-
contentType: 'application/json',
|
|
30
|
-
body: JSON.stringify({ content: f, filename: target }),
|
|
31
|
-
}
|
|
32
|
-
}
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import { IncomingMessage, ServerResponse } from 'http'
|
|
2
|
-
import { styleText } from 'node:util'
|
|
3
|
-
import render from '@tenjuu99/blog/lib/render.js'
|
|
4
|
-
import makePageData from '@tenjuu99/blog/lib/pageData.js'
|
|
5
|
-
|
|
6
|
-
export const path = '/preview'
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* @param {IncomingMessage} req
|
|
10
|
-
* @param {ServerResponse} res
|
|
11
|
-
*/
|
|
12
|
-
export const post = async (req, res) => {
|
|
13
|
-
const chunks = []
|
|
14
|
-
req
|
|
15
|
-
.on('data', (chunk) => chunks.push(chunk))
|
|
16
|
-
.on('end', async () => {
|
|
17
|
-
const json = JSON.parse(chunks.join())
|
|
18
|
-
const filename = json.inputFileName ? json.inputFileName : json.selectDataFile
|
|
19
|
-
if (!filename) {
|
|
20
|
-
res.writeHead(400, { 'content-type': 'application/json' })
|
|
21
|
-
return res.end(JSON.stringify({
|
|
22
|
-
message: 'filename is requried.'
|
|
23
|
-
}))
|
|
24
|
-
}
|
|
25
|
-
const pageData = makePageData(filename, json.content)
|
|
26
|
-
const rendered = await render(pageData.template, pageData)
|
|
27
|
-
res.writeHead(200, { 'content-type': 'application/json' })
|
|
28
|
-
res.end(JSON.stringify({
|
|
29
|
-
'preview': rendered
|
|
30
|
-
}))
|
|
31
|
-
})
|
|
32
|
-
return true
|
|
33
|
-
}
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
<!DOCTYPE html>
|
|
2
|
-
<html lang="ja">
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="UTF-8">
|
|
5
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
-
<title>{{SITE_NAME}}</title>
|
|
7
|
-
<link rel="stylesheet" href="${/css/editor.css<<reset.css,editor.css}">
|
|
8
|
-
<script src="/js/editor.js" defer></script>
|
|
9
|
-
|
|
10
|
-
</head>
|
|
11
|
-
<body>
|
|
12
|
-
<main class="container">
|
|
13
|
-
<div class="sidebar">
|
|
14
|
-
<ul>
|
|
15
|
-
<script type="ssg">
|
|
16
|
-
return helper.readIndex().map(p => {
|
|
17
|
-
return `<li><a href="/editor?md=${p.name}.${p.__filetype}">${p.url}.${p.__filetype}</a></li>`
|
|
18
|
-
}).join("\n")
|
|
19
|
-
</script>
|
|
20
|
-
</ul>
|
|
21
|
-
<div class="sidebar-toggle"> </div>
|
|
22
|
-
</div>
|
|
23
|
-
<form action="/editor" class="editor" method="post" id="editor">
|
|
24
|
-
<div class="editor-options">
|
|
25
|
-
<div>
|
|
26
|
-
<input id="inputFileName" name="inputFileName" type="text" value="" placeholder="sample.md">
|
|
27
|
-
<select id="selectDataFile" name="selectDataFile">
|
|
28
|
-
<option value="">新規作成</option>
|
|
29
|
-
<script type="ssg">
|
|
30
|
-
return helper.readIndex().map(p => {
|
|
31
|
-
return `<option value="${p.name}.${p.__filetype}">${p.url}.${p.__filetype}</option>`
|
|
32
|
-
}).join("\n")
|
|
33
|
-
</script>
|
|
34
|
-
</select>
|
|
35
|
-
</div>
|
|
36
|
-
<div>
|
|
37
|
-
<input type="submit" value="preview" data-url="/preview">
|
|
38
|
-
<input type="submit" value="save" data-url="/editor">
|
|
39
|
-
<a href="/">戻る</a>
|
|
40
|
-
</div>
|
|
41
|
-
</div>
|
|
42
|
-
<div class="textareaAndPreview">
|
|
43
|
-
<textarea id="editorTextArea" name="content" cols="30" rows="10">
|
|
44
|
-
{{ MARKDOWN_NOT_PARSED }}
|
|
45
|
-
</textarea>
|
|
46
|
-
<div class="preview">
|
|
47
|
-
<div id="previewContent"></div>
|
|
48
|
-
</div>
|
|
49
|
-
</div>
|
|
50
|
-
<input type="hidden" name="token" value="{{TOKEN}}">
|
|
51
|
-
</form>
|
|
52
|
-
<div class="hamburger-menu">
|
|
53
|
-
<input type="checkbox" id="menu-btn-check">
|
|
54
|
-
<label for="menu-btn-check" class="menu-btn"><span></span></label>
|
|
55
|
-
</div>
|
|
56
|
-
</main>
|
|
57
|
-
</body>
|
|
58
|
-
</html>
|