Commit 7aa039bd authored by 孙灵跃 leon's avatar 孙灵跃 leon

项目初始化搭建完成

parent b833cd0a
.DS_Store
node_modules/
dist/
lib/
npm-debug.log*
yarn-debug.log*
yarn-error.log*
/test/unit/coverage/
/test/e2e/reports/
selenium-debug.log
package-lock.json
yarn.lock*
bower_components/
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
# markdown-render
一个和编辑器配套的库,用于解析编辑器输出的内容,将markdown解析为html文本,支持自定义指令
一个和编辑器配套的库,用于解析编辑器输出的内容,将markdown解析为html文本和JSON的数据结构,支持自定义指令;
```
编辑器中解析自定义指令用的是 remark相关的库, remark-parse,remark-rehype,remark-directive,rehype-stringify因为需要对mdast和hast进行更仔细的操作
```
```
我们只采用 micromark 相关的库,micromark-extension-directive,micromark-extension-gfm
专注于markdown生成html
```
```
其中对 directive 的解析规则是相同的, remark也是借助于micromark完成的,markdown-it 也可以做; 不用markdown-it的原因是里面有大量的 remark-directive 指令相关,markdown-it只会产生token,没有ast的概念,自定义指令不属于 commonMark和gfm的语法, markdown-it词法解析的时候,可能会误判,<块状的独占一行,还是可以匹配出来, 行内的可能会和其他文本一起切成一个token,然后需要用正则去匹配,自己在重新切分生成token,比较麻烦> ,上面的库则天然支持解析,并且和编辑器配套
```
\ No newline at end of file
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.container{
display: flex;
height: 80vh;
overflow: auto;
gap: 10px;
}
</style>
</head>
<body>
<div class="container">
<div id="preview" style="flex:1; border-right: 1px solid #ccc;"></div>
</div>
<script type="module">
import renderer , {rendererToAst}from './lib/index.esm.js'
import results from './test.js'
const content = results.results.content;
console.log('resultsresults',rendererToAst(content))
const preview = document.getElementById('preview')
preview.innerHTML = renderer(content);
</script>
</body>
</html>
\ No newline at end of file
{
"name": "coopwire-markdown-render",
"version": "1.0.0",
"description": "一个和编辑器配套的库,用于解析编辑器输出的内容,将markdown解析为html文本,支持自定义指令",
"main": "lib/index.cjs.js",
"module": "lib/index.esm.js",
"browser": "lib/index.umd.js",
"types": "lib/type.d.js",
"dependencies": {
"highlight.js": "^11.11.1",
"mdast-util-directive": "^3.1.0",
"mdast-util-from-markdown": "^2.0.2",
"mdast-util-gfm": "^3.1.0",
"micromark": "^4.0.2",
"micromark-extension-directive": "^4.0.0",
"micromark-extension-gfm": "^3.0.0",
"rollup": "^4.35.0"
},
"devDependencies": {
"@rollup/plugin-node-resolve": "^16.0.1",
"@rollup/plugin-terser": "^0.4.4",
"rollup-plugin-copy": "^3.5.0",
"rollup-plugin-delete": "^3.0.1",
"rollup-plugin-typescript2": "^0.36.0",
"typescript": "^5.8.2"
},
"scripts": {
"build": "rollup --config"
},
"engine-strict": true,
"engines": {
"node": ">=21.6.1"
},
"repository": {
"type": "git",
"url": "ssh://git@gitlab.logwire.cn:13389/leon.sun/markdown-render.git"
},
"keywords": [],
"author": "",
"license": "ISC"
}
import terser from '@rollup/plugin-terser';
import deletePlugin from 'rollup-plugin-delete';
import typescript from 'rollup-plugin-typescript2';
import { nodeResolve } from '@rollup/plugin-node-resolve';
import copy from 'rollup-plugin-copy';
export default {
input: 'src/index.ts',
output: [
{
file: 'lib/index.cjs.js',
format: 'cjs'
},
{
file: 'lib/index.esm.js',
format: 'es'
},
{
file: 'lib/index.umd.js',
name:'CoopEditorRenderer',
format: 'umd'
}
],
plugins:[
deletePlugin({ targets: 'lib', hook: 'buildStart' }),
terser(),
nodeResolve(),
typescript(),
copy({
targets: [
{ src: 'type.d.ts', dest: 'lib' }
]
})
]
};
\ No newline at end of file
export default function (d){
console.log(d);
if (d.name !== 'column') return false
this.tag(`<div class='layout-column'`)
this.raw(d.content || '')
this.tag('</div>');
return true;
}
\ No newline at end of file
export default function (d){
console.log(d);
if (d.name !== 'drawio') return false;
const { page, oid } = d.attributes;
this.tag(`<div class='drawioContent'>`)
this.raw('drawo' + oid + '-' + page)
this.tag('</div>');
return true;
}
\ No newline at end of file
export default function (d){
console.log(d);
if (d.name !== 'layout') return false
const classAttrs = d.attributes.class || '1-1-1';
const style = classAttrs.split('-').map(frNum => `${frNum}fr`).join(' ');
this.tag(`<div style='display:grid;grid-template-columns: ${style}'>`)
this.raw(d.content || '')
this.tag('</div>');
return true;
}
\ No newline at end of file
export default function (d){
console.log(d);
if (d.name !== 'mention') return false;
const { type, oid } = d.attributes;
this.tag(`<div class='mentionContent'>`)
this.raw(type + oid)
this.tag('</div>');
return true;
}
\ No newline at end of file
export default function (d){
console.log(d);
if (d.name !== 'minimap') return false;
const { minimapId } = d.attributes;
this.tag(`<div class='mindmMapContent'>`)
this.raw('mindmap' + minimapId)
this.tag('</div>');
return true;
}
\ No newline at end of file
export default function (d){
console.log(d);
if (d.name !== 'example') return false
this.tag(`<div class='noteContent' style='color:red'>`)
this.raw(d.content || '')
this.tag('</div>');
return true;
}
\ No newline at end of file
export default function (d){
console.log(d);
if (d.name !== 'note') return false
this.tag(`<div class='noteContent' style='color:red'>`)
this.raw(d.content || '')
this.tag('</div>');
return true;
}
\ No newline at end of file
export default function (d){
console.log(d);
if (d.name !== 'tip') return false
this.tag(`<div class='noteContent' style='color:red'>`)
this.raw(d.content || '')
this.tag('</div>');
return true;
}
\ No newline at end of file
export default function (d){
console.log(d);
if (d.name !== 'warning') return false
this.tag(`<div class='noteContent' style='color:red'>`)
this.raw(d.content || '')
this.tag('</div>');
return true;
}
\ No newline at end of file
import tip from './extension-note/tip'
import example from './extension-note/example'
import warning from './extension-note/warning'
import note from './extension-note/note'
import layout from './extension-layout'
import column from './extension-column'
import mention from './extension-mention'
import drawio from './extension-drawio'
import minimap from './extension-mindmap'
import type { RendererOption } from '../../type'
export default (options:RendererOption) => {
return {
tip,
example,
warning,
note,
layout,
column,
mention,
drawio,
minimap
}
}
\ No newline at end of file
import { micromark } from 'micromark'
import { gfmHtml, gfm} from 'micromark-extension-gfm'
import { fromMarkdown } from 'mdast-util-from-markdown'
import { directive, directiveHtml } from 'micromark-extension-directive'
import {directiveFromMarkdown} from 'mdast-util-directive'
import {gfmFromMarkdown} from 'mdast-util-gfm'
import extension from './extension'
import type { RendererOption } from '../type'
const renderer = function(text,options:RendererOption){
const extensions = extension(options)
return micromark(text,{
allowDangerousHtml: true,
extensions: [
gfm(),
directive()
],
htmlExtensions: [
gfmHtml(),
directiveHtml(extensions)
]
})
}
export default renderer;
export const rendererToAst = (text) => {
const tree = fromMarkdown(text, {
extensions: [
gfm(),
directive()
],
mdastExtensions:[
gfmFromMarkdown(),
directiveFromMarkdown()
]
});
return tree
}
\ No newline at end of file
export default {
"code": 0,
"msg": "操作成功",
"traceId": "67d7f0dbde3cf10001859ea0",
"results": {
"id": "67cfb3cc3195292d20590c45",
"createType": "MAIN_EMPTY",
"pid": "5ede01b52f391b62cc0f5270",
"code": "1185",
"title": "pbwy0311-1",
"content": "| 34 | 3434 | 34 |\n| :- | :--- | :- |\n| 34 | 34 | 34 |\n| 34 | 34 | 34 |\n\n:::tip\n这是一个 *提示* 的note\n:::\n\n:::example\n这是一个例子的note\n:::\n\n::::layout{.1-1}\n:::column\n这是一个分栏第一个\n:::\n\n:::column\n这是一个分栏第二个\n:::\n::::\n\n:mention{type=\"user\" oid=\"0\"}\n\n:mention{type=\"attachment\" oid=\"67d7ebe86eee482856d14124\" fileName=\"议题-20250108135440.xlsx\"}\n\n:mention{type=\"requirement\" oid=\"652c8f6d752c467b8d063a24\"}\n\n:mention{type=\"flowchart\" oid=\"6554785c71164b7a4c1fb7f8\"}\n\n:mention{type=\"api\" oid=\"6612130da0460e1cede7d754\"}\n\n:mention{type=\"function\" oid=\"66c46431e1cb9c1627e39b00\" aid=\"5ede01b52f391b62cc0f5270\"}\n\n:mention{type=\"wiki\" oid=\"66de65ee416f43394b41a010\"}\n\n:mention{type=\"issue\" oid=\"67cfb1b1aefa7719525dcaee\"}\n\n\n\n::drawio{oid=\"67d7f0bac72dc75b30144032\" page=\"1\"}\n\n::minimap{minimapId=\"67d7f0cac72dc75b30144034\"}\n\n #*#67d7e7b60030ac7c211fd232",
"subList": [],
"relatedList": [],
"issuesOfEpic": [],
"insertUserId": "718580632296357888",
"insertUserName": "夏迎宾",
"insertUserImg": "64db8f6bb1ab247cb3ab397e",
"executorId": "718580632296357888",
"executorName": "夏迎宾",
"executorImg": "64db8f6bb1ab247cb3ab397e",
"status": "todo",
"type": "story",
"testUsers": [
"718580632296357888"
],
"attachmentIds": [
"67d7ebe86eee482856d14124#*#议题-20250108135440.xlsx"
],
"urgency": "3",
"labels": [],
"estimateScore": 0,
"estimatedWorkHours": 60,
"usedWorkHours": 0,
"estimateProcess": 0,
"sprints": [],
"insertDate": "2025-03-11 11:53:48",
"updateDate": "2025-03-17 17:52:22",
"feedbackIds": [],
"version": 6,
"followList": [
{
"id": "766340961813921792",
"accountName": "孙灵跃",
"email": "leon.sun@logwirecloud.com",
"hidden": false,
"expandCustomMenu": false,
"avatarId": "64d9f44bb1ab247cb3ab3863",
"cid": "0"
}
],
"dealResult": "completed",
"aid": "5ede01b52f391b62cc0f5270",
"releasePlanLogs": [],
"historyReleasePlans": [],
"bugAffectReleasePlans": [],
"enableScore": false,
"screenshots": [],
"isKeyIssue": false,
"gitStatus": "UNKNOWN",
"apiNum": 0,
"apiCaseNum": 0,
"apiCasePassNum": 0,
"issueRoleMap": {
"owner": [
"718580632296357888"
],
"executor": [
"718580632296357888"
],
"tester": [
"718580632296357888"
],
"examiner": [
"718580632296357888"
]
},
"testTaskEstimatedWorkHours": 0,
"testTaskEstimateProcess": 0
}
}
\ No newline at end of file
{
"compilerOptions": {
"target": "esnext",
"lib": [
"ESNext",
"ES2015",
"ES2016",
"ES2017",
"ES2018",
"ES2019",
"ES2020"
],
"paths": {
"@/*":["src/*"]
} ,
"allowJs": false,
"checkJs": false,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": false,
"forceConsistentCasingInFileNames": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"noImplicitAny": false,
"noEmit": true,
"strictFunctionTypes": false,
"downlevelIteration": true,
"noFallthroughCasesInSwitch": true,
"baseUrl": "./src"
},
"include": ["**/*.ts"],
"exclude": ["./node_modules","lib/types"]
}
\ No newline at end of file
export interface MentionOptions {
[id: string]: {
avatar?: string
id: string
icon: string
title: string
}
}
export interface RendererOption {
/** 渲染mention数据使用 */
mention: MentionOptions
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment