@tenjuu99/blog 0.2.6 → 0.2.8

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 CHANGED
@@ -9,6 +9,7 @@ import { fileURLToPath } from 'url';
9
9
 
10
10
  const __filename = fileURLToPath(import.meta.url);
11
11
  const libDir = path.dirname(__filename) + '/../lib/'
12
+ const binDir = path.dirname(__filename) + '/../bin/'
12
13
 
13
14
  watchers.push({
14
15
  paths: srcDir,
@@ -38,7 +39,7 @@ watch()
38
39
  let childProcess = null
39
40
 
40
41
  const proceed = () => {
41
- const child = spawn('node', ['bin/server'])
42
+ const child = spawn('node', [`${binDir}server`])
42
43
  console.log(`start process. PID(parent): ${process.pid}, PID(child): ${child.pid}`)
43
44
 
44
45
  child.stdout.on('data', (data) => {
package/bin/new CHANGED
@@ -1,14 +1,5 @@
1
1
  #!/usr/bin/env bash
2
2
 
3
- mkdir -p "$(pwd)/src/pages"
4
- echo "create src/pages"
5
- mkdir -p "$(pwd)/src/template"
6
- echo "create src/template"
7
- mkdir -p "$(pwd)/src/css"
8
- echo "create src/css"
9
- mkdir -p "$(pwd)/src/image"
10
- echo "create src/image"
11
-
12
3
  mkdir "$(pwd)/.cache"
13
4
  echo "[]" > "$(pwd)/.cache/index.json"
14
5
 
@@ -24,7 +15,7 @@ echo '{
24
15
  "src_dir": "src",
25
16
  "dist_dir": "dist",
26
17
  "distribute_raw": "image,js",
27
- "helper": "helper/index.js",
18
+ "helper": "index.js",
28
19
  "editor_enable": true
29
20
  }' > "$(pwd)/blog.json"
30
21
  echo "create blog.json"
package/lib/helper.js CHANGED
@@ -1,12 +1,14 @@
1
- import * as helperDefault from '../helper/index.js'
2
1
  import config from './config.js'
3
- import { srcDir } from './dir.js'
2
+ import { helperDir } from './dir.js'
4
3
 
5
- let helper = {...helperDefault}
4
+ let helper = {}
6
5
 
7
- if (config['helper']) {
8
- const helperAdditional = await import(`${srcDir}/${config.helper}`)
9
- helper = Object.assign(helper, helperAdditional)
6
+ if (config.helper) {
7
+ const files = config.helper.split(',')
8
+ files.forEach(async file => {
9
+ const helperAdditional = await import(`${helperDir}/${file}`)
10
+ helper = Object.assign(helper, helperAdditional)
11
+ })
10
12
  }
11
13
 
12
14
  export default helper
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/lib/tryServer.js CHANGED
@@ -22,6 +22,9 @@ const handlers = async (path) => {
22
22
  * @param {http.ServerResponse} res
23
23
  */
24
24
  const tryServer = async (path, req, res) => {
25
+ if (!fs.existsSync(serverDir)) {
26
+ return
27
+ }
25
28
  const handler = await handlers(path)
26
29
  const method = req.method.toLowerCase()
27
30
  if (handler && handler[method]) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tenjuu99/blog",
3
- "version": "0.2.6",
3
+ "version": "0.2.8",
4
4
  "description": "blog template",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -1,13 +1,17 @@
1
1
  body {
2
2
  background: #fafafa;
3
- --container-max-width: 100%;
4
- --container-min-width: 100%;
5
- --container-width: 100%;
6
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;
7
11
  }
8
12
  main {
9
13
  height: 100%;
10
- margin: 0 auto;
14
+ /*margin: 0 auto;*/
11
15
  display: flex;
12
16
  flex-direction: row;
13
17
  justify-content: flex-start;
@@ -17,7 +21,7 @@ main.container {
17
21
  }
18
22
  .textareaAndPreview {
19
23
  display: flex;
20
- margin: 10px 0;
24
+ margin: 0;
21
25
  border: 1px solid #666;
22
26
  border-radius: 5px;
23
27
  height: 100%;
@@ -28,19 +32,23 @@ main.container {
28
32
  .editor {
29
33
  display: flex;
30
34
  flex-direction: column;
31
- padding: 15px 20px;
35
+ padding: 5px;
32
36
  justify-content:center;
33
37
  height: 100%;
34
38
  /* width: 100%; */
35
- margin: 0 auto;
39
+ margin: 0;
36
40
  position: relative;
41
+ width: 100%;
37
42
  left: 0;
38
43
  flex-basis: 100%;
39
- transition: flex-basis 0.3s;
40
44
  }
41
45
  .sidebar-close .editor {
42
- flex-basis: 90%;
43
- transition: flex-basis 0.3s;
46
+ /*flex-basis: 90%;*/
47
+ margin-left: 20px;
48
+ }
49
+ .editor-options {
50
+ display: flex;
51
+ justify-content: space-between;
44
52
  }
45
53
  #editorTextArea {
46
54
  resize: none;
@@ -58,7 +66,6 @@ main.container {
58
66
  }
59
67
  form select {
60
68
  padding: 5px;
61
- margin-top: 5px;
62
69
  border-radius: 5px;
63
70
  }
64
71
  #previewContent {
@@ -80,64 +87,55 @@ form select {
80
87
  width: 300px;
81
88
  overflow: hidden;
82
89
  left: 0;
83
- background: rgba(104, 117, 154);
90
+ background: rgb(192, 198, 217);
84
91
  height: 100%;
85
92
  padding: 0;
86
93
  overflow-y: hidden;
87
- transition: left 0.3s, flex-basis 0.3s;
88
94
  flex-basis: 300px;
89
95
  position: relative;
96
+ z-index: 3;
97
+ word-break: break-all;
90
98
  }
91
99
  .sidebar-close .sidebar {
92
100
  left: -290px;
93
- transition: left 0.3s, flex-basis 0.3s;
94
101
  flex-basis: 0;
95
102
  }
96
103
  .sidebar ul {
97
104
  padding: 0;
98
- margin: 0 0 0 20px;
99
- left: 0;
100
- transition: left 0.3s;
101
- min-width: 180px;
102
- max-width: 180px;
105
+ margin: 0;
103
106
  }
104
107
  .sidebar-close .sidebar ul {
105
108
  position: absolute;
106
109
  left: -290px;
107
110
  transition: left 0.3s;
108
111
  }
109
- @media screen and (min-width: 1100px) {
110
- }
111
- @media screen and (min-width: 1400px) {
112
- }
113
- @media screen and (max-width: 600px) {
114
- .sidebar {
115
- flex-basis: 80%;
116
- }
117
- .sidebar.close {
118
- flex-basis: 5%;
119
- }
120
- }
121
112
  .sidebar li {
122
113
  list-style: none;
114
+ padding-left: 20px;
123
115
  }
124
116
  .sidebar a {
125
- color: #fff;
117
+ color: #666;
118
+ text-decoration: none;
119
+ }
120
+ .sidebar li:hover {
121
+ background: rgba(104, 117, 154, .3);
126
122
  }
127
123
  .sidebar-toggle {
128
124
  cursor: pointer;
129
125
  width: 20px;
130
126
  height: 100%;
131
- background: rgba(104, 117, 154);
127
+ position: absolute;
128
+ right: 0;
132
129
  }
133
130
  .sidebar-close .sidebar-toggle {
134
131
  position: fixed;
135
132
  left: 0;
133
+ background: rgb(192, 198, 217);
136
134
  }
137
135
  .sidebar-toggle:hover:after {
138
136
  position: absolute;
139
137
  right: 0;
140
- content: ' ';
138
+ content: '';
141
139
  height: 100%;
142
140
  width: 20px;
143
141
  background: rgba(255, 255,255, 0.3);
@@ -177,6 +175,12 @@ form select {
177
175
  .sidebar-toggle {
178
176
  display: none;
179
177
  }
178
+ .sidebar {
179
+ flex-basis: 80%;
180
+ }
181
+ .sidebar.close {
182
+ flex-basis: 5%;
183
+ }
180
184
  }
181
185
  /**
182
186
  * hamburger
@@ -185,6 +189,17 @@ form select {
185
189
  display: none;
186
190
  }
187
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
+ }
188
203
  .hamburger-menu {
189
204
  display: block;
190
205
  }
@@ -208,7 +223,7 @@ form select {
208
223
  height: 3px;
209
224
  width: 25px;
210
225
  border-radius: 3px;
211
- background-color: #ffffff;
226
+ background-color: #666666;
212
227
  position: absolute;
213
228
  transition: transform 0.3s, background-color 0.3s;
214
229
  }
@@ -1,4 +1,119 @@
1
1
  import { allData } from '@tenjuu99/blog/lib/indexer.js'
2
+ import { replaceVariablesFilter } from "@tenjuu99/blog/lib/filter.js";
3
+ import config from '@tenjuu99/blog/lib/config.js'
4
+
5
+ export function readIndex (filter = null) {
6
+ const data = Object.entries(allData)
7
+ .sort((a, b) => new Date(b[1].published) - new Date(a[1].published))
8
+ return filter
9
+ ? data.filter(v => v[0].indexOf(filter) === 0).map(v => v[1])
10
+ : data.map(v => v[1])
11
+ }
12
+
13
+ export function dateFormat(dateString) {
14
+ const date = new Date(dateString)
15
+ return `${date.getFullYear()}年${date.getMonth() + 1}月${date.getDate()}日`
16
+ }
17
+
18
+ export function render(text, variables) {
19
+ return replaceVariablesFilter(text, variables)
20
+ }
21
+
22
+ export function getPageData(name) {
23
+ return allData[name]
24
+ }
25
+
26
+ let indexedItemsSorted = null
27
+ export function indexedItems() {
28
+ if (indexedItemsSorted) {
29
+ return indexedItemsSorted
30
+ }
31
+ const sorted = readIndex()
32
+ .filter(v => v.index && v.published != '1970-01-01')
33
+ .sort((a, b) => new Date(a.published) - new Date(b.published))
34
+ let prev, next
35
+ for (const item of sorted) {
36
+ if (prev) {
37
+ prev.next = {
38
+ name: item.name,
39
+ published: item.published,
40
+ url: item.url,
41
+ title: item.title,
42
+ }
43
+ item.prev = {
44
+ name: prev.name,
45
+ published: prev.published,
46
+ url: prev.url,
47
+ title: prev.title,
48
+ }
49
+ }
50
+ prev = item
51
+ }
52
+ indexedItemsSorted = sorted
53
+ return indexedItemsSorted
54
+ }
55
+
56
+ /**
57
+ * 配列を再帰的に順不同リストに変換する
58
+ * @param {Array|string} arrayOrText
59
+ * @returns {mixed}
60
+ */
61
+ export function arrayToList(arrayOrText) {
62
+ if (typeof arrayOrText === 'string') {
63
+ return `<li>${arrayOrText}</li>`
64
+ }
65
+ if (Array.isArray(arrayOrText)) {
66
+ let resultListText = '<ul>'
67
+ for (const item of arrayOrText) {
68
+ if (Array.isArray(item)) {
69
+ resultListText += `<li>${arrayToList(item)}</li>`
70
+ } else {
71
+ resultListText += `<li>${item}</li>`
72
+ }
73
+ }
74
+ resultListText += '</ul>'
75
+ arrayOrText = resultListText
76
+ }
77
+ return arrayOrText
78
+ }
79
+
80
+ export function renderIndex(pages, nodate = 'nodate', headingTag = 'h3') {
81
+ if (!pages) {
82
+ pages = readIndex()
83
+ }
84
+
85
+ const renderList = {}
86
+ for (const page of pages) {
87
+ if (page.index) {
88
+ const url = config.relative_path ? config.relative_path + page.url : page.url
89
+ if (page.published === '1970-01-01') {
90
+ if (!renderList[nodate]) {
91
+ renderList[nodate] = []
92
+ }
93
+ renderList[nodate].push(`<a href="${url}">${page.title}</a>`)
94
+ continue
95
+ }
96
+ const published = new Date(page.published)
97
+ const year = `${published.getFullYear()}年`
98
+ const date = `${published.getMonth() +1}月${published.getDate()}日`
99
+ if (!renderList[year]) {
100
+ renderList[year] = []
101
+ }
102
+ renderList[year].push(`<a href="${url}">${page.title}</a> (${date})`)
103
+ }
104
+ }
105
+
106
+ const resultText = []
107
+ for (const key in renderList) {
108
+ resultText.push(`<${headingTag}>${key}</${headingTag}>`)
109
+ if (Array.isArray(renderList[key])) {
110
+ resultText.push(arrayToList(renderList[key]))
111
+ } else {
112
+ resultText.push(`<p>${renderList[key]}</p>`)
113
+ }
114
+ }
115
+ return resultText.join('\n')
116
+ }
2
117
 
3
118
  export function additionalHelper() {
4
119
  return 'これは追加ヘルパーによって出力されているメッセージです。'
@@ -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 => {
@@ -92,15 +102,19 @@ const sidebarToggle = (e) => {
92
102
  toggle.addEventListener('click', (e) => {
93
103
  e.preventDefault()
94
104
  main.classList.toggle('sidebar-close')
105
+ localStorage.setItem('sidebar-is-open', !main.classList.contains('sidebar-close'))
95
106
  })
107
+ if (localStorage.getItem('sidebar-is-open') === 'true') {
108
+ main.classList.remove('sidebar-close')
109
+ } else {
110
+ main.classList.add('sidebar-close')
111
+ }
96
112
  const hamburger = document.querySelector('.hamburger-menu input[type="checkbox"]')
97
- console.log(hamburger)
98
113
  hamburger.addEventListener('change', (e) => {
99
114
  main.classList.toggle('sidebar-close')
100
115
  })
101
116
  }
102
117
  document.addEventListener('DOMContentLoaded', (event) => {
103
- console.log(event)
104
118
  onloadFunction(event)
105
119
  sidebarToggle(event)
106
120
  })
@@ -0,0 +1,8 @@
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 = `${url.pathname.replace('/', '')}のページを作成する`
8
+ }
@@ -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>
@@ -4,22 +4,12 @@
4
4
  <meta charset="UTF-8">
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
6
  <title>{{SITE_NAME}}</title>
7
- {include('template/css.html')}
8
- <link rel="stylesheet" href="${/css/editor.css<<editor.css}">
7
+ <link rel="stylesheet" href="${/css/editor.css<<reset.css,editor.css}">
9
8
  <script src="/js/editor.js" defer></script>
10
9
 
11
10
  </head>
12
11
  <body>
13
- <header>
14
- <p class="container">
15
- <a href="/">{{SITE_NAME}}/Editor</a>
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>
21
- </header>
22
- <main class="container sidebar-close">
12
+ <main class="container">
23
13
  <div class="sidebar">
24
14
  <ul>
25
15
  <script type="ssg">
@@ -31,32 +21,38 @@
31
21
  <div class="sidebar-toggle">&nbsp;</div>
32
22
  </div>
33
23
  <form action="/editor" class="editor" method="post" id="editor">
34
- <input id="inputFileName" name="inputFileName" type="text" value="" placeholder="sample.md">
35
- <select id="selectDataFile" name="selectDataFile">
36
- <option value="">新規作成</option>
37
- <script type="ssg">
38
- return helper.readIndex().map(p => {
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 => {
39
31
  return `<option value="${p.name}.${p.__filetype}">${p.url}.${p.__filetype}</option>`
40
32
  }).join("\n")
41
- </script>
42
- </select>
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>
43
42
  <div class="textareaAndPreview">
44
43
  <textarea id="editorTextArea" name="content" cols="30" rows="10">
45
- # H1
46
-
47
- ここにマークダウンを入力してください。
44
+ {{ MARKDOWN_NOT_PARSED }}
48
45
  </textarea>
49
46
  <div class="preview">
50
47
  <div id="previewContent"></div>
51
48
  </div>
52
49
  </div>
53
50
  <input type="hidden" name="token" value="{{TOKEN}}">
54
- <div>
55
- <input type="submit" value="preview" data-url="/preview">
56
- <input type="submit" value="save" data-url="/editor">
57
- <a href="/">戻る</a>
58
- </div>
59
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>
60
56
  </main>
61
57
  </body>
62
58
  </html>
package/helper/index.js DELETED
@@ -1,116 +0,0 @@
1
- import { allData } from "../lib/indexer.js";
2
- import { replaceVariablesFilter } from "../lib/filter.js";
3
- import config from '../lib/config.js'
4
-
5
- export function readIndex (filter = null) {
6
- const data = Object.entries(allData)
7
- .sort((a, b) => new Date(b[1].published) - new Date(a[1].published))
8
- return filter
9
- ? data.filter(v => v[0].indexOf(filter) === 0).map(v => v[1])
10
- : data.map(v => v[1])
11
- }
12
-
13
- export function dateFormat(dateString) {
14
- const date = new Date(dateString)
15
- return `${date.getFullYear()}年${date.getMonth() + 1}月${date.getDate()}日`
16
- }
17
-
18
- export function render(text, variables) {
19
- return replaceVariablesFilter(text, variables)
20
- }
21
-
22
- export function getPageData(name) {
23
- return allData[name]
24
- }
25
-
26
- let indexedItemsSorted = null
27
- export function indexedItems() {
28
- if (indexedItemsSorted) {
29
- return indexedItemsSorted
30
- }
31
- const sorted = readIndex()
32
- .filter(v => v.index && v.published != '1970-01-01')
33
- .sort((a, b) => new Date(a.published) - new Date(b.published))
34
- let prev, next
35
- for (const item of sorted) {
36
- if (prev) {
37
- prev.next = {
38
- name: item.name,
39
- published: item.published,
40
- url: item.url,
41
- title: item.title,
42
- }
43
- item.prev = {
44
- name: prev.name,
45
- published: prev.published,
46
- url: prev.url,
47
- title: prev.title,
48
- }
49
- }
50
- prev = item
51
- }
52
- indexedItemsSorted = sorted
53
- return indexedItemsSorted
54
- }
55
-
56
- /**
57
- * 配列を再帰的に順不同リストに変換する
58
- * @param {Array|string} arrayOrText
59
- * @returns {mixed}
60
- */
61
- export function arrayToList(arrayOrText) {
62
- if (typeof arrayOrText === 'string') {
63
- return `<li>${arrayOrText}</li>`
64
- }
65
- if (Array.isArray(arrayOrText)) {
66
- let resultListText = '<ul>'
67
- for (const item of arrayOrText) {
68
- if (Array.isArray(item)) {
69
- resultListText += `<li>${arrayToList(item)}</li>`
70
- } else {
71
- resultListText += `<li>${item}</li>`
72
- }
73
- }
74
- resultListText += '</ul>'
75
- arrayOrText = resultListText
76
- }
77
- return arrayOrText
78
- }
79
-
80
- export function renderIndex(pages, nodate = 'nodate', headingTag = 'h3') {
81
- if (!pages) {
82
- pages = readIndex()
83
- }
84
-
85
- const renderList = {}
86
- for (const page of pages) {
87
- if (page.index) {
88
- const url = config.relative_path ? config.relative_path + page.url : page.url
89
- if (page.published === '1970-01-01') {
90
- if (!renderList[nodate]) {
91
- renderList[nodate] = []
92
- }
93
- renderList[nodate].push(`<a href="${url}">${page.title}</a>`)
94
- continue
95
- }
96
- const published = new Date(page.published)
97
- const year = `${published.getFullYear()}年`
98
- const date = `${published.getMonth() +1}月${published.getDate()}日`
99
- if (!renderList[year]) {
100
- renderList[year] = []
101
- }
102
- renderList[year].push(`<a href="${url}">${page.title}</a> (${date})`)
103
- }
104
- }
105
-
106
- const resultText = []
107
- for (const key in renderList) {
108
- resultText.push(`<${headingTag}>${key}</${headingTag}>`)
109
- if (Array.isArray(renderList[key])) {
110
- resultText.push(arrayToList(renderList[key]))
111
- } else {
112
- resultText.push(`<p>${renderList[key]}</p>`)
113
- }
114
- }
115
- return resultText.join('\n')
116
- }