@tenjuu99/blog 0.2.5 → 0.2.7

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/bin/dev-server ADDED
@@ -0,0 +1,58 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { spawn } from 'child_process'
4
+ import { srcDir, pageDir, serverDir, helperDir } from '../lib/dir.js'
5
+ import { watchers, watch } from '../lib/watcher.js'
6
+ import generate from '../lib/generate.js'
7
+ import path from 'path'
8
+ import { fileURLToPath } from 'url';
9
+
10
+ const __filename = fileURLToPath(import.meta.url);
11
+ const libDir = path.dirname(__filename) + '/../lib/'
12
+ const binDir = path.dirname(__filename) + '/../bin/'
13
+
14
+ watchers.push({
15
+ paths: srcDir,
16
+ watchOptions: {
17
+ ignored: [pageDir, serverDir, helperDir],
18
+ },
19
+ callback: generate
20
+ })
21
+ watchers.push({
22
+ paths: pageDir,
23
+ callback: generate,
24
+ watchOptions: {
25
+ ignoreInitial: true
26
+ },
27
+ event: ['change', 'unlink', 'add']
28
+ })
29
+ watchers.push({
30
+ paths: [serverDir, helperDir, libDir],
31
+ callback: () => {
32
+ childProcess.kill('SIGINT')
33
+ childProcess = proceed()
34
+ console.error('restarting')
35
+ }
36
+ })
37
+ watch()
38
+
39
+ let childProcess = null
40
+
41
+ const proceed = () => {
42
+ const child = spawn('node', [`${binDir}server`])
43
+ console.log(`start process. PID(parent): ${process.pid}, PID(child): ${child.pid}`)
44
+
45
+ child.stdout.on('data', (data) => {
46
+ console.log(data.toString().split('\n').filter(v => v).join('\n'))
47
+ })
48
+ child.stderr.on('data', (data) => {
49
+ console.log(data.toString().split('\n').filter(v => v).join('\n'))
50
+ })
51
+ child.on('exit', (code, signal) => {
52
+ console.error(`process exit: ${code}, SIGNAL: ${signal}`);
53
+ })
54
+
55
+ return child
56
+ }
57
+
58
+ childProcess = proceed()
package/bin/server CHANGED
@@ -1,26 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  import server from '../lib/server.js'
4
- import { srcDir, pageDir } from '../lib/dir.js'
5
- import { watchers, watch } from '../lib/watcher.js'
6
4
  import generate from '../lib/generate.js'
7
5
 
8
- watchers.push({
9
- paths: srcDir,
10
- watchOptions: {
11
- ignored: pageDir
12
- },
13
- callback: generate
14
- })
15
- watchers.push({
16
- paths: pageDir,
17
- callback: generate,
18
- watchOptions: {
19
- ignoreInitial: true
20
- },
21
- event: ['change', 'unlink', 'add']
22
- })
23
- watch()
24
6
  generate()
25
-
26
7
  server().listen(process.env.PORT || 8000)
package/lib/dir.js CHANGED
@@ -8,6 +8,7 @@ const templateDir = `${srcDir}/template`
8
8
  const cssDir = `${srcDir}/css`
9
9
  const cacheDir = `${rootDir}/.cache`
10
10
  const serverDir = `${srcDir}/server`
11
+ const helperDir = `${srcDir}/helper`
11
12
 
12
13
  export {
13
14
  rootDir,
@@ -17,5 +18,6 @@ export {
17
18
  templateDir,
18
19
  cssDir,
19
20
  cacheDir,
20
- serverDir
21
+ serverDir,
22
+ helperDir
21
23
  }
package/lib/pageData.js CHANGED
@@ -24,6 +24,7 @@ const parse = (content, name, ext) => {
24
24
  site_name: config.site_name,
25
25
  url_base: config.url_base,
26
26
  markdown: markdownReplaced,
27
+ markdown_not_parsed: markdownReplaced,
27
28
  relative_path: config.relative_path || '',
28
29
  template: 'default.html',
29
30
  ext: 'html',
package/lib/server.js CHANGED
@@ -61,7 +61,7 @@ const server = () => {
61
61
  } catch (e) {
62
62
  console.log(e)
63
63
  console.log(styleText('red', `[${request.method}] 500`), request.url)
64
- const errorContent = fs.readFileSync(`${distDir}/404.html`)
64
+ const errorContent = fs.readFileSync(`${distDir}/500.html`)
65
65
  response.writeHead(500)
66
66
  response.end(errorContent)
67
67
  }
package/package.json CHANGED
@@ -1,16 +1,17 @@
1
1
  {
2
2
  "name": "@tenjuu99/blog",
3
- "version": "0.2.5",
3
+ "version": "0.2.7",
4
4
  "description": "blog template",
5
5
  "main": "index.js",
6
6
  "scripts": {
7
- "dev": "node bin/server",
7
+ "dev": "node bin/dev-server",
8
+ "server": "node bin/server",
8
9
  "generate": "node bin/generate",
9
10
  "test": "echo \"Error: no test specified\" && exit 1"
10
11
  },
11
12
  "bin": {
12
13
  "generate": "bin/generate",
13
- "server": "bin/server",
14
+ "server": "bin/dev-server",
14
15
  "create-blog": "bin/new"
15
16
  },
16
17
  "author": "AmashigeSeiji",
@@ -1,13 +1,19 @@
1
1
  body {
2
2
  background: #fafafa;
3
- --container-max-width: 90%;
4
- --container-min-width: 90%;
5
- --container-width: 90%;
3
+ --container-max-width: 100%;
4
+ --container-min-width: 100%;
5
+ --container-width: 100%;
6
6
  height: 100vh;
7
7
  }
8
8
  main {
9
9
  height: 100%;
10
10
  margin: 0 auto;
11
+ display: flex;
12
+ flex-direction: row;
13
+ justify-content: flex-start;
14
+ }
15
+ main.container {
16
+ padding: 0;
11
17
  }
12
18
  .textareaAndPreview {
13
19
  display: flex;
@@ -22,9 +28,19 @@ main {
22
28
  .editor {
23
29
  display: flex;
24
30
  flex-direction: column;
25
- padding: 15px 0;
31
+ padding: 15px 20px;
26
32
  justify-content:center;
27
33
  height: 100%;
34
+ /* width: 100%; */
35
+ margin: 0 auto;
36
+ position: relative;
37
+ left: 0;
38
+ flex-basis: 100%;
39
+ transition: flex-basis 0.3s;
40
+ }
41
+ .sidebar-close .editor {
42
+ flex-basis: 90%;
43
+ transition: flex-basis 0.3s;
28
44
  }
29
45
  #editorTextArea {
30
46
  resize: none;
@@ -61,43 +77,45 @@ form select {
61
77
  .sidebar {
62
78
  display: flex;
63
79
  justify-content: space-between;
64
- width: 50vw;
80
+ width: 300px;
65
81
  overflow: hidden;
66
- position: absolute;
82
+ left: 0;
67
83
  background: rgba(104, 117, 154);
68
84
  height: 100%;
69
85
  padding: 0;
70
- box-shadow: 3px 13px 13px rgba(50, 50, 50, 0.5);
71
- left: 0;
72
- transition: left 0.3s, width 0.3s;
73
86
  overflow-y: hidden;
87
+ transition: left 0.3s, flex-basis 0.3s;
88
+ flex-basis: 300px;
89
+ position: relative;
90
+ }
91
+ .sidebar-close .sidebar {
92
+ left: -290px;
93
+ transition: left 0.3s, flex-basis 0.3s;
94
+ flex-basis: 0;
74
95
  }
75
- .sidebar.close {
76
- left: -48vw;
77
- transition: left 0.3s, width 0.3s;
96
+ .sidebar ul {
97
+ padding: 0;
98
+ margin: 0 0 0 20px;
99
+ left: 0;
100
+ transition: left 0.3s;
101
+ min-width: 180px;
102
+ max-width: 180px;
103
+ }
104
+ .sidebar-close .sidebar ul {
105
+ position: absolute;
106
+ left: -290px;
107
+ transition: left 0.3s;
78
108
  }
79
109
  @media screen and (min-width: 1100px) {
80
- .sidebar {
81
- width: 40vw;
82
- }
83
- .sidebar.close {
84
- left: -39vw;
85
- }
86
110
  }
87
111
  @media screen and (min-width: 1400px) {
88
- .sidebar {
89
- width: 30vw;
90
- }
91
- .sidebar.close {
92
- left: -29vw;
93
- }
94
112
  }
95
113
  @media screen and (max-width: 600px) {
96
114
  .sidebar {
97
- width: 80vw;
115
+ flex-basis: 80%;
98
116
  }
99
117
  .sidebar.close {
100
- left: -77vw;
118
+ flex-basis: 5%;
101
119
  }
102
120
  }
103
121
  .sidebar li {
@@ -110,7 +128,11 @@ form select {
110
128
  cursor: pointer;
111
129
  width: 20px;
112
130
  height: 100%;
113
- position: relative;
131
+ background: rgba(104, 117, 154);
132
+ }
133
+ .sidebar-close .sidebar-toggle {
134
+ position: fixed;
135
+ left: 0;
114
136
  }
115
137
  .sidebar-toggle:hover:after {
116
138
  position: absolute;
@@ -125,6 +147,24 @@ form select {
125
147
  width: 100%;
126
148
  display: block;
127
149
  }
150
+ main.container {
151
+ padding: 0 5px;
152
+ }
153
+ .sidebar {
154
+ position: fixed;
155
+ width: 80vw;
156
+ z-index: 3;
157
+ right: 0;
158
+ left: unset;
159
+ transition: right .3s, width .3s;
160
+ }
161
+ .sidebar-close .sidebar {
162
+ width: 0;
163
+ position: fixed;
164
+ right: -300px;
165
+ left: unset;
166
+ transition: right .3s, width .3s;
167
+ }
128
168
  .editor {
129
169
  padding: 15px 0;
130
170
  }
@@ -134,4 +174,64 @@ form select {
134
174
  #editorTextArea {
135
175
  flex-basis: 100%;
136
176
  }
177
+ .sidebar-toggle {
178
+ display: none;
179
+ }
180
+ }
181
+ /**
182
+ * hamburger
183
+ */
184
+ .hamburger-menu {
185
+ display: none;
186
+ }
187
+ @media screen and (max-width: 600px) {
188
+ .hamburger-menu {
189
+ display: block;
190
+ }
191
+ .menu-btn {
192
+ position: fixed;
193
+ top: 10px;
194
+ right: 10px;
195
+ display: flex;
196
+ height: 40px;
197
+ width: 40px;
198
+ justify-content: center;
199
+ align-items: center;
200
+ z-index: 90;
201
+ /* background-color: #3584bb; */
202
+ }
203
+ .menu-btn span,
204
+ .menu-btn span:before,
205
+ .menu-btn span:after {
206
+ content: '';
207
+ display: block;
208
+ height: 3px;
209
+ width: 25px;
210
+ border-radius: 3px;
211
+ background-color: #ffffff;
212
+ position: absolute;
213
+ transition: transform 0.3s, background-color 0.3s;
214
+ }
215
+ .menu-btn span:before {
216
+ bottom: 8px;
217
+ }
218
+ .menu-btn span:after {
219
+ top: 8px;
220
+ }
221
+ #menu-btn-check:checked ~ .menu-btn span {
222
+ background-color: rgba(255, 255, 255, 0);/*メニューオープン時は真ん中の線を透明にする*/
223
+ }
224
+ #menu-btn-check:checked ~ .menu-btn span::before {
225
+ bottom: 0;
226
+ transform: rotate(45deg);
227
+ transition: transform 0.3s, background-color 0.3s;
228
+ }
229
+ #menu-btn-check:checked ~ .menu-btn span::after {
230
+ top: 0;
231
+ transform: rotate(-45deg);
232
+ transition: transform 0.3s, background-color 0.3s;
233
+ }
234
+ #menu-btn-check {
235
+ display: none;
236
+ }
137
237
  }
@@ -43,7 +43,6 @@ body {
43
43
  */
44
44
  header {
45
45
  padding: 10px 0;
46
- border-bottom: 0.5px solid #ccc;
47
46
  background: var(--header-bg);
48
47
  }
49
48
 
@@ -3,8 +3,15 @@ const sleep = waitTime => new Promise( resolve => setTimeout(resolve, waitTime)
3
3
  const fetchData = (target) => {
4
4
  return fetch(`/get_editor_target?md=${target}`)
5
5
  .then(async res => {
6
- const json = await res.json()
7
- return json
6
+ if (!res.ok) {
7
+ document.querySelector('#inputFileName').value = target
8
+ document.querySelector('#editorTextArea').value = `${target.split('.')[0]}についての記事を作成しましょう`
9
+ // submit('/preview', form)
10
+ throw new Error(`${target} does not exist.`)
11
+ } else {
12
+ const json = await res.json()
13
+ return json
14
+ }
8
15
  })
9
16
  }
10
17
  const onloadFunction = async (e) => {
@@ -22,6 +29,9 @@ const onloadFunction = async (e) => {
22
29
  inputFileName.value = json.filename
23
30
  inputFileName.setAttribute('disabled', true)
24
31
  submit('/preview', form)
32
+ }).catch(e => {
33
+ console.log('error!!!')
34
+ console.log(e)
25
35
  })
26
36
  }
27
37
  select.addEventListener('change', async (event) => {
@@ -51,7 +61,7 @@ const onloadFunction = async (e) => {
51
61
  formData.forEach((v, k) => {
52
62
  obj[k] = v
53
63
  })
54
- fetch(fetchUrl, {
64
+ return fetch(fetchUrl, {
55
65
  method: 'post',
56
66
  body: JSON.stringify(obj)
57
67
  }).then(async response => {
@@ -67,7 +77,7 @@ const onloadFunction = async (e) => {
67
77
  if (json.preview) {
68
78
  const iframe = document.createElement('iframe')
69
79
  iframe.setAttribute('srcdoc', json.preview)
70
- iframe.setAttribute('sandbox', '')
80
+ iframe.setAttribute('sandbox', 'allow-same-origin allow-scripts')
71
81
  const old = preview.querySelector('iframe')
72
82
  if (!old) {
73
83
  preview.appendChild(iframe)
@@ -87,14 +97,18 @@ const onloadFunction = async (e) => {
87
97
 
88
98
  const sidebarToggle = (e) => {
89
99
  const sidebar = document.querySelector('.sidebar')
100
+ const main = document.querySelector('main')
90
101
  const toggle = sidebar.querySelector('.sidebar-toggle')
91
102
  toggle.addEventListener('click', (e) => {
92
103
  e.preventDefault()
93
- sidebar.classList.toggle('close')
104
+ main.classList.toggle('sidebar-close')
105
+ })
106
+ const hamburger = document.querySelector('.hamburger-menu input[type="checkbox"]')
107
+ hamburger.addEventListener('change', (e) => {
108
+ main.classList.toggle('sidebar-close')
94
109
  })
95
110
  }
96
111
  document.addEventListener('DOMContentLoaded', (event) => {
97
- console.log(event)
98
112
  onloadFunction(event)
99
113
  sidebarToggle(event)
100
114
  })
@@ -0,0 +1,7 @@
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
+ }
@@ -0,0 +1,5 @@
1
+ ---
2
+ index: false
3
+ noindex: true
4
+ ---
5
+ 問題が発生しました。
@@ -3,3 +3,5 @@ template: editor.html
3
3
  index: false
4
4
  distribute: config.editor_enable
5
5
  ---
6
+
7
+ 新規に記事を作成しましょう。
@@ -3,6 +3,7 @@ title: 404 not found
3
3
  url: /404
4
4
  index: false
5
5
  noindex: true
6
+ add_script: /js/error.js
6
7
  ---
7
8
 
8
9
  記事が見つかりませんでした。
@@ -17,7 +17,11 @@ export const get = async (req, res) => {
17
17
  }
18
18
  const file = `${pageDir}/${target}`
19
19
  if (!fs.existsSync(`${file}`)) {
20
- return false
20
+ return {
21
+ status: 404,
22
+ contentType: 'application/json',
23
+ body: JSON.stringify({ content: '', filename: target })
24
+ }
21
25
  }
22
26
  const f = fs.readFileSync(`${file}`, 'utf8')
23
27
  return {
@@ -16,6 +16,12 @@ export const post = async (req, res) => {
16
16
  .on('end', async () => {
17
17
  const json = JSON.parse(chunks.join())
18
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
+ }
19
25
  const pageData = makePageData(filename, json.content)
20
26
  const rendered = await render(pageData.template, pageData)
21
27
  res.writeHead(200, { 'content-type': 'application/json' })
@@ -48,10 +48,13 @@
48
48
  </main>
49
49
  {if isEditorEnabled() }
50
50
  <div class="container">
51
- <a href="/editor?md={{name}}.{{__filetype}}">編集する</a>
51
+ <a href="/editor?md={{name}}.{{__filetype}}" class="editor_link">編集する</a>
52
52
  </div>
53
53
  {/if}
54
54
 
55
55
  {include('template/footer.html')}
56
+ {if add_script}
57
+ <script src="{{ADD_SCRIPT}}" async></script>
58
+ {/if}
56
59
  </body>
57
60
  </html>
@@ -14,8 +14,13 @@
14
14
  <p class="container">
15
15
  <a href="/">{{SITE_NAME}}/Editor</a>
16
16
  </p>
17
+ <div class="hamburger-menu">
18
+ <input type="checkbox" id="menu-btn-check">
19
+ <label for="menu-btn-check" class="menu-btn"><span></span></label>
20
+ </div>
17
21
  </header>
18
- <div class="sidebar close">
22
+ <main class="container sidebar-close">
23
+ <div class="sidebar">
19
24
  <ul>
20
25
  <script type="ssg">
21
26
  return helper.readIndex().map(p => {
@@ -25,7 +30,6 @@
25
30
  </ul>
26
31
  <div class="sidebar-toggle">&nbsp;</div>
27
32
  </div>
28
- <main class="container">
29
33
  <form action="/editor" class="editor" method="post" id="editor">
30
34
  <input id="inputFileName" name="inputFileName" type="text" value="" placeholder="sample.md">
31
35
  <select id="selectDataFile" name="selectDataFile">
@@ -38,9 +42,7 @@
38
42
  </select>
39
43
  <div class="textareaAndPreview">
40
44
  <textarea id="editorTextArea" name="content" cols="30" rows="10">
41
- # H1
42
-
43
- ここにマークダウンを入力してください。
45
+ {{ MARKDOWN_NOT_PARSED }}
44
46
  </textarea>
45
47
  <div class="preview">
46
48
  <div id="previewContent"></div>