mm_statics 1.6.1 → 1.6.2

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/index.js CHANGED
@@ -3,29 +3,52 @@ const { EsToAmdConvert } = require('mm_es6_to_amd');
3
3
  const { parse } = require('@vue/compiler-sfc');
4
4
  const { compile } = require('@vue/compiler-dom');
5
5
  const prettier = require('prettier');
6
+ const { marked } = require('marked');
6
7
 
7
8
  /**
8
9
  * 静态文件处理类
9
10
  */
10
11
  class Static {
11
12
  static config = {
13
+ // 默认索引文件
12
14
  index: 'index.html',
15
+ // 默认缓存过期时间
13
16
  max_age: 7200,
14
- key_prefix: 'static:',
15
- cache: true,
17
+ // 静态文件缓存键前缀
18
+ prefix: 'static:',
19
+ // 缓存过期时间
16
20
  cache_age: 7200,
21
+ // 是否开启缓存
22
+ cache: true,
23
+ // 是否开启不可变缓存
17
24
  immutable: true,
25
+ // 是否隐藏静态文件
18
26
  hidden: false,
27
+ // 是否格式化静态文件内容
19
28
  format: true,
29
+ // 是否开启文件扩展名
20
30
  extensions: false,
31
+ // 是否开启Brotli压缩
21
32
  brotli: false,
33
+ // 是否压缩静态文件
22
34
  gzip: false,
35
+ // 静态文件根目录
23
36
  root: './static',
37
+ // 是否编译Vue文件为JS
24
38
  compile_vue: true,
39
+ // 是否编译Markdown文件为HTML
40
+ compile_md: true,
41
+ // 编译Markdown文件时,是否添加引入css和js文件
42
+ markdown_link: ['/css/common.css', '/css/markdown.css', '/js/markdown.js'],
43
+ // 需要转换的静态文件路径前缀
25
44
  path: '/src',
45
+ // 需要转换的静态文件扩展名
26
46
  files: ['.js', '.vue', '.html'],
47
+ // 是否转换ES6模块为AMD模块
27
48
  convert_amd: true,
49
+ // 是否开启文件监听
28
50
  watch: false,
51
+ // 监听的文件扩展名
29
52
  watch_files: ['.js', '.css', '.html', '.vue', '.json', '.md', '.txt', '.xml']
30
53
  };
31
54
 
@@ -371,7 +394,17 @@ Static.prototype._compileVue = async function (code) {
371
394
  */
372
395
  Static.prototype._sendFile = async function (ctx, path) {
373
396
  // koa-send会自动处理查询参数,直接传递路径
374
- await send(ctx, path, this.config);
397
+ const config = { ...this.config };
398
+
399
+ // 为markdown文件设置正确的MIME类型
400
+ if (path.endsWith('.md')) {
401
+ config.setHeaders = (res) => {
402
+ // 当代码走到_sendFile路径时,说明文件没有被编译,应该返回原始markdown类型
403
+ res.setHeader('Content-Type', 'text/plain; charset=utf-8');
404
+ };
405
+ }
406
+
407
+ await send(ctx, path, config);
375
408
  };
376
409
 
377
410
  /**
@@ -405,6 +438,93 @@ Static.prototype._runVue = async function (path) {
405
438
  return code;
406
439
  };
407
440
 
441
+ /**
442
+ * 从Markdown内容中提取第一个一级标题
443
+ * @param {string} text Markdown文本内容
444
+ * @returns {string|null} 提取的标题,未找到时返回null
445
+ */
446
+ Static.prototype._extractMarkdownTitle = function (text) {
447
+ if (!text || typeof text !== 'string') {
448
+ return null;
449
+ }
450
+
451
+ // 匹配一级标题格式:# 标题
452
+ var title_regex = /^#\s+(.+)$/m;
453
+ var match = text.match(title_regex);
454
+
455
+ if (match && match[1]) {
456
+ return match[1].trim();
457
+ }
458
+
459
+ return null;
460
+ };
461
+
462
+ /**
463
+ * 处理Markdown文件转换
464
+ * @param {string} path 文件路径
465
+ * @returns {string|null} 转换后的HTML内容
466
+ */
467
+ Static.prototype._runMarkdown = async function (path) {
468
+ let html = null;
469
+ let file = `.${path}`.fullname(this.config.root);
470
+ let text = file.loadText();
471
+
472
+ if (text) {
473
+ try {
474
+ // 使用marked将markdown转换为HTML
475
+ let markdown_html = marked.parse(text);
476
+
477
+ // 优先从Markdown内容中提取一级标题,后备使用文件名
478
+ var title_from_content = this._extractMarkdownTitle(text);
479
+ var title_from_file = path.split('/').pop().replace('.md', '');
480
+ var title = title_from_content || title_from_file;
481
+ // 构建外部资源链接
482
+ let links = '';
483
+ if (this.config.markdown_link && Array.isArray(this.config.markdown_link)) {
484
+ this.config.markdown_link.forEach(path => {
485
+ if (path.endsWith('.css')) {
486
+ links += ` <link rel="stylesheet" href="${path}">\n`;
487
+ } else if (path.endsWith('.js')) {
488
+ links += ` <script src="${path}"></script>\n`;
489
+ }
490
+ });
491
+ }
492
+
493
+ // 构建完整的HTML结构
494
+ html = `<!DOCTYPE html>
495
+ <html>
496
+ <head>
497
+ <meta charset="UTF-8">
498
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
499
+ <title>${title}</title>
500
+ ${links}
501
+ </head>
502
+ <body>
503
+ ${markdown_html}
504
+ </body>
505
+ </html>`;
506
+
507
+ // 如果启用了格式化,使用prettier格式化完整的HTML
508
+ if (this.config.format) {
509
+ try {
510
+ html = prettier.format(html, {
511
+ parser: 'html',
512
+ printWidth: 100,
513
+ tabWidth: 2
514
+ });
515
+ } catch (error) {
516
+ console.warn('HTML格式化失败,使用原始HTML:', error.message);
517
+ }
518
+ }
519
+ } catch (error) {
520
+ console.error('Markdown转换错误:', error);
521
+ return null;
522
+ }
523
+ }
524
+
525
+ return html;
526
+ };
527
+
408
528
  /**
409
529
  * 返回响应
410
530
  * @param {object} ctx Koa上下文对象
@@ -456,7 +576,7 @@ Static.prototype._initWatcher = function () {
456
576
  Static.prototype._handleFileChange = function (event, file_path) {
457
577
  // 构建缓存键(相对于静态目录的路径)
458
578
  const relative_path = file_path.replace(this.config.root, '').replace(/^[\\\/]/, '');
459
- const cache_key = this.config.key_prefix + relative_path;
579
+ const cache_key = this.config.prefix + relative_path;
460
580
 
461
581
  // 根据事件类型处理缓存
462
582
  switch (event) {
@@ -503,6 +623,14 @@ Static.prototype._getHeaders = function (file_type) {
503
623
  case 'html':
504
624
  headers['content-type'] = 'text/html; charset=utf-8';
505
625
  break;
626
+ case 'md':
627
+ if (this.config.compile_md) {
628
+ headers['content-type'] = 'text/html; charset=utf-8';
629
+ }
630
+ else {
631
+ headers['content-type'] = 'text/plain; charset=utf-8';
632
+ }
633
+ break;
506
634
  default:
507
635
  headers['content-type'] = 'text/plain; charset=utf-8';
508
636
  break;
@@ -517,7 +645,7 @@ Static.prototype._getHeaders = function (file_type) {
517
645
  */
518
646
  Static.prototype._setCache = async function (path, ret) {
519
647
  // 使用完整路径(包含查询参数)作为缓存键
520
- await this._cache.set(this.config.key_prefix + path, ret, this.config.cache_age);
648
+ await this._cache.set(this.config.prefix + path, ret, this.config.cache_age);
521
649
  };
522
650
 
523
651
  /**
@@ -552,7 +680,7 @@ Static.prototype._getType = function (path) {
552
680
  */
553
681
  Static.prototype._getCache = async function (path) {
554
682
  // 使用完整路径(包含查询参数)作为缓存键
555
- return await this._cache.get(this.config.key_prefix + path);
683
+ return await this._cache.get(this.config.prefix + path);
556
684
  };
557
685
 
558
686
  /**
@@ -560,7 +688,7 @@ Static.prototype._getCache = async function (path) {
560
688
  * @param {string} path 文件路径(包含查询参数)
561
689
  */
562
690
  Static.prototype._delCache = async function (path) {
563
- await this._cache.del(this.config.key_prefix + path);
691
+ await this._cache.del(this.config.prefix + path);
564
692
  };
565
693
 
566
694
  /**
@@ -597,7 +725,9 @@ Static.prototype._handleFileCompile = async function (path) {
597
725
  else if (compile_vue && file_type === 'vue') {
598
726
  return await this._runVue(path);
599
727
  }
600
-
728
+ else if (this.config.compile_md && file_type === 'md') {
729
+ return await this._runMarkdown(path);
730
+ }
601
731
  return null;
602
732
  };
603
733
 
@@ -610,6 +740,10 @@ Static.prototype._handleFileCompile = async function (path) {
610
740
  */
611
741
  Static.prototype._handleCompiledResp = async function (url, path, body, ctx) {
612
742
  let file_type = this._getType(path);
743
+ // 只有当启用了Markdown转换时,才将markdown文件类型设置为HTML
744
+ if (file_type === 'md' && this.config.compile_md) {
745
+ file_type = 'html';
746
+ }
613
747
  let headers = this._getHeaders(file_type);
614
748
  let ret = this._return(ctx, body, headers);
615
749
 
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "mm_statics",
3
- "version": "1.6.1",
3
+ "version": "1.6.2",
4
4
  "description": "这是超级美眉statics函数模块,用于web服务端statics缓存",
5
5
  "main": "index.js",
6
6
  "scripts": {
7
- "test": "node ./tests/index.js",
7
+ "test": "mocha tests/index.js",
8
8
  "tests": "mocha tests/*.js"
9
9
  },
10
10
  "repository": {
@@ -41,6 +41,7 @@
41
41
  "chokidar": "^5.0.0",
42
42
  "koa": "^3.1.1",
43
43
  "koa-send": "^5.0.1",
44
+ "marked": "^17.0.1",
44
45
  "mm_cache": "^1.4.8",
45
46
  "mm_es6_to_amd": "^1.4.7",
46
47
  "prettier": "^3.7.4"
package/static/test.txt DELETED
@@ -1 +0,0 @@
1
- This is a test static file for mm_statics module.