@kobalab/liulian 0.9.0 → 1.0.1

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/ChangeLog.md CHANGED
@@ -1,3 +1,17 @@
1
+ ### v1.0.1 / 2022-04-10
2
+
3
+ - paiga モジュールのMサイズの指定の誤りを修正
4
+
5
+ # v1.0.0 / 2022-04-09
6
+
7
+ - 正式バージョンリリース
8
+ - #6 Markdown記法に対応した
9
+ - JavaScriptを編集可能にした
10
+
11
+ ### v0.9.1 / 2022-04-06
12
+
13
+ - paiga モジュールに空文字列を指定した場合に異常終了するバグを修正
14
+
1
15
  ## v0.9.0 / 2022-04-03
2
16
 
3
17
  - import モジュールで外部モジュールをインポートできるようにした
package/css/liulian.css CHANGED
@@ -333,6 +333,13 @@ input[type="submit"] {
333
333
  color: red;
334
334
  }
335
335
 
336
+ .footnotes {
337
+ font-size: 90%;
338
+ }
339
+ .footnotes li p {
340
+ margin: 0.2em auto;
341
+ }
342
+
336
343
  .hljs-comment,
337
344
  .hljs-quote {
338
345
  color: #a0a1a7;
@@ -97,7 +97,7 @@ module.exports = class Folder extends File {
97
97
  for (let file of this._r.files.sort(cmp(s))) {
98
98
 
99
99
  if (req.cmd != 'edit'
100
- && file.name.match(/^(?:README|HEAD|TAIL)$/)) continue;
100
+ && file.name.match(/^(?:README|HEAD|TAIL)(?:\.md)?$/)) continue;
101
101
 
102
102
  let name = file.name + (file.type ? '' : '/');
103
103
  let link = encodeURIComponent(file.name) + (file.type ? '' : '/')
package/lib/html/index.js CHANGED
@@ -30,8 +30,8 @@ module.exports = class HTML {
30
30
  }
31
31
 
32
32
  title(title) {
33
- if (title) this._.title = title;
34
- else return this._.title;
33
+ if (title != null) this._.title = title;
34
+ else return this._.title;
35
35
  return this;
36
36
  }
37
37
 
@@ -68,8 +68,6 @@ module.exports = class HTML {
68
68
  _head() {
69
69
  const req = this._req;
70
70
 
71
- if (! this._.stylesheet.length)
72
- this._.stylesheet.push({url: DEFAULT_STYLE});
73
71
  const stylesheet = this._.stylesheet.map(opt=>
74
72
  '<link rel="stylesheet" type="text/css" '
75
73
  + `href="${cdata(fixpath(opt.url, req.baseUrl))}"`
@@ -151,7 +149,8 @@ module.exports = class HTML {
151
149
  + `</div>\n`;
152
150
  }
153
151
 
154
- stringify(content = '') {
152
+ stringify(content = '', needDefaultStyle = ! this._.stylesheet.length) {
153
+ if (needDefaultStyle) this._.stylesheet.push({url: DEFAULT_STYLE});
155
154
  return '<!DOCTYPE html>\n'
156
155
  + `<html lang="${cdata(this.lang())}">\n`
157
156
  + this._head()
@@ -49,7 +49,7 @@ function markup(paistr, w, h) {
49
49
  let url, v = 0;
50
50
  let html = '<span class="l-mod-paiga" style="white-space:pre;">';
51
51
 
52
- for (let pai of paistr.match(/[mpsz](?:\d+[\-\=]?)+|[ _]|.+/g)) {
52
+ for (let pai of paistr.match(/[mpsz](?:\d+[\-\=]?)+|[ _]|.+/g)||[]) {
53
53
 
54
54
  if (pai == ' ') {
55
55
  html += ' ';
@@ -114,7 +114,7 @@ module.exports = class Paiga {
114
114
  let w = 24, h = 34;
115
115
  if (! param) { w = 24; h = 34 }
116
116
  else if (param == 'L') { w = 24; h = 34 }
117
- else if (param == 'M') { w = 19; h = 24 }
117
+ else if (param == 'M') { w = 19; h = 26 }
118
118
  else if (param == 'S') { w = 16; h = 23 }
119
119
  else if (param.match(/^\d+x\d+$/)) {
120
120
  [ w, h ] = param.split(/x/);
@@ -7,6 +7,7 @@ const fs = require('fs').promises;
7
7
  const { join } = require('path');
8
8
  const HTML = require('../html/folder');
9
9
  const parse = require('../text/liulian');
10
+ const md = require('../text/markdown');
10
11
 
11
12
  const File = require('./file');
12
13
 
@@ -39,7 +40,7 @@ module.exports = class Folder extends File {
39
40
  catch(err) {}
40
41
  }
41
42
  if (this._req.cmd != 'edit') {
42
- for (let ext of ['', '.html', '.htm']) {
43
+ for (let ext of ['', '.md', '.html', '.htm']) {
43
44
  let index = this._files.find(f=>f.name == 'index' + ext);
44
45
  if (index) return index.open();
45
46
  }
@@ -99,11 +100,19 @@ module.exports = class Folder extends File {
99
100
  res.sendText(new HTML(this).edit());
100
101
  }
101
102
  else {
102
- let readme = this._files.find(f=>f.name == 'README');
103
+ let readme;
104
+ for (let file of ['README','README.md']) {
105
+ readme = this._files.find(f=>f.name == file);
106
+ if (readme) break;
107
+ }
103
108
  if (readme) {
104
109
  await readme.open();
105
110
  readme._html = new HTML(this);
106
- res.sendText(readme._html.folder(await parse(readme)));
111
+ res.sendText(readme._html.folder(
112
+ readme.type == 'text/x-liulian'
113
+ ? await parse(readme)
114
+ : md.render(readme._text)
115
+ ));
107
116
  }
108
117
  else if (this._req.user) {
109
118
  res.sendText(new HTML(this).folder());
@@ -11,6 +11,7 @@ const File = require('./file');
11
11
  const Folder = require('./folder');
12
12
  const Text = require('./text');
13
13
  const LiuLian = require('./liulian');
14
+ const Markdown = require('./markdown');
14
15
 
15
16
  async function resource(req, file) {
16
17
  let location;
@@ -35,6 +36,12 @@ async function resource(req, file) {
35
36
  else if (! basename(path).match(/\./))
36
37
  return new LiuLian(req, path, stat,
37
38
  location, resource);
39
+ else if (mime.getType(path) == 'text/markdown')
40
+ return new Markdown (req, path, stat,
41
+ location, resource);
42
+ else if (mime.getType(path) == 'application/javascript')
43
+ return new Text (req, path, stat,
44
+ location, resource);
38
45
  else if ((mime.getType(path)||'').match(/^text\//))
39
46
  return new Text(req, path, stat,
40
47
  location, resource);
@@ -18,44 +18,18 @@ module.exports = class LiuLian extends Text {
18
18
  script(script) { this._html.script(script) }
19
19
  meta(attr) { this._html.meta(attr) }
20
20
 
21
- async _seekToParent(filename) {
22
- let pathDir = this._req.pathDir;
23
- while (pathDir) {
24
- try {
25
- const r = await this.openFile(this._req, pathDir + filename);
26
- await r.open();
27
- return r.text;
28
- }
29
- catch(e) {
30
- pathDir = pathDir.replace(/[^\/]*\/$/,'');
31
- }
32
- }
33
- return '';
34
- }
35
-
36
21
  async update() {
37
22
  await super.update();
38
23
  if (this._req.param('text')) this._redirect = [303, this.name];
39
24
  }
40
25
 
41
- async send(res) {
42
- if (this._req.cmd == 'edit') {
43
- res.sendText(new HTML(this).edit());
44
- }
45
- else if (this._req.cmd == 'log') {
46
- res.sendText(new HTML(this).log());
47
- }
48
- else if (this._req.cmd == 'diff') {
49
- res.sendText(new HTML(this).diff());
50
- }
51
- else {
52
- this._text = (this.name != 'HEAD'
53
- ? await this._seekToParent('HEAD') + '\n' : '')
54
- + this._text + '\n'
55
- + (this.name != 'TAIL'
56
- ? await this._seekToParent('TAIL') : '');
57
- this._html = new HTML(this);
58
- res.sendText(this._html.stringify(await parse(this)));
59
- }
26
+ async _send(res) {
27
+ this._text = (this.name != 'HEAD'
28
+ ? await this._seekToParent('HEAD') + '\n' : '')
29
+ + this._text + '\n'
30
+ + (this.name != 'TAIL'
31
+ ? await this._seekToParent('TAIL') : '');
32
+ this._html = new HTML(this);
33
+ res.sendText(this._html.stringify(await parse(this)));
60
34
  }
61
35
  }
@@ -0,0 +1,33 @@
1
+ /*
2
+ * resource/markdown
3
+ */
4
+ "use strict";
5
+
6
+ const { strip } = require('../util/html-escape');
7
+
8
+ const HTML = require('../html/text');
9
+ const Text = require('./text');
10
+ const md = require('../text/markdown');
11
+
12
+ module.exports = class Markdown extends Text {
13
+
14
+ async update() {
15
+ await super.update();
16
+ if (this._req.param('text')) this._redirect = [303, this.name];
17
+ }
18
+
19
+ async _send(res) {
20
+ this._text = (this.name != 'HEAD.md'
21
+ ? await this._seekToParent('HEAD.md') + '\n' : '')
22
+ + this._text + '\n'
23
+ + (this.name != 'TAIL.md'
24
+ ? await this._seekToParent('TAIL.md') : '');
25
+ let html = md.render(this._text);
26
+ let title = strip((html.match(/<title>(.*?)<\/title>/i)||
27
+ html.match(/<h1>(.*?)<\/h1>/i)||[])[1]);
28
+ let style = (html.match(/<link\s?.*?>/ig)||[])
29
+ .filter(tag=>tag.match(/\srel="stylesheet"/i));
30
+ this._html = new HTML(this);
31
+ res.sendText(this._html.title(title).stringify(html, ! style.length));
32
+ }
33
+ }
@@ -13,6 +13,21 @@ module.exports = class Text extends File {
13
13
  get text() { return this._text }
14
14
  get diff() { return this._diff }
15
15
 
16
+ async _seekToParent(filename) {
17
+ let pathDir = this._req.pathDir;
18
+ while (pathDir) {
19
+ try {
20
+ const r = await this.openFile(this._req, pathDir + filename);
21
+ await r.open();
22
+ return r.text;
23
+ }
24
+ catch(e) {
25
+ pathDir = pathDir.replace(/[^\/]*\/$/,'');
26
+ }
27
+ }
28
+ return '';
29
+ }
30
+
16
31
  async open() {
17
32
  await super.open();
18
33
  if (this._backup && this._req.cmd == 'diff') {
@@ -57,6 +72,10 @@ module.exports = class Text extends File {
57
72
  if (this._req.cmd == 'edit') res.sendText(new HTML(this).edit());
58
73
  else if (this._req.cmd == 'log') res.sendText(new HTML(this).log());
59
74
  else if (this._req.cmd == 'diff') res.sendText(new HTML(this).diff());
60
- else res.sendFile(this._path, this.type);
75
+ else this._send(res);
76
+ }
77
+
78
+ _send(res) {
79
+ res.sendFile(this._path, this.type);
61
80
  }
62
81
  }
@@ -0,0 +1,25 @@
1
+ /*
2
+ * text/markdown
3
+ */
4
+ "use strict";
5
+
6
+ const hljs = require('highlight.js');
7
+
8
+ module.exports = require('markdown-it')({
9
+ html: true,
10
+ linkify: true,
11
+ highlight: function(str, lang) {
12
+ const error = console.error; console.error = ()=>{};
13
+ let html = '';
14
+ if (lang) {
15
+ try {
16
+ html = hljs.highlight(lang, str).value;
17
+ }
18
+ catch(err) {
19
+ html = hljs.highlightAuto(str).value;
20
+ }
21
+ }
22
+ console.error = error;
23
+ return html;
24
+ }
25
+ }).use(require('markdown-it-footnote'));
@@ -15,8 +15,13 @@ function cdata(str = '') {
15
15
 
16
16
  const cref = replacer(cref_pt, null, cdata);
17
17
 
18
+ function getAlt(img) {
19
+ return cref((img.match(/\salt="(.*?)"/)||[])[1]);
20
+ }
21
+
18
22
  function strip(html = '') {
19
- return html.replace(/<.*?>/g, '')
23
+ return html.replace(/<img\s?.*?>/g, getAlt)
24
+ .replace(/<.*?>/g, '')
20
25
  .replace(/&gt;/g, '>')
21
26
  .replace(/&lt;/g, '<')
22
27
  .replace(/&quot;/g,'"')
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kobalab/liulian",
3
- "version": "0.9.0",
3
+ "version": "1.0.1",
4
4
  "description": "Node.jsで動作するWebサイト作成ツール",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -34,6 +34,8 @@
34
34
  "express": "^4.17.1",
35
35
  "express-session": "^1.17.1",
36
36
  "highlight.js": "^10.4.1",
37
+ "markdown-it": "^12.3.2",
38
+ "markdown-it-footnote": "^3.0.3",
37
39
  "mime": "^2.4.6",
38
40
  "multer": "^1.4.2",
39
41
  "passport": "^0.4.1",