@isdk/mdast-plus 0.1.2 → 0.2.0
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/README.cn.md +69 -22
- package/README.md +69 -22
- package/dist/index.d.mts +564 -199
- package/dist/index.d.ts +564 -199
- package/dist/index.js +1 -1
- package/dist/index.mjs +1 -1
- package/docs/README.md +69 -22
- package/docs/_media/CONTRIBUTING.md +53 -24
- package/docs/_media/README.cn.md +69 -22
- package/docs/classes/MdastBasePipeline.md +416 -0
- package/docs/classes/MdastPipeline.md +611 -0
- package/docs/enumerations/PipelineStage.md +62 -0
- package/docs/functions/astCompiler.md +25 -0
- package/docs/functions/jsonParser.md +24 -0
- package/docs/functions/mdast.md +4 -4
- package/docs/globals.md +17 -10
- package/docs/interfaces/MdastDataOrigin.md +8 -8
- package/docs/interfaces/MdastFormat.md +71 -0
- package/docs/interfaces/MdastMark.md +4 -4
- package/docs/interfaces/MdastPlugin.md +57 -25
- package/docs/interfaces/MdastSub.md +4 -4
- package/docs/interfaces/MdastSup.md +4 -4
- package/docs/interfaces/ReadabilityOptions.md +33 -0
- package/docs/type-aliases/PipelineStageName.md +13 -0
- package/docs/variables/DefaultPipelineStage.md +13 -0
- package/docs/variables/astFormat.md +15 -0
- package/docs/variables/htmlFormat.md +6 -4
- package/docs/variables/htmlReadability.md +13 -0
- package/docs/variables/htmlReadabilityPlugin.md +27 -0
- package/docs/variables/htmlReadabilityPlugins.md +13 -0
- package/docs/variables/markdownFormat.md +6 -4
- package/docs/variables/restoreReadabilityMetaPlugin.md +49 -0
- package/package.json +18 -9
- package/docs/classes/FluentProcessor.md +0 -210
- package/docs/functions/htmlStringify.md +0 -23
- package/docs/functions/markdownCommon.md +0 -23
- package/docs/interfaces/ConvertResult.md +0 -39
- package/docs/interfaces/MdastAsset.md +0 -41
- package/docs/interfaces/MdastFormatDefinition.md +0 -51
- package/docs/interfaces/MdastReader.md +0 -41
- package/docs/interfaces/MdastTransformer.md +0 -33
- package/docs/interfaces/MdastWriter.md +0 -47
- package/docs/type-aliases/Stage.md +0 -13
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var t,e=Object.create,r=Object.defineProperty,i=Object.getOwnPropertyDescriptor,n=Object.getOwnPropertyNames,s=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(t,e,s,o)=>{if(e&&"object"==typeof e||"function"==typeof e)for(let u of n(e))a.call(t,u)||u===s||r(t,u,{get:()=>e[u],enumerable:!(o=i(e,u))||o.enumerable});return t},u=(t,i,n)=>(n=null!=t?e(s(t)):{},o(!i&&t&&t.__esModule?n:r(n,"default",{value:t,enumerable:!0}),t)),c={};((t,e)=>{for(var i in e)r(t,i,{get:e[i],enumerable:!0})})(c,{FluentProcessor:()=>P,htmlFormat:()=>F,htmlStringify:()=>D,markdownCommon:()=>q,markdownFormat:()=>z,mdast:()=>$}),module.exports=(t=c,o(r({},"__esModule",{value:!0}),t));var l=require("unified"),m=u(require("remark-parse")),h=u(require("remark-stringify")),f=u(require("remark-gfm")),p=u(require("remark-directive")),d=u(require("remark-math")),y=u(require("remark-frontmatter")),v=require("unist-util-visit");function g(t,e){return{type:t,children:e,data:{hName:t}}}var w={mark:(t,e)=>{const r={type:"mark",children:t.all(e)};return t.patch(e,r),r},sub:(t,e)=>{const r={type:"sub",children:t.all(e)};return t.patch(e,r),r},sup:(t,e)=>{const r={type:"sup",children:t.all(e)};return t.patch(e,r),r}},b={mark:(t,e,r)=>"=="+r.containerPhrasing(t,{before:"==",after:"=="})+"==",sub:(t,e,r)=>"~"+r.containerPhrasing(t,{before:"~",after:"~"})+"~",sup:(t,e,r)=>"^"+r.containerPhrasing(t,{before:"^",after:"^"})+"^"},k={name:"normalize-inline-styles",stage:"normalize",transform:t=>{!function(t){(0,v.visit)(t,"text",(t,e,r)=>{if(!r||void 0===e)return;const i=t.value;let n=0;const s=[];let a=!1;const o=/(==[^=]+==|~[^~]+~|\^[^^]+\^)/g;let u;for(;null!==(u=o.exec(i));){a=!0;const t=u[0],e=u.index;e>n&&s.push({type:"text",value:i.slice(n,e)});let r="mark",c="";t.startsWith("==")?(r="mark",c=t.slice(2,-2)):t.startsWith("~")?(r="sub",c=t.slice(1,-1)):t.startsWith("^")&&(r="sup",c=t.slice(1,-1)),s.push(g(r,[{type:"text",value:c}])),n=o.lastIndex}return a?(n<i.length&&s.push({type:"text",value:i.slice(n)}),r.children.splice(e,1,...s),e+s.length):void 0})}(t)}};function q(){const t=this.data();var e,r;r={handlers:b},t[e="toMarkdownExtensions"]?t[e].push(r):t[e]=[r],this.use(f.default,{singleTilde:!1}).use(p.default).use(d.default).use(y.default,["yaml","toml"])}var z={parse:t=>t.use(m.default).use(q),stringify:t=>t.use(h.default).use(q)},x=u(require("rehype-parse")),S=u(require("rehype-remark")),j=u(require("remark-rehype")),O=u(require("rehype-sanitize")),N=u(require("rehype-stringify"));function D(){this.use(j.default).use(O.default,{...O.defaultSchema,tagNames:[...O.defaultSchema.tagNames||[],"mark","sub","sup"],attributes:{...O.defaultSchema.attributes,"*":[...O.defaultSchema.attributes?.["*"]||[],"className","id","style"],td:[...O.defaultSchema.attributes?.td||[],"rowSpan","colSpan","rowspan","colspan"],th:[...O.defaultSchema.attributes?.th||[],"rowSpan","colSpan","rowspan","colspan"],img:[...O.defaultSchema.attributes?.img||[],"width","height"]}}).use(N.default)}var F={parse:t=>t.use(x.default).use(S.default,{handlers:w}),stringify:t=>t.use(D)},M=require("unist-util-visit"),T={error:"danger",warn:"warning",success:"tip",important:"important",caution:"caution",note:"note"},C={name:"normalize-directive",stage:"normalize",order:10,transform:async t=>{(0,M.visit)(t,["containerDirective","leafDirective","textDirective"],t=>{const e=t,r=e.name.toLowerCase();if(e.name=T[r]||r,e.children&&e.children.length>0){const t=e.children[0];if(t.data?.directiveLabel||"directiveLabel"===t.type){const r=t;let i="";(0,M.visit)(r,"text",t=>{i+=t.value}),i&&!e.attributes?.title&&(e.attributes=e.attributes||{},e.attributes.title=i.trim()),e.children.shift()}}e.attributes?.title&&(e.attributes.title=String(e.attributes.title).trim()),e.data=e.data||{},e.data.hName=e.data.hName||("containerDirective"===e.type?"div":"span"),e.data.hProperties={...e.data.hProperties||{},...e.attributes,className:[e.name,e.data.hProperties?.className].filter(Boolean).join(" ")}})}},I=require("unist-util-visit"),L={name:"normalize-table-span",stage:"normalize",order:20,transform:async t=>{(0,I.visit)(t,"tableCell",t=>{if(t.data){const{rowspan:e,colspan:r}=t.data;t.data.hProperties=t.data.hProperties||{},void 0!==e&&(t.data.hProperties.rowSpan=e,delete t.data.rowspan),void 0!==r&&(t.data.hProperties.colSpan=r,delete t.data.colspan)}})}},_=require("unist-util-visit"),A=require("shell-quote");var B={name:"extract-code-meta",stage:"normalize",order:30,transform:async t=>{(0,_.visit)(t,"code",t=>{if(t.meta){const e=function(t){const e={},r=(0,A.parse)(t);for(const t of r)if("string"==typeof t){const r=t.split("=",2);2===r.length?e[r[0]]=r[1]:e[t]="true"}return e}(t.meta),r=t.data=t.data||{};e.title&&(r.title=e.title),e.filename&&(r.filename=e.filename),r.kv={...r.kv||{},...e}}})}},E=require("unist-util-visit"),H={name:"image-size",stage:"normalize",order:40,transform:async t=>{(0,E.visit)(t,"image",t=>{const e=t.data=t.data||{},r=e.hProperties=e.hProperties||{},i=/[#?&](?:width=([0-9]+))?(?:&?height=([0-9]+))?(?:=([0-9]+)x([0-9]+))?$/,n=t.url.match(i);if(n){const e=n[1]||n[3],s=n[2]||n[4];e&&!r.width&&(r.width=parseInt(e,10)),s&&!r.height&&(r.height=parseInt(s,10)),t.url=t.url.replace(i,"")}e.width&&!r.width&&(r.width=e.width),e.height&&!r.height&&(r.height=e.height)})}},J=class t{constructor(t){this.inputFormat="markdown",this.plugins=[],this.globalData={},this.input=t,this.processor=(0,l.unified)(),this.use(C),this.use(L),this.use(B),this.use(H),this.use(k)}static registerFormat(e,r){t.formats[e.toLowerCase()]=r}from(t){return this.inputFormat=t.toLowerCase(),this}use(t){return this.plugins.push(t),this}data(t){return this.globalData={...this.globalData,...t},this}async to(e){e=e.toLowerCase();const r=t.formats[this.inputFormat];r?.parse&&r.parse(this.processor);let i="string"==typeof this.input?this.processor.parse(this.input):this.input;i=await this.processor.run(i),i.data={...i.data,...this.globalData};const n=[...this.plugins].sort((t,e)=>{const r={normalize:0,compile:1,finalize:2},i=t.stage||"normalize",n=e.stage||"normalize";return i!==n?r[i]-r[n]:(t.order||0)-(e.order||0)});for(const t of n)await t.transform(i,this.processor);const s=(0,l.unified)().data("settings",this.processor.data("settings")),a=t.formats[e];a?.stringify&&a.stringify(s),"markdown"!==e||a||z.stringify(s);const o=await s.run(i),u=s.stringify(o),c=[];return i.data&&i.data.assets&&c.push(...i.data.assets),{content:u,assets:c}}async toMarkdown(){return(await this.to("markdown")).content}async toHTML(){return(await this.to("html")).content}async toAST(){return(await this.to("ast")).content}};J.formats={markdown:z,html:F,ast:{parse:t=>{t.Parser=t=>JSON.parse(t)},stringify:t=>{t.Compiler=t=>t}}};var P=J;function $(t){return new P(t)}
|
|
1
|
+
"use strict";var t,e=Object.create,r=Object.defineProperty,i=Object.getOwnPropertyDescriptor,n=Object.getOwnPropertyNames,s=Object.getPrototypeOf,o=Object.prototype.hasOwnProperty,a=(t,e,s,a)=>{if(e&&"object"==typeof e||"function"==typeof e)for(let u of n(e))o.call(t,u)||u===s||r(t,u,{get:()=>e[u],enumerable:!(a=i(e,u))||a.enumerable});return t},u=(t,i,n)=>(n=null!=t?e(s(t)):{},a(!i&&t&&t.__esModule?n:r(n,"default",{value:t,enumerable:!0}),t)),l={};((t,e)=>{for(var i in e)r(t,i,{get:e[i],enumerable:!0})})(l,{DefaultPipelineStage:()=>p,MdastBasePipeline:()=>Q,MdastPipeline:()=>U,PipelineStage:()=>c,astCompiler:()=>V,astFormat:()=>G,htmlFormat:()=>C,htmlReadability:()=>Y,htmlReadabilityPlugin:()=>Z,htmlReadabilityPlugins:()=>et,jsonParser:()=>_,markdownFormat:()=>R,mdast:()=>W,restoreReadabilityMetaPlugin:()=>tt}),module.exports=(t=l,a(r({},"__esModule",{value:!0}),t));var c=(t=>(t[t.parse=0]="parse",t[t.normalize=100]="normalize",t[t.compile=200]="compile",t[t.finalize=300]="finalize",t[t.stringify=400]="stringify",t))(c||{}),p=200,f=require("unified"),h=require("vfile"),m=u(require("remark-parse")),g=u(require("remark-stringify")),d=u(require("remark-gfm")),y=u(require("remark-directive")),b=u(require("remark-math")),w=u(require("remark-frontmatter")),v=require("unist-util-visit");function k(t,e){return{type:t,children:e,data:{hName:t}}}var q={mark:(t,e,r)=>"=="+r.containerPhrasing(t,{before:"==",after:"=="})+"==",sub:(t,e,r)=>"~"+r.containerPhrasing(t,{before:"~",after:"~"})+"~",sup:(t,e,r)=>"^"+r.containerPhrasing(t,{before:"^",after:"^"})+"^"},j={plugin:()=>t=>{!function(t){(0,v.visit)(t,"text",(t,e,r)=>{if(!r||void 0===e)return;const i=t.value;let n=0;const s=[];let o=!1;const a=/(==[^=]+==|~[^~]+~|\^[^^]+\^)/g;let u;for(;null!==(u=a.exec(i));){o=!0;const t=u[0],e=u.index;e>n&&s.push({type:"text",value:i.slice(n,e)});let r="mark",l="";t.startsWith("==")?(r="mark",l=t.slice(2,-2)):t.startsWith("~")?(r="sub",l=t.slice(1,-1)):t.startsWith("^")&&(r="sup",l=t.slice(1,-1)),s.push(k(r,[{type:"text",value:l}])),n=a.lastIndex}return o?(n<i.length&&s.push({type:"text",value:i.slice(n)}),r.children.splice(e,1,...s),e+s.length):void 0})}(t)},stage:100},M=require("unist-util-visit"),P={error:"danger",warn:"warning",success:"tip",important:"important",caution:"caution",note:"note"},x={plugin:()=>async t=>{(0,M.visit)(t,["containerDirective","leafDirective","textDirective"],t=>{const e=t,r=e.name.toLowerCase();if(e.name=P[r]||r,e.children&&e.children.length>0){const t=e.children[0];if(t.data?.directiveLabel||"directiveLabel"===t.type){const r=t;let i="";(0,M.visit)(r,"text",t=>{i+=t.value}),i&&!e.attributes?.title&&(e.attributes=e.attributes||{},e.attributes.title=i.trim()),e.children.shift()}}e.attributes?.title&&(e.attributes.title=String(e.attributes.title).trim()),e.data=e.data||{},e.data.hName=e.data.hName||("containerDirective"===e.type?"div":"span"),e.data.hProperties={...e.data.hProperties||{},...e.attributes,className:[e.name,e.data.hProperties?.className].filter(Boolean).join(" ")}})},stage:100,order:10},F=require("unist-util-visit"),S={plugin:()=>async t=>{(0,F.visit)(t,"tableCell",t=>{if(t.data){const{rowspan:e,colspan:r}=t.data;t.data.hProperties=t.data.hProperties||{},void 0!==e&&(t.data.hProperties.rowSpan=e,delete t.data.rowspan),void 0!==r&&(t.data.hProperties.colSpan=r,delete t.data.colspan)}})},stage:100,order:20},O=require("unist-util-visit"),A=require("shell-quote");var D={plugin:()=>async t=>{(0,O.visit)(t,"code",t=>{if(t.meta){const e=function(t){const e={},r=(0,A.parse)(t);for(const t of r)if("string"==typeof t){const r=t.split("=",2);2===r.length?e[r[0]]=r[1]:e[t]="true"}return e}(t.meta),r=t.data=t.data||{};e.title&&(r.title=e.title),e.filename&&(r.filename=e.filename),r.kv={...r.kv||{},...e}}})},stage:100,order:30},T=require("unist-util-visit"),N={plugin:()=>async t=>{(0,T.visit)(t,"image",t=>{const e=t.data=t.data||{},r=e.hProperties=e.hProperties||{},i=/[#?&](?:width=([0-9]+))?(?:&?height=([0-9]+))?(?:=([0-9]+)x([0-9]+))?$/,n=t.url.match(i);if(n){const e=n[1]||n[3],s=n[2]||n[4];e&&!r.width&&(r.width=parseInt(e,10)),s&&!r.height&&(r.height=parseInt(s,10)),t.url=t.url.replace(i,"")}e.width&&!r.width&&(r.width=e.width),e.height&&!r.height&&(r.height=e.height)})},stage:100,order:40},z=[{plugin:m.default,stage:0},{plugin:d.default,options:[{singleTilde:!1}],stage:0},{plugin:y.default,stage:0},{plugin:b.default,stage:0},{plugin:w.default,options:[["yaml","toml"]],stage:0},x,S,D,N,j],E=[{plugin:g.default,options:[{handlers:q}],stage:400},{plugin:d.default,options:[{singleTilde:!1}],stage:400},{plugin:y.default,stage:400},{plugin:b.default,stage:400},{plugin:w.default,options:[["yaml","toml"]],stage:400}];E.forEach(t=>{t.plugin===g.default?t.order=100:t.order=10});var R={id:"markdown",title:"Markdown (GFM + Directives)",extensions:["md","markdown","mdown","mkdn"],mediaTypes:["text/markdown"],input:z,output:E},H=u(require("rehype-parse")),$=u(require("rehype-remark")),B=u(require("remark-rehype")),I=u(require("rehype-sanitize")),L=u(require("rehype-stringify")),C={id:"html",title:"HTML",extensions:["html","htm"],mediaTypes:["text/html"],input:[{name:"rehype-parse",plugin:H.default,stage:0},{name:"rehype-remark",plugin:$.default,options:[{handlers:{mark:(t,e)=>{const r={type:"mark",children:t.all(e)};return t.patch(e,r),r},sub:(t,e)=>{const r={type:"sub",children:t.all(e)};return t.patch(e,r),r},sup:(t,e)=>{const r={type:"sup",children:t.all(e)};return t.patch(e,r),r}}}],stage:0}],output:[{plugin:B.default,stage:300,order:10},{plugin:I.default,options:[{...I.defaultSchema,tagNames:[...I.defaultSchema.tagNames||[],"mark","sub","sup"],attributes:{...I.defaultSchema.attributes,"*":[...I.defaultSchema.attributes?.["*"]||[],"className","id","style"],td:[...I.defaultSchema.attributes?.td||[],"rowSpan","colSpan","rowspan","colspan"],th:[...I.defaultSchema.attributes?.th||[],"rowSpan","colSpan","rowspan","colspan"],img:[...I.defaultSchema.attributes?.img||[],"width","height"]}}],stage:300,order:20},{plugin:L.default,stage:400}]};function V(){this.Compiler=t=>t}function _(){this.Parser=t=>JSON.parse(t)}var G={id:"ast",title:"MDAST",input:[{plugin:_,stage:0},x,S,D,N,j],output:[{plugin:V,options:[],stage:400}]};function J(t){return"object"==typeof t&&null!==t&&"string"==typeof t.type}var K=class t{constructor(t){this.queue=[],this._data={},this.input=t}static register(t){this.registry.set(t.id,t)}static getFormat(t){return this.registry.get(t)}data(t,e){return"string"==typeof t?this._data[t]=e:Object.assign(this._data,t),this}getFormat(t){return this.constructor.getFormat(t)}resolveFormat(t){if("string"==typeof t){const e=this.getFormat(t);if(!e)throw new Error(`[MdastPlus] Format '${t}' is not registered.`);return e}return t}toRuntimeEntry(t,e,r){let i=e;void 0!==t.stage&&(i="string"==typeof t.stage?c[t.stage]??e:t.stage);let n=t.options||[];const s=t.name||t.plugin.name;if(r&&s&&s in r){const e=r[s];"object"!=typeof e||null===e||Array.isArray(e)?n=Array.isArray(e)?e:[e]:("main"in e&&(t.main=!!e.main),"before"in e&&(t.before=e.before),"after"in e&&(t.after=e.after),n=[e])}return{name:s,plugin:t.plugin,options:n,stage:i,order:t.order||0,main:t.main,before:t.before,after:t.after}}ensureInputPlugins(e,r,i=400){const n=e.some(t=>0===(t.stage??p)),s=J(this.input);if(!n){let n=[];if(s){const e=t.getFormat("ast");e&&e.input&&(n=e.input)}else{const e=t.getFormat("markdown");e&&e.input&&(n=e.input)}for(const t of n){const n=this.toRuntimeEntry(t,0,r);(n.stage??p)<=i&&e.push(n)}}}from(t,e){const r=this.resolveFormat(t);if(!r.input||0===r.input.length)throw new Error(`[MdastPlus] Format '${r.id}' does not support input.`);for(const t of r.input)this.queue.push(this.toRuntimeEntry(t,0,e));return this}async to(t,e){const r=this.resolveFormat(t);if(!r.output)throw new Error(`[MdastPlus] Format '${r.id}' does not support output.`);const i=[...this.queue];this.ensureInputPlugins(i,e);for(const t of r.output)i.push(this.toRuntimeEntry(t,300,e));const n=this.assembleProcessor(i);if(J(this.input)){const t=await n.run(this.input),e=n.stringify(t),r=new h.VFile;return"string"==typeof e||Buffer.isBuffer(e)?r.value=e:r.result=e,r}return n.process(this.input)}use(t,...e){return this.useAt("compile",t,...e)}useAt(t,e,...r){if(Array.isArray(t)){for(const i of t)this.useAt(i,e,...r);return this}if(Array.isArray(e)){for(const i of e)this.useAt(t,i,...r);return this}if("object"==typeof t&&null!==t&&"plugin"in t){const i=t,n=void 0!==i.stage?"string"==typeof i.stage?i.stage:c[i.stage]:"compile",s=void 0!==e?[e,...r]:i.options;this.queue.push(this.toRuntimeEntry({...i,options:s},c[n]))}else{const i=t;if("object"==typeof e&&null!==e&&"plugin"in e){const t=e,n=r.length>0?r:t.options;this.queue.push(this.toRuntimeEntry({...t,options:n},c[i]))}else e&&this.queue.push({plugin:e,options:r,stage:c[i],order:0})}return this}priority(t){const e=this.queue[this.queue.length-1];return e&&(e.order=t),this}assembleProcessor(t){const e={};for(const r of t){const t=r.stage??p;e[t]||(e[t]=[]),e[t].push(r)}const r=[],i=Object.keys(e).map(Number).sort((t,e)=>t-e);for(const t of i){const i=e[t].sort((t,e)=>(t.order||0)-(e.order||0)),n=i.findIndex(t=>t.main);if(-1!==n){const t=i[n];i.splice(n,1),i[0]=t}let s=!0,o=0;for(;s&&o<i.length;){s=!1,o++;for(let t=0;t<i.length;t++){const e=i[t];if(e.after){const r=i.findIndex(t=>t.name===e.after);if(-1!==r&&r>t){i.splice(t,1),i.splice(r,0,e),s=!0;break}}if(e.before){const r=i.findIndex(t=>t.name===e.before);if(-1!==r&&r<t){i.splice(t,1),i.splice(r,0,e),s=!0;break}}}}r.push(...i)}const n=(0,f.unified)();Object.keys(this._data).length>0&&n.data(this._data);for(const t of r)n.use(t.plugin,...t.options||[]);return n}};K.registry=new Map;var Q=K,U=class extends Q{async toMarkdown(){const t=await this.to("markdown");return String(t)}toMarkdownVFile(){return this.to("markdown")}async toHtml(){const t=await this.to("html");return String(t)}toHtmlVFile(){return this.to("html")}async toAst(t){if(t?.stage){const e=c[t.stage],r=this.queue.filter(t=>(t.stage??p)<=e);r.push({plugin:V,options:[],stage:400,order:0}),this.ensureInputPlugins(r,t.overrides,e);const i=this.assembleProcessor(r);if(J(this.input)){return await i.run(this.input)}return(await i.process(this.input)).result}return(await this.to("ast",t?.overrides)).result}toHTML(){return this.toHtml()}toAST(t){return this.toAst(t)}};function W(t){return new U(t)}U.register(R),U.register(C),U.register(G);var X=require("hast-util-from-html"),Y=function(t){let e={};"boolean"==typeof t?e={enable:t}:t&&(e=t);const{enable:r,readability:i,jsdom:n}=e;!1!==r&&(this.parser=function(t,e){let r,s;try{r=require("jsdom").JSDOM;s=require("@mozilla/readability").Readability}catch(t){throw new Error("[html-readability] Dependency missing. Please install 'jsdom' and '@mozilla/readability'.")}const o=new s(new r(t,n).window.document,i).parse();if(!o||!o.content)return(0,X.fromHtml)(t,{fragment:!0});const a=(0,X.fromHtml)(o.content,{fragment:!0}),u={title:o.title,byline:o.byline,excerpt:o.excerpt,siteName:o.siteName,lang:o.lang};return e&&(e.data=e.data||{},e.data.readability=u),a&&(a.data=a.data||{},a.data.readability=u),a})},Z={name:"readability",plugin:Y,stage:0},tt={name:"restore-readability-meta",plugin:()=>(t,e)=>{e.data?.readability&&(t.data=t.data||{},t.data.readability=e.data.readability)},stage:0,after:"rehype-remark"},et=[Z,tt];
|
package/dist/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{unified as t}from"unified";import r from"remark-parse";import i from"remark-stringify";import e from"remark-gfm";import s from"remark-directive";import n from"remark-math";import a from"remark-frontmatter";import{visit as o}from"unist-util-visit";function m(t,r){return{type:t,children:r,data:{hName:t}}}var c={mark:(t,r)=>{const i={type:"mark",children:t.all(r)};return t.patch(r,i),i},sub:(t,r)=>{const i={type:"sub",children:t.all(r)};return t.patch(r,i),i},sup:(t,r)=>{const i={type:"sup",children:t.all(r)};return t.patch(r,i),i}},l={mark:(t,r,i)=>"=="+i.containerPhrasing(t,{before:"==",after:"=="})+"==",sub:(t,r,i)=>"~"+i.containerPhrasing(t,{before:"~",after:"~"})+"~",sup:(t,r,i)=>"^"+i.containerPhrasing(t,{before:"^",after:"^"})+"^"},p={name:"normalize-inline-styles",stage:"normalize",transform:t=>{!function(t){o(t,"text",(t,r,i)=>{if(!i||void 0===r)return;const e=t.value;let s=0;const n=[];let a=!1;const o=/(==[^=]+==|~[^~]+~|\^[^^]+\^)/g;let c;for(;null!==(c=o.exec(e));){a=!0;const t=c[0],r=c.index;r>s&&n.push({type:"text",value:e.slice(s,r)});let i="mark",l="";t.startsWith("==")?(i="mark",l=t.slice(2,-2)):t.startsWith("~")?(i="sub",l=t.slice(1,-1)):t.startsWith("^")&&(i="sup",l=t.slice(1,-1)),n.push(m(i,[{type:"text",value:l}])),s=o.lastIndex}return a?(s<e.length&&n.push({type:"text",value:e.slice(s)}),i.children.splice(r,1,...n),r+n.length):void 0})}(t)}};function f(){const t=this.data();var r,i;i={handlers:l},t[r="toMarkdownExtensions"]?t[r].push(i):t[r]=[i],this.use(e,{singleTilde:!1}).use(s).use(n).use(a,["yaml","toml"])}var h={parse:t=>t.use(r).use(f),stringify:t=>t.use(i).use(f)};import u from"rehype-parse";import d from"rehype-remark";import v from"remark-rehype";import y,{defaultSchema as g}from"rehype-sanitize";import w from"rehype-stringify";function k(){this.use(v).use(y,{...g,tagNames:[...g.tagNames||[],"mark","sub","sup"],attributes:{...g.attributes,"*":[...g.attributes?.["*"]||[],"className","id","style"],td:[...g.attributes?.td||[],"rowSpan","colSpan","rowspan","colspan"],th:[...g.attributes?.th||[],"rowSpan","colSpan","rowspan","colspan"],img:[...g.attributes?.img||[],"width","height"]}}).use(w)}var z={parse:t=>t.use(u).use(d,{handlers:c}),stringify:t=>t.use(k)};import{visit as b}from"unist-util-visit";var x={error:"danger",warn:"warning",success:"tip",important:"important",caution:"caution",note:"note"},S={name:"normalize-directive",stage:"normalize",order:10,transform:async t=>{b(t,["containerDirective","leafDirective","textDirective"],t=>{const r=t,i=r.name.toLowerCase();if(r.name=x[i]||i,r.children&&r.children.length>0){const t=r.children[0];if(t.data?.directiveLabel||"directiveLabel"===t.type){let i="";b(t,"text",t=>{i+=t.value}),i&&!r.attributes?.title&&(r.attributes=r.attributes||{},r.attributes.title=i.trim()),r.children.shift()}}r.attributes?.title&&(r.attributes.title=String(r.attributes.title).trim()),r.data=r.data||{},r.data.hName=r.data.hName||("containerDirective"===r.type?"div":"span"),r.data.hProperties={...r.data.hProperties||{},...r.attributes,className:[r.name,r.data.hProperties?.className].filter(Boolean).join(" ")}})}};import{visit as N}from"unist-util-visit";var D={name:"normalize-table-span",stage:"normalize",order:20,transform:async t=>{N(t,"tableCell",t=>{if(t.data){const{rowspan:r,colspan:i}=t.data;t.data.hProperties=t.data.hProperties||{},void 0!==r&&(t.data.hProperties.rowSpan=r,delete t.data.rowspan),void 0!==i&&(t.data.hProperties.colSpan=i,delete t.data.colspan)}})}};import{visit as M}from"unist-util-visit";import{parse as T}from"shell-quote";var I={name:"extract-code-meta",stage:"normalize",order:30,transform:async t=>{M(t,"code",t=>{if(t.meta){const r=function(t){const r={},i=T(t);for(const t of i)if("string"==typeof t){const i=t.split("=",2);2===i.length?r[i[0]]=i[1]:r[t]="true"}return r}(t.meta),i=t.data=t.data||{};r.title&&(i.title=r.title),r.filename&&(i.filename=r.filename),i.kv={...i.kv||{},...r}}})}};import{visit as L}from"unist-util-visit";var q={name:"image-size",stage:"normalize",order:40,transform:async t=>{L(t,"image",t=>{const r=t.data=t.data||{},i=r.hProperties=r.hProperties||{},e=/[#?&](?:width=([0-9]+))?(?:&?height=([0-9]+))?(?:=([0-9]+)x([0-9]+))?$/,s=t.url.match(e);if(s){const r=s[1]||s[3],n=s[2]||s[4];r&&!i.width&&(i.width=parseInt(r,10)),n&&!i.height&&(i.height=parseInt(n,10)),t.url=t.url.replace(e,"")}r.width&&!i.width&&(i.width=r.width),r.height&&!i.height&&(i.height=r.height)})}},A=class r{constructor(r){this.inputFormat="markdown",this.plugins=[],this.globalData={},this.input=r,this.processor=t(),this.use(S),this.use(D),this.use(I),this.use(q),this.use(p)}static registerFormat(t,i){r.formats[t.toLowerCase()]=i}from(t){return this.inputFormat=t.toLowerCase(),this}use(t){return this.plugins.push(t),this}data(t){return this.globalData={...this.globalData,...t},this}async to(i){i=i.toLowerCase();const e=r.formats[this.inputFormat];e?.parse&&e.parse(this.processor);let s="string"==typeof this.input?this.processor.parse(this.input):this.input;s=await this.processor.run(s),s.data={...s.data,...this.globalData};const n=[...this.plugins].sort((t,r)=>{const i={normalize:0,compile:1,finalize:2},e=t.stage||"normalize",s=r.stage||"normalize";return e!==s?i[e]-i[s]:(t.order||0)-(r.order||0)});for(const t of n)await t.transform(s,this.processor);const a=t().data("settings",this.processor.data("settings")),o=r.formats[i];o?.stringify&&o.stringify(a),"markdown"!==i||o||h.stringify(a);const m=await a.run(s),c=a.stringify(m),l=[];return s.data&&s.data.assets&&l.push(...s.data.assets),{content:c,assets:l}}async toMarkdown(){return(await this.to("markdown")).content}async toHTML(){return(await this.to("html")).content}async toAST(){return(await this.to("ast")).content}};A.formats={markdown:h,html:z,ast:{parse:t=>{t.Parser=t=>JSON.parse(t)},stringify:t=>{t.Compiler=t=>t}}};var B=A;function C(t){return new B(t)}export{B as FluentProcessor,z as htmlFormat,k as htmlStringify,f as markdownCommon,h as markdownFormat,C as mdast};
|
|
1
|
+
var t=(t=>"undefined"!=typeof require?require:"undefined"!=typeof Proxy?new Proxy(t,{get:(t,e)=>("undefined"!=typeof require?require:t)[e]}):t)(function(t){if("undefined"!=typeof require)return require.apply(this,arguments);throw Error('Dynamic require of "'+t+'" is not supported')}),e=(t=>(t[t.parse=0]="parse",t[t.normalize=100]="normalize",t[t.compile=200]="compile",t[t.finalize=300]="finalize",t[t.stringify=400]="stringify",t))(e||{}),r=200;import{unified as i}from"unified";import{VFile as n}from"vfile";import o from"remark-parse";import s from"remark-stringify";import a from"remark-gfm";import u from"remark-directive";import p from"remark-math";import l from"remark-frontmatter";import{visit as f}from"unist-util-visit";function m(t,e){return{type:t,children:e,data:{hName:t}}}var c={plugin:()=>t=>{!function(t){f(t,"text",(t,e,r)=>{if(!r||void 0===e)return;const i=t.value;let n=0;const o=[];let s=!1;const a=/(==[^=]+==|~[^~]+~|\^[^^]+\^)/g;let u;for(;null!==(u=a.exec(i));){s=!0;const t=u[0],e=u.index;e>n&&o.push({type:"text",value:i.slice(n,e)});let r="mark",p="";t.startsWith("==")?(r="mark",p=t.slice(2,-2)):t.startsWith("~")?(r="sub",p=t.slice(1,-1)):t.startsWith("^")&&(r="sup",p=t.slice(1,-1)),o.push(m(r,[{type:"text",value:p}])),n=a.lastIndex}return s?(n<i.length&&o.push({type:"text",value:i.slice(n)}),r.children.splice(e,1,...o),e+o.length):void 0})}(t)},stage:100};import{visit as h}from"unist-util-visit";var g={error:"danger",warn:"warning",success:"tip",important:"important",caution:"caution",note:"note"},d={plugin:()=>async t=>{h(t,["containerDirective","leafDirective","textDirective"],t=>{const e=t,r=e.name.toLowerCase();if(e.name=g[r]||r,e.children&&e.children.length>0){const t=e.children[0];if(t.data?.directiveLabel||"directiveLabel"===t.type){let r="";h(t,"text",t=>{r+=t.value}),r&&!e.attributes?.title&&(e.attributes=e.attributes||{},e.attributes.title=r.trim()),e.children.shift()}}e.attributes?.title&&(e.attributes.title=String(e.attributes.title).trim()),e.data=e.data||{},e.data.hName=e.data.hName||("containerDirective"===e.type?"div":"span"),e.data.hProperties={...e.data.hProperties||{},...e.attributes,className:[e.name,e.data.hProperties?.className].filter(Boolean).join(" ")}})},stage:100,order:10};import{visit as y}from"unist-util-visit";var v={plugin:()=>async t=>{y(t,"tableCell",t=>{if(t.data){const{rowspan:e,colspan:r}=t.data;t.data.hProperties=t.data.hProperties||{},void 0!==e&&(t.data.hProperties.rowSpan=e,delete t.data.rowspan),void 0!==r&&(t.data.hProperties.colSpan=r,delete t.data.colspan)}})},stage:100,order:20};import{visit as w}from"unist-util-visit";import{parse as b}from"shell-quote";var k={plugin:()=>async t=>{w(t,"code",t=>{if(t.meta){const e=function(t){const e={},r=b(t);for(const t of r)if("string"==typeof t){const r=t.split("=",2);2===r.length?e[r[0]]=r[1]:e[t]="true"}return e}(t.meta),r=t.data=t.data||{};e.title&&(r.title=e.title),e.filename&&(r.filename=e.filename),r.kv={...r.kv||{},...e}}})},stage:100,order:30};import{visit as x}from"unist-util-visit";var M={plugin:()=>async t=>{x(t,"image",t=>{const e=t.data=t.data||{},r=e.hProperties=e.hProperties||{},i=/[#?&](?:width=([0-9]+))?(?:&?height=([0-9]+))?(?:=([0-9]+)x([0-9]+))?$/,n=t.url.match(i);if(n){const e=n[1]||n[3],o=n[2]||n[4];e&&!r.width&&(r.width=parseInt(e,10)),o&&!r.height&&(r.height=parseInt(o,10)),t.url=t.url.replace(i,"")}e.width&&!r.width&&(r.width=e.width),e.height&&!r.height&&(r.height=e.height)})},stage:100,order:40},j=[{plugin:o,stage:0},{plugin:a,options:[{singleTilde:!1}],stage:0},{plugin:u,stage:0},{plugin:p,stage:0},{plugin:l,options:[["yaml","toml"]],stage:0},d,v,k,M,c],S=[{plugin:s,options:[{handlers:{mark:(t,e,r)=>"=="+r.containerPhrasing(t,{before:"==",after:"=="})+"==",sub:(t,e,r)=>"~"+r.containerPhrasing(t,{before:"~",after:"~"})+"~",sup:(t,e,r)=>"^"+r.containerPhrasing(t,{before:"^",after:"^"})+"^"}}],stage:400},{plugin:a,options:[{singleTilde:!1}],stage:400},{plugin:u,stage:400},{plugin:p,stage:400},{plugin:l,options:[["yaml","toml"]],stage:400}];S.forEach(t=>{t.plugin===s?t.order=100:t.order=10});var F={id:"markdown",title:"Markdown (GFM + Directives)",extensions:["md","markdown","mdown","mkdn"],mediaTypes:["text/markdown"],input:j,output:S};import q from"rehype-parse";import A from"rehype-remark";import D from"remark-rehype";import P,{defaultSchema as T}from"rehype-sanitize";import N from"rehype-stringify";var E={id:"html",title:"HTML",extensions:["html","htm"],mediaTypes:["text/html"],input:[{name:"rehype-parse",plugin:q,stage:0},{name:"rehype-remark",plugin:A,options:[{handlers:{mark:(t,e)=>{const r={type:"mark",children:t.all(e)};return t.patch(e,r),r},sub:(t,e)=>{const r={type:"sub",children:t.all(e)};return t.patch(e,r),r},sup:(t,e)=>{const r={type:"sup",children:t.all(e)};return t.patch(e,r),r}}}],stage:0}],output:[{plugin:D,stage:300,order:10},{plugin:P,options:[{...T,tagNames:[...T.tagNames||[],"mark","sub","sup"],attributes:{...T.attributes,"*":[...T.attributes?.["*"]||[],"className","id","style"],td:[...T.attributes?.td||[],"rowSpan","colSpan","rowspan","colspan"],th:[...T.attributes?.th||[],"rowSpan","colSpan","rowspan","colspan"],img:[...T.attributes?.img||[],"width","height"]}}],stage:300,order:20},{plugin:N,stage:400}]};function z(){this.Compiler=t=>t}function H(){this.Parser=t=>JSON.parse(t)}var O={id:"ast",title:"MDAST",input:[{plugin:H,stage:0},d,v,k,M,c],output:[{plugin:z,options:[],stage:400}]};function $(t){return"object"==typeof t&&null!==t&&"string"==typeof t.type}var I=class t{constructor(t){this.queue=[],this._data={},this.input=t}static register(t){this.registry.set(t.id,t)}static getFormat(t){return this.registry.get(t)}data(t,e){return"string"==typeof t?this._data[t]=e:Object.assign(this._data,t),this}getFormat(t){return this.constructor.getFormat(t)}resolveFormat(t){if("string"==typeof t){const e=this.getFormat(t);if(!e)throw new Error(`[MdastPlus] Format '${t}' is not registered.`);return e}return t}toRuntimeEntry(t,r,i){let n=r;void 0!==t.stage&&(n="string"==typeof t.stage?e[t.stage]??r:t.stage);let o=t.options||[];const s=t.name||t.plugin.name;if(i&&s&&s in i){const e=i[s];"object"!=typeof e||null===e||Array.isArray(e)?o=Array.isArray(e)?e:[e]:("main"in e&&(t.main=!!e.main),"before"in e&&(t.before=e.before),"after"in e&&(t.after=e.after),o=[e])}return{name:s,plugin:t.plugin,options:o,stage:n,order:t.order||0,main:t.main,before:t.before,after:t.after}}ensureInputPlugins(e,i,n=400){const o=e.some(t=>0===(t.stage??r)),s=$(this.input);if(!o){let o=[];if(s){const e=t.getFormat("ast");e&&e.input&&(o=e.input)}else{const e=t.getFormat("markdown");e&&e.input&&(o=e.input)}for(const t of o){const o=this.toRuntimeEntry(t,0,i);(o.stage??r)<=n&&e.push(o)}}}from(t,e){const r=this.resolveFormat(t);if(!r.input||0===r.input.length)throw new Error(`[MdastPlus] Format '${r.id}' does not support input.`);for(const t of r.input)this.queue.push(this.toRuntimeEntry(t,0,e));return this}async to(t,e){const r=this.resolveFormat(t);if(!r.output)throw new Error(`[MdastPlus] Format '${r.id}' does not support output.`);const i=[...this.queue];this.ensureInputPlugins(i,e);for(const t of r.output)i.push(this.toRuntimeEntry(t,300,e));const o=this.assembleProcessor(i);if($(this.input)){const t=await o.run(this.input),e=o.stringify(t),r=new n;return"string"==typeof e||Buffer.isBuffer(e)?r.value=e:r.result=e,r}return o.process(this.input)}use(t,...e){return this.useAt("compile",t,...e)}useAt(t,r,...i){if(Array.isArray(t)){for(const e of t)this.useAt(e,r,...i);return this}if(Array.isArray(r)){for(const e of r)this.useAt(t,e,...i);return this}if("object"==typeof t&&null!==t&&"plugin"in t){const n=t,o=void 0!==n.stage?"string"==typeof n.stage?n.stage:e[n.stage]:"compile",s=void 0!==r?[r,...i]:n.options;this.queue.push(this.toRuntimeEntry({...n,options:s},e[o]))}else{const n=t;if("object"==typeof r&&null!==r&&"plugin"in r){const t=r,o=i.length>0?i:t.options;this.queue.push(this.toRuntimeEntry({...t,options:o},e[n]))}else r&&this.queue.push({plugin:r,options:i,stage:e[n],order:0})}return this}priority(t){const e=this.queue[this.queue.length-1];return e&&(e.order=t),this}assembleProcessor(t){const e={};for(const i of t){const t=i.stage??r;e[t]||(e[t]=[]),e[t].push(i)}const n=[],o=Object.keys(e).map(Number).sort((t,e)=>t-e);for(const t of o){const r=e[t].sort((t,e)=>(t.order||0)-(e.order||0)),i=r.findIndex(t=>t.main);if(-1!==i){const t=r[i];r.splice(i,1),r[0]=t}let o=!0,s=0;for(;o&&s<r.length;){o=!1,s++;for(let t=0;t<r.length;t++){const e=r[t];if(e.after){const i=r.findIndex(t=>t.name===e.after);if(-1!==i&&i>t){r.splice(t,1),r.splice(i,0,e),o=!0;break}}if(e.before){const i=r.findIndex(t=>t.name===e.before);if(-1!==i&&i<t){r.splice(t,1),r.splice(i,0,e),o=!0;break}}}}n.push(...r)}const s=i();Object.keys(this._data).length>0&&s.data(this._data);for(const t of n)s.use(t.plugin,...t.options||[]);return s}};I.registry=new Map;var L=I,B=class extends L{async toMarkdown(){const t=await this.to("markdown");return String(t)}toMarkdownVFile(){return this.to("markdown")}async toHtml(){const t=await this.to("html");return String(t)}toHtmlVFile(){return this.to("html")}async toAst(t){if(t?.stage){const i=e[t.stage],n=this.queue.filter(t=>(t.stage??r)<=i);n.push({plugin:z,options:[],stage:400,order:0}),this.ensureInputPlugins(n,t.overrides,i);const o=this.assembleProcessor(n);if($(this.input)){return await o.run(this.input)}return(await o.process(this.input)).result}return(await this.to("ast",t?.overrides)).result}toHTML(){return this.toHtml()}toAST(t){return this.toAst(t)}};function V(t){return new B(t)}B.register(F),B.register(E),B.register(O);import{fromHtml as C}from"hast-util-from-html";var G=function(e){let r={};"boolean"==typeof e?r={enable:e}:e&&(r=e);const{enable:i,readability:n,jsdom:o}=r;!1!==i&&(this.parser=function(e,r){let i,s;try{i=t("jsdom").JSDOM;s=t("@mozilla/readability").Readability}catch(t){throw new Error("[html-readability] Dependency missing. Please install 'jsdom' and '@mozilla/readability'.")}const a=new s(new i(e,o).window.document,n).parse();if(!a||!a.content)return C(e,{fragment:!0});const u=C(a.content,{fragment:!0}),p={title:a.title,byline:a.byline,excerpt:a.excerpt,siteName:a.siteName,lang:a.lang};return r&&(r.data=r.data||{},r.data.readability=p),u&&(u.data=u.data||{},u.data.readability=p),u})},J={name:"readability",plugin:G,stage:0},R={name:"restore-readability-meta",plugin:()=>(t,e)=>{e.data?.readability&&(t.data=t.data||{},t.data.readability=e.data.readability)},stage:0,after:"rehype-remark"},K=[J,R];export{r as DefaultPipelineStage,L as MdastBasePipeline,B as MdastPipeline,e as PipelineStage,z as astCompiler,O as astFormat,E as htmlFormat,G as htmlReadability,J as htmlReadabilityPlugin,K as htmlReadabilityPlugins,H as jsonParser,F as markdownFormat,V as mdast,R as restoreReadabilityMetaPlugin};
|
package/docs/README.md
CHANGED
|
@@ -15,7 +15,7 @@ English | [简体中文](_media/README.cn.md) | [GitHub](https://github.com/isdk
|
|
|
15
15
|
## Features
|
|
16
16
|
|
|
17
17
|
- **Fluent API**: Chainable interface `mdast(input).use(plugin).toHTML()`.
|
|
18
|
-
- **Staged Plugins**: Organize transformations into `normalize`, `compile`, and `
|
|
18
|
+
- **Staged Plugins**: Organize transformations into `parse`, `normalize`, `compile`, `finalize`, and `stringify` stages.
|
|
19
19
|
- **Semantic Normalization**:
|
|
20
20
|
- **Directives**: Canonicalizes admonition names and extracts titles from labels.
|
|
21
21
|
- **Table Spans**: Support for `rowspan` and `colspan` in HTML output.
|
|
@@ -44,6 +44,17 @@ const html = await mdast(':::warning[Special Note]\nBe careful!\n:::')
|
|
|
44
44
|
// Result: <div title="Special Note" class="warning"><p>Be careful!</p></div>
|
|
45
45
|
```
|
|
46
46
|
|
|
47
|
+
### Configure Input Options
|
|
48
|
+
|
|
49
|
+
You can pass options to input plugins (like `remark-gfm` or `remark-parse`) using the second argument of `.from()`:
|
|
50
|
+
|
|
51
|
+
```typescript
|
|
52
|
+
// Enable single tilde strikethrough (~text~)
|
|
53
|
+
const md = await mdast('Hello ~world~')
|
|
54
|
+
.from('markdown', { remarkGfm: { singleTilde: true } })
|
|
55
|
+
.toMarkdown();
|
|
56
|
+
```
|
|
57
|
+
|
|
47
58
|
### Image Sizing
|
|
48
59
|
|
|
49
60
|
```typescript
|
|
@@ -54,23 +65,46 @@ const html = await mdast('').toHTML();
|
|
|
54
65
|
### AST Output
|
|
55
66
|
|
|
56
67
|
```typescript
|
|
68
|
+
// Get the fully processed AST (after normalization)
|
|
57
69
|
const ast = await mdast('==Highlighted==').toAST();
|
|
58
|
-
|
|
70
|
+
|
|
71
|
+
// Get the raw AST (after parsing, before normalization)
|
|
72
|
+
const rawAst = await mdast('==Highlighted==').toAST({ stage: 'parse' });
|
|
59
73
|
```
|
|
60
74
|
|
|
61
75
|
### Advanced Pipeline
|
|
62
76
|
|
|
63
77
|
```typescript
|
|
64
|
-
|
|
78
|
+
import { htmlReadabilityPlugins } from '@isdk/mdast-plus';
|
|
79
|
+
|
|
80
|
+
const vfile = await mdast(myInput)
|
|
65
81
|
.data({ myGlobal: 'value' })
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
}
|
|
72
|
-
})
|
|
82
|
+
// Add multiple plugins as an array at the 'compile' stage
|
|
83
|
+
.use([pluginA, pluginB])
|
|
84
|
+
// Or add a set of plugins at a specific stage
|
|
85
|
+
.useAt('parse', htmlReadabilityPlugins)
|
|
86
|
+
.priority(10) // Run later than default plugins
|
|
73
87
|
.to('html');
|
|
88
|
+
|
|
89
|
+
console.log(vfile.value); // The serialized HTML string
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Plugin Behavior
|
|
93
|
+
|
|
94
|
+
`mdast-plus` uses [unified](https://github.com/unifiedjs/unified) internally. If you add the same plugin function multiple times, the last configuration **overrides** the previous ones.
|
|
95
|
+
|
|
96
|
+
```typescript
|
|
97
|
+
// The plugin will run ONCE with option: 2
|
|
98
|
+
pipeline.use(myPlugin, { option: 1 });
|
|
99
|
+
pipeline.use(myPlugin, { option: 2 });
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
To run the same plugin logic multiple times (e.g., for different purposes), provide a distinct function reference:
|
|
103
|
+
|
|
104
|
+
```typescript
|
|
105
|
+
// The plugin will run TWICE
|
|
106
|
+
pipeline.use(myPlugin, { option: 1 });
|
|
107
|
+
pipeline.use(myPlugin.bind({}), { option: 2 });
|
|
74
108
|
```
|
|
75
109
|
|
|
76
110
|
### Arbitrary Formats
|
|
@@ -78,16 +112,20 @@ const { content, assets } = await mdast(myInput)
|
|
|
78
112
|
You can register custom input or output formats:
|
|
79
113
|
|
|
80
114
|
```typescript
|
|
81
|
-
import {
|
|
115
|
+
import { MdastPipeline, mdast, PipelineStage } from '@isdk/mdast-plus';
|
|
82
116
|
|
|
83
117
|
// Register a custom output format
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
118
|
+
MdastPipeline.register({
|
|
119
|
+
id: 'reverse',
|
|
120
|
+
output: [{
|
|
121
|
+
plugin: function() {
|
|
122
|
+
this.Compiler = (tree) => {
|
|
123
|
+
// your custom stringification logic
|
|
124
|
+
return '...';
|
|
125
|
+
};
|
|
126
|
+
},
|
|
127
|
+
stage: PipelineStage.stringify
|
|
128
|
+
}]
|
|
91
129
|
});
|
|
92
130
|
|
|
93
131
|
const result = await mdast('Hello').to('reverse');
|
|
@@ -97,11 +135,19 @@ const result = await mdast('Hello').to('reverse');
|
|
|
97
135
|
|
|
98
136
|
## Staged Processing
|
|
99
137
|
|
|
100
|
-
Plugins are executed based on their `stage` and `
|
|
138
|
+
Plugins are executed based on their `stage`, `order`, and semantic constraints (`before`/`after`):
|
|
139
|
+
|
|
140
|
+
1. **parse** (0): Input parsing (e.g., `remark-parse`).
|
|
141
|
+
2. **normalize** (100): Cleanup and canonicalize the tree.
|
|
142
|
+
3. **compile** (200): High-level semantic transformations.
|
|
143
|
+
4. **finalize** (300): Final preparation before output (e.g. `rehype-sanitize`).
|
|
144
|
+
5. **stringify** (400): Output generation.
|
|
145
|
+
|
|
146
|
+
### Main Plugin Replacement
|
|
147
|
+
|
|
148
|
+
Each stage can have one "main" plugin. If a plugin is marked with `main: true`, it will **replace** the first plugin in that same stage. This is useful for swapping out default parsers or compilers while keeping the rest of the pipeline intact.
|
|
101
149
|
|
|
102
|
-
|
|
103
|
-
2. **compile** (order 0-100): High-level semantic transformations.
|
|
104
|
-
3. **finalize** (order 0-100): Final preparation before output.
|
|
150
|
+
> **Note**: Only one main plugin is allowed per stage. If multiple plugins are marked as main, only the last one defined will take effect as the replacement.
|
|
105
151
|
|
|
106
152
|
## Core Plugins Included
|
|
107
153
|
|
|
@@ -112,6 +158,7 @@ Plugins are executed based on their `stage` and `order`:
|
|
|
112
158
|
| `extract-code-meta` | normalize | Parses `title="foo"` from code block meta. |
|
|
113
159
|
| `image-size` | normalize | Parses `#=WxH` from image URLs. |
|
|
114
160
|
| `normalize-inline-styles` | normalize | Standardizes `==mark==`, `~sub~`, and `^sup^`. |
|
|
161
|
+
| `html-readability` | parse | Uses Mozilla's Readability to extract main content from HTML. Use `htmlReadabilityPlugins` array for easier setup. |
|
|
115
162
|
|
|
116
163
|
## Contributing
|
|
117
164
|
|
|
@@ -8,12 +8,14 @@ Thank you for your interest in contributing to `@isdk/mdast-plus`! This document
|
|
|
8
8
|
|
|
9
9
|
### Core Concepts
|
|
10
10
|
|
|
11
|
-
1.
|
|
12
|
-
2.
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
|
|
11
|
+
1. **Fluent API**: The main entry point is the `mdast()` function in `src/pipeline.ts`, backed by `MdastPipeline`.
|
|
12
|
+
2. **Staged Plugins**: Plugins are categorized into 5 stages (`PipelineStage`):
|
|
13
|
+
* `parse`: Parsing input to AST.
|
|
14
|
+
* `normalize`: Cleanup and canonicalize the tree.
|
|
15
|
+
* `compile`: High-level semantic transformations.
|
|
16
|
+
* `finalize`: Final preparation before output.
|
|
17
|
+
* `stringify`: Serializing AST to output.
|
|
18
|
+
3. **Universal Data Protocols**: Nodes use `node.data` for metadata, and `node.data.hProperties` for HTML attributes.
|
|
17
19
|
|
|
18
20
|
## Getting Started
|
|
19
21
|
|
|
@@ -54,40 +56,67 @@ pnpm run lint
|
|
|
54
56
|
|
|
55
57
|
## Adding a New Plugin
|
|
56
58
|
|
|
57
|
-
1.
|
|
58
|
-
2.
|
|
59
|
+
1. Create your plugin in `src/plugins/`.
|
|
60
|
+
2. Implement the `MdastPlugin` interface. The `plugin` property should be a standard unified plugin.
|
|
59
61
|
|
|
60
62
|
```typescript
|
|
61
|
-
import { MdastPlugin } from '../types';
|
|
63
|
+
import { MdastPlugin, PipelineStage } from '../types';
|
|
64
|
+
import { visit } from 'unist-util-visit';
|
|
65
|
+
|
|
66
|
+
const myUnifiedPlugin = (options) => {
|
|
67
|
+
return (tree) => {
|
|
68
|
+
visit(tree, 'text', (node) => {
|
|
69
|
+
// transform logic
|
|
70
|
+
});
|
|
71
|
+
};
|
|
72
|
+
};
|
|
62
73
|
|
|
63
74
|
export const myPlugin: MdastPlugin = {
|
|
64
|
-
name: 'my-plugin',
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
75
|
+
name: 'my-custom-plugin',
|
|
76
|
+
plugin: myUnifiedPlugin,
|
|
77
|
+
stage: PipelineStage.normalize, // or 'compile', 'finalize', etc.
|
|
78
|
+
order: 50, // 0-100
|
|
79
|
+
main: false, // Set to true to replace the first plugin of the stage, defaults to false
|
|
80
|
+
before: 'some-other-plugin', // Optional: run before another plugin
|
|
81
|
+
after: 'another-plugin', // Optional: run after another plugin
|
|
70
82
|
};
|
|
71
83
|
```
|
|
72
84
|
|
|
73
|
-
|
|
85
|
+
### Main Plugins
|
|
86
|
+
|
|
87
|
+
Each stage supports a **single** main plugin. When a plugin is marked with `main: true`, it will replace the first plugin that was originally registered for that stage. This is primarily used by formats to allow users to override the default parser or stringifier by injecting a different one at the same stage.
|
|
88
|
+
|
|
89
|
+
1. If it's a default plugin, add it to the `input` or `output` list of the relevant format in `src/formats/`.
|
|
74
90
|
|
|
75
91
|
## Adding a New Format
|
|
76
92
|
|
|
77
|
-
1.
|
|
78
|
-
2. Register it using `
|
|
93
|
+
1. Define a `MdastFormat` object.
|
|
94
|
+
2. Register it using `MdastPipeline.register(format)`.
|
|
79
95
|
|
|
80
96
|
```typescript
|
|
81
|
-
import {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
97
|
+
import { MdastPipeline, PipelineStage } from '../src/pipeline';
|
|
98
|
+
|
|
99
|
+
MdastPipeline.register({
|
|
100
|
+
id: 'json',
|
|
101
|
+
title: 'JSON Format',
|
|
102
|
+
output: [{
|
|
103
|
+
plugin: function() {
|
|
104
|
+
this.Compiler = (tree) => JSON.stringify(tree);
|
|
105
|
+
},
|
|
106
|
+
stage: PipelineStage.stringify
|
|
107
|
+
}]
|
|
87
108
|
});
|
|
88
109
|
```
|
|
89
110
|
|
|
90
111
|
> **Note**: Format names are case-insensitive.
|
|
112
|
+
>
|
|
113
|
+
> **Important**: `unified` requires a `Compiler` to be attached for the process to complete successfully. If your format is intended to return an object (like the AST itself) rather than a string, you must provide a "pass-through" compiler:
|
|
114
|
+
>
|
|
115
|
+
> ```typescript
|
|
116
|
+
> function astCompiler() {
|
|
117
|
+
> this.Compiler = (tree) => tree;
|
|
118
|
+
> }
|
|
119
|
+
> ```
|
|
91
120
|
|
|
92
121
|
## Coding Standards
|
|
93
122
|
|
package/docs/_media/README.cn.md
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
## 特性
|
|
12
12
|
|
|
13
13
|
- **Fluent API**: 链式调用接口 `mdast(input).use(plugin).toHTML()`。
|
|
14
|
-
- **分阶段插件**: 将转换组织为 `normalize
|
|
14
|
+
- **分阶段插件**: 将转换组织为 `parse`, `normalize`, `compile`, `finalize` 和 `stringify` 阶段。
|
|
15
15
|
- **语义化规范**:
|
|
16
16
|
- **指令 (Directives)**: 规范化提示框 (Admonition) 名称并从标签中提取标题。
|
|
17
17
|
- **表格跨行/跨列**: 支持 HTML 输出中的 `rowspan` 和 `colspan`。
|
|
@@ -40,6 +40,17 @@ const html = await mdast(':::warning[重要提示]\n请小心!\n:::')
|
|
|
40
40
|
// 结果: <div title="重要提示" class="warning"><p>请小心!</p></div>
|
|
41
41
|
```
|
|
42
42
|
|
|
43
|
+
### 配置输入选项
|
|
44
|
+
|
|
45
|
+
您可以通过 `.from()` 的第二个参数向输入插件(如 `remark-gfm` 或 `remark-parse`)传递选项:
|
|
46
|
+
|
|
47
|
+
```typescript
|
|
48
|
+
// 启用单个波浪线删除线 (~text~)
|
|
49
|
+
const md = await mdast('Hello ~world~')
|
|
50
|
+
.from('markdown', { remarkGfm: { singleTilde: true } })
|
|
51
|
+
.toMarkdown();
|
|
52
|
+
```
|
|
53
|
+
|
|
43
54
|
### 图片尺寸
|
|
44
55
|
|
|
45
56
|
```typescript
|
|
@@ -50,23 +61,46 @@ const html = await mdast('').toHTML();
|
|
|
50
61
|
### AST 输出
|
|
51
62
|
|
|
52
63
|
```typescript
|
|
64
|
+
// 获取处理后的完整 AST (在 normalization 之后)
|
|
53
65
|
const ast = await mdast('==高亮内容==').toAST();
|
|
54
|
-
|
|
66
|
+
|
|
67
|
+
// 获取原始 AST (在 parse 之后, normalization 之前)
|
|
68
|
+
const rawAst = await mdast('==高亮内容==').toAST({ stage: 'parse' });
|
|
55
69
|
```
|
|
56
70
|
|
|
57
71
|
### 高级工作流
|
|
58
72
|
|
|
59
73
|
```typescript
|
|
60
|
-
|
|
74
|
+
import { htmlReadabilityPlugins } from '@isdk/mdast-plus';
|
|
75
|
+
|
|
76
|
+
const vfile = await mdast(myInput)
|
|
61
77
|
.data({ myGlobal: 'value' })
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
}
|
|
68
|
-
})
|
|
78
|
+
// 以数组形式在 'compile' 阶段添加多个插件
|
|
79
|
+
.use([pluginA, pluginB])
|
|
80
|
+
// 或在特定阶段添加一组插件
|
|
81
|
+
.useAt('parse', htmlReadabilityPlugins)
|
|
82
|
+
.priority(10) // 比默认插件更晚执行
|
|
69
83
|
.to('html');
|
|
84
|
+
|
|
85
|
+
console.log(vfile.value); // 序列化后的 HTML 字符串
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### 插件行为
|
|
89
|
+
|
|
90
|
+
`mdast-plus` 内部使用 [unified](https://github.com/unifiedjs/unified)。如果您多次添加同一个插件函数,最后的配置将**覆盖**之前的配置。
|
|
91
|
+
|
|
92
|
+
```typescript
|
|
93
|
+
// 插件将只执行一次,且选项为: 2
|
|
94
|
+
pipeline.use(myPlugin, { option: 1 });
|
|
95
|
+
pipeline.use(myPlugin, { option: 2 });
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
若要多次运行相同的插件逻辑(例如用于不同目的),请提供不同的函数引用:
|
|
99
|
+
|
|
100
|
+
```typescript
|
|
101
|
+
// 插件将执行两次
|
|
102
|
+
pipeline.use(myPlugin, { option: 1 });
|
|
103
|
+
pipeline.use(myPlugin.bind({}), { option: 2 });
|
|
70
104
|
```
|
|
71
105
|
|
|
72
106
|
### 任意格式支持
|
|
@@ -74,16 +108,20 @@ const { content, assets } = await mdast(myInput)
|
|
|
74
108
|
您可以注册自定义的输入或输出格式:
|
|
75
109
|
|
|
76
110
|
```typescript
|
|
77
|
-
import {
|
|
111
|
+
import { MdastPipeline, mdast, PipelineStage } from '@isdk/mdast-plus';
|
|
78
112
|
|
|
79
113
|
// 注册自定义输出格式
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
114
|
+
MdastPipeline.register({
|
|
115
|
+
id: 'reverse',
|
|
116
|
+
output: [{
|
|
117
|
+
plugin: function() {
|
|
118
|
+
this.Compiler = (tree) => {
|
|
119
|
+
// 您的自定义序列化逻辑
|
|
120
|
+
return '...';
|
|
121
|
+
};
|
|
122
|
+
},
|
|
123
|
+
stage: PipelineStage.stringify
|
|
124
|
+
}]
|
|
87
125
|
});
|
|
88
126
|
|
|
89
127
|
const result = await mdast('Hello').to('reverse');
|
|
@@ -93,11 +131,19 @@ const result = await mdast('Hello').to('reverse');
|
|
|
93
131
|
|
|
94
132
|
## 分阶段处理
|
|
95
133
|
|
|
96
|
-
插件根据它们的 `stage` (阶段)
|
|
134
|
+
插件根据它们的 `stage` (阶段)、`order` (顺序) 以及语义约束 (`before`/`after`) 执行:
|
|
135
|
+
|
|
136
|
+
1. **parse** (0): 输入解析 (例如 `remark-parse`)。
|
|
137
|
+
2. **normalize** (100): 清理并规范化树。
|
|
138
|
+
3. **compile** (200): 高级语义转换。
|
|
139
|
+
4. **finalize** (300): 输出前的最后准备 (例如 `rehype-sanitize`)。
|
|
140
|
+
5. **stringify** (400): 输出生成。
|
|
141
|
+
|
|
142
|
+
### 主插件替换 (Main Plugin Replacement)
|
|
143
|
+
|
|
144
|
+
每个阶段可以有一个“主”插件。如果一个插件被标记为 `main: true`,它将 **替换** 该阶段中的第一个插件。这对于在保持管道其余部分不变的情况下更换默认解析器或编译器非常有用。
|
|
97
145
|
|
|
98
|
-
|
|
99
|
-
2. **compile** (order 0-100): 高级语义转换。
|
|
100
|
-
3. **finalize** (order 0-100): 输出前的最后准备。
|
|
146
|
+
> **注意**: 每个阶段只允许存在一个主插件。如果多个插件被标记为 main,则只有最后定义的那个会作为替换生效。
|
|
101
147
|
|
|
102
148
|
## 内置核心插件
|
|
103
149
|
|
|
@@ -108,6 +154,7 @@ const result = await mdast('Hello').to('reverse');
|
|
|
108
154
|
| `extract-code-meta` | normalize | 从代码块元数据中解析 `title="foo"`。 |
|
|
109
155
|
| `image-size` | normalize | 从图片 URL 中解析 `#=WxH`。 |
|
|
110
156
|
| `normalize-inline-styles` | normalize | 标准化 `==mark==`、`~sub~` 和 `^sup^`。 |
|
|
157
|
+
| `html-readability` | parse | 使用 Mozilla 的 Readability 从 HTML 中提取主体内容。使用 `htmlReadabilityPlugins` 数组可以简化配置。 |
|
|
111
158
|
|
|
112
159
|
## 贡献
|
|
113
160
|
|