@rokelamen/md2html 0.1.1 → 0.1.3

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/dist/index.js CHANGED
@@ -1,50 +1,107 @@
1
- #!/usr/bin/env node
2
- import { program } from 'commander';
3
- import * as fs from 'fs';
1
+ const headerReg = /^\s*(#{1,6})(?:\s+|$)(.*)$/;
2
+
3
+ /**
4
+ * Since AST-based parsing is too complex and not
5
+ * suitable for a personal typescript learning project,
6
+ * So I just let my markdown rendering engine to
7
+ * receive a line and analysis which type it is,
8
+ * and then output the corresponding format(with tags).
9
+ * That means it's just a simple line-by-line parsing.
10
+ *
11
+ * Some special scenes still need to be handled carefully:
12
+ * plain text -> <p>plain text</p>
13
+ * need to consider whether there is a following empty line.
14
+ * Cause
15
+ * ```
16
+ * plain text 1
17
+ * plain text 2
18
+ * ```
19
+ * is one paragraph NOT two.
20
+ * The same happens with quote text:
21
+ * ```
22
+ * > quote text
23
+ * plain text
24
+ * ```
25
+ * is one paragraph as well.
26
+ */
4
27
  /* The main parse logic */
5
- function parse(content) {
6
- const transform = content.trim();
7
- return `<p>${transform}</p>`;
28
+ function parse(markdown) {
29
+ /* Split markdown content to many lines */
30
+ const crlfReg = /\r?\n/;
31
+ const lines = markdown.split(crlfReg);
32
+ // console.log(lines);
33
+ const mdBlocks = parseToBlocks(lines);
34
+ // console.log(mdBlocks);
35
+ const html = handleTags(mdBlocks);
36
+ return html;
8
37
  }
9
- // Import these from package.json in the future
10
- const name = 'md2html';
11
- const version = '0.1.1';
12
- const description = 'A simple tool to convert markdown content to html';
13
- /* Command-line tool logic */
14
- function command() {
15
- /* Set basic info */
16
- program
17
- .name(name)
18
- .version(version)
19
- .description(description);
20
- /* Config arguments info */
21
- program
22
- .option('-f, --file <path>', 'source file path')
23
- .argument('[input]', 'input content');
24
- /* Parse the cli options */
25
- program.parse(process.argv);
26
- /* Validation check */
27
- const options = program.opts();
28
- const input = program.args[0];
29
- const hasFile = typeof options.file === 'string';
30
- const hasInput = typeof input === 'string';
31
- // XOR validation
32
- if (hasFile === hasInput) {
33
- console.error('error: exactly one content source must be provided (either <input> or -f, --file).');
34
- process.exit(1);
35
- }
36
- /* Define one-source content */
37
- const content = hasFile
38
- ? (() => {
39
- try {
40
- return fs.readFileSync(options.file, 'utf-8');
41
- }
42
- catch {
43
- console.error(`error: failed to read file "${options.file}"`);
44
- process.exit(1);
38
+ /**
39
+ * Traverse lines to turn to blocks with different types
40
+ */
41
+ function parseToBlocks(lines) {
42
+ let lastTextQuoteBlock = { content: '', type: 'text' };
43
+ let pushed = true;
44
+ const mdBlocks = [];
45
+ for (const line of lines) {
46
+ // Empty line
47
+ if (!Boolean(line.trim())) {
48
+ if (!pushed) {
49
+ mdBlocks.push(lastTextQuoteBlock);
50
+ pushed = true;
45
51
  }
46
- })()
47
- : input;
48
- console.log(parse(content));
52
+ continue;
53
+ }
54
+ // Header
55
+ const headerM = line.match(headerReg);
56
+ if (headerM) {
57
+ mdBlocks.push({
58
+ type: 'header',
59
+ level: headerM[1].length,
60
+ content: headerM[2].trim()
61
+ });
62
+ continue;
63
+ }
64
+ // Fall back to plain text
65
+ if (!pushed) {
66
+ /* last line is also text */
67
+ lastTextQuoteBlock.content += ' ' + line.trim();
68
+ }
69
+ else {
70
+ lastTextQuoteBlock = {
71
+ type: 'text',
72
+ content: line.trim()
73
+ };
74
+ pushed = false;
75
+ }
76
+ }
77
+ // Avoid the last block is omitted
78
+ if (!pushed) {
79
+ mdBlocks.push(lastTextQuoteBlock);
80
+ pushed = true;
81
+ }
82
+ return mdBlocks;
83
+ }
84
+ /* traverse markdown content blocks and wrap text with tags at proper positions. */
85
+ function handleTags(mdBlocks) {
86
+ let result = '';
87
+ for (const block of mdBlocks) {
88
+ const type = block.type;
89
+ const content = tagSwtich(block);
90
+ switch (type) {
91
+ case "text":
92
+ result += `<p>${content}</p>` +
93
+ '\n';
94
+ break;
95
+ case "header":
96
+ result += `<h${block.level}>${content}</h${block.level}>` +
97
+ '\n';
98
+ break;
99
+ }
100
+ }
101
+ return result;
102
+ }
103
+ function tagSwtich(block) {
104
+ return block.content;
49
105
  }
50
- command();
106
+
107
+ export { parse };
package/package.json CHANGED
@@ -1,20 +1,28 @@
1
1
  {
2
2
  "name": "@rokelamen/md2html",
3
3
  "type": "module",
4
- "version": "0.1.1",
4
+ "version": "0.1.3",
5
5
  "description": "A simple tool to convert markdown content to html",
6
6
  "author": "rokelamen <rogerskelamen@gmail.com>",
7
7
  "license": "MIT",
8
- "main": "dist/index.js",
8
+ "main": "./dist/index.js",
9
9
  "bin": {
10
- "md2html": "./dist/index.js"
10
+ "md2html": "./bin/cli.cjs"
11
+ },
12
+ "exports": {
13
+ ".": {
14
+ "import": "./dist/index.js",
15
+ "types": "./dist/index.d.ts"
16
+ }
11
17
  },
12
18
  "scripts": {
13
- "clean": "rimraf dist",
14
- "build": "npm run clean && tsc",
19
+ "clean": "rimraf bin dist",
20
+ "build": "npm run clean && rollup -c rollup.config.ts --configPlugin typescript",
21
+ "test": "node bin/cli.cjs",
15
22
  "prepublishOnly": "npm run build"
16
23
  },
17
24
  "files": [
25
+ "bin",
18
26
  "dist"
19
27
  ],
20
28
  "keywords": [
@@ -23,12 +31,16 @@
23
31
  "md2html"
24
32
  ],
25
33
  "devDependencies": {
34
+ "@rollup/plugin-commonjs": "^29.0.0",
35
+ "@rollup/plugin-json": "^6.1.0",
36
+ "@rollup/plugin-node-resolve": "^16.0.3",
37
+ "@rollup/plugin-typescript": "^12.3.0",
26
38
  "@types/commander": "^2.12.0",
27
39
  "@types/node": "^25.0.3",
40
+ "commander": "^14.0.2",
28
41
  "rimraf": "^6.1.2",
42
+ "rollup": "^4.54.0",
43
+ "tslib": "^2.8.1",
29
44
  "typescript": "^5.9.3"
30
- },
31
- "dependencies": {
32
- "commander": "^14.0.2"
33
45
  }
34
46
  }