1
1
/**
2
2
* @typedef {import("mathup").Options } MathupOptions
3
+ * @typedef {import("markdown-it").default } MarkdownIt
3
4
* @typedef {import("markdown-it/lib/parser_block.mjs").RuleBlock } RuleBlock
4
5
* @typedef {import("markdown-it/lib/parser_inline.mjs").RuleInline } RuleInline
5
6
* @typedef {import("markdown-it/lib/rules_block/state_block.mjs").default } StateBlock
@@ -203,11 +204,12 @@ function createBlockMathRule(open, close) {
203
204
204
205
const token = state . push ( "math_block" , "math" , 0 ) ;
205
206
token . block = true ;
206
- token . content =
207
- ( firstLine && firstLine . trim ( ) ? `${ firstLine } \n` : "" ) +
208
- state . getLines ( startLine + 1 , nextLine , len , true ) +
209
- ( lastLine && lastLine . trim ( ) ? lastLine : "" ) ;
210
207
208
+ const firstLineContent = firstLine && firstLine . trim ( ) ? firstLine : "" ;
209
+ const contentLines = state . getLines ( startLine + 1 , nextLine , len , false ) ;
210
+ const lastLineContent = lastLine && lastLine . trim ( ) ? lastLine : "" ;
211
+
212
+ token . content = `${ firstLineContent } ${ firstLineContent && ( contentLines || lastLineContent ) ? "\n" : "" } ${ contentLines } ${ contentLines && lastLineContent ? "\n" : "" } ${ lastLineContent } ` ;
211
213
token . map = [ startLine , state . line ] ;
212
214
token . markup = open ;
213
215
@@ -216,56 +218,93 @@ function createBlockMathRule(open, close) {
216
218
}
217
219
218
220
/**
219
- * @param {MathupOptions } [options]
221
+ * @typedef {string | [tag: string, attrs?: Record<string, string>] } CustomElementOption
222
+ * @param {CustomElementOption } customElementOption
223
+ * @param {MarkdownIt } md
220
224
* @returns {(src: string) => string }
221
225
*/
222
- function defaultInlineRenderer ( options ) {
226
+ function createCustomElementRenderer ( customElementOption , md ) {
227
+ const { escapeHtml } = md . utils ;
228
+
229
+ /** @type {string } */
230
+ let tag ;
231
+ let attrs = "" ;
232
+ if ( typeof customElementOption === "string" ) {
233
+ tag = customElementOption ;
234
+ } else {
235
+ const [ tagName , attrsObj = { } ] = customElementOption ;
236
+ tag = tagName ;
237
+
238
+ for ( const [ key , value ] of Object . entries ( attrsObj ) ) {
239
+ attrs += ` ${ key } ="${ escapeHtml ( value ) } "` ;
240
+ }
241
+ }
242
+
243
+ return ( src ) => `<${ tag } ${ attrs } >${ escapeHtml ( src ) } </${ tag } >` ;
244
+ }
245
+
246
+ /**
247
+ * @param {MathupOptions } options
248
+ * @param {MarkdownIt } md
249
+ * @returns {(src: string) => string }
250
+ */
251
+ function defaultInlineRenderer ( options , md ) {
223
252
if ( ! mathup ) {
224
- return ( src ) => `< span class= "math inline"> ${ src } </span>` ;
253
+ return createCustomElementRenderer ( [ " span" , { class : "math inline" } ] , md ) ;
225
254
}
226
255
227
256
return ( src ) => mathup ( src , options ) . toString ( ) ;
228
257
}
229
258
230
259
/**
231
- * @param {MathupOptions } [options]
260
+ * @param {MathupOptions } options
261
+ * @param {MarkdownIt } md
232
262
* @returns {(src: string) => string }
233
263
*/
234
- function defaultBlockRenderer ( options = { } ) {
264
+ function defaultBlockRenderer ( options , md ) {
235
265
if ( ! mathup ) {
236
- return ( src ) => `< div class= "math block"> ${ src } </div>` ;
266
+ return createCustomElementRenderer ( [ " div" , { class : "math block" } ] , md ) ;
237
267
}
238
268
239
- return ( src ) =>
240
- mathup ( src . trim ( ) , { ...options , display : "block" } ) . toString ( ) ;
269
+ return ( src ) => mathup ( src , { ...options , display : "block" } ) . toString ( ) ;
241
270
}
242
271
243
272
/**
244
- * @typedef {Record<string, string> } AttrsOption
273
+ * @callback Renderer
274
+ * @param {string } src - The source content
275
+ * @param {Token } token - The parsed markdown-it token
276
+ * @param {MarkdownIt } md - The markdown-it instance
245
277
* @typedef {object } PluginOptions
246
- * @property {string } [inlineOpen]
247
- * @property {string } [inlineClose]
248
- * @property {(src: string, token: Token) => string } [inlineRenderer]
249
- * @property {string } [blockOpen]
250
- * @property {string } [blockClose]
251
- * @property {(src: string, token: Token) => string } [blockRenderer]
252
- * @property {import("mathup").Options } [defaultRendererOptions]
253
- * @typedef {import("markdown-it").PluginWithOptions<PluginOptions> } Plugin
278
+ * @property {string } [inlineOpen] - Inline math open delimiter.
279
+ * @property {string } [inlineClose] - Inline math close delimeter.
280
+ * @property {CustomElementOption } [inlineCustomElement] - If you want to render to a custom element.
281
+ * @property {MathupOptions } [defaultRendererOptions] - The options passed into the default renderer.
282
+ * @property {Renderer } [inlineRenderer] - Custom renderer for inline math. Default mathup.
283
+ * @property {string } [blockOpen] - Block math open delimter.
284
+ * @property {string } [blockClose] - Block math close delimter.
285
+ * @property {CustomElementOption } [blockCustomElement] - If you want to render to a custom element.
286
+ * @property {Renderer } [blockRenderer] - Custom renderer for block math. Default mathup with display = "block".
254
287
*/
255
288
256
- /**
257
- * @type {Plugin }
258
- */
289
+ /** @type {import("markdown-it").PluginWithOptions<PluginOptions> } */
259
290
export default function markdownItMath (
260
291
md ,
261
292
{
262
293
inlineOpen = "$" ,
263
294
inlineClose = "$" ,
264
295
blockOpen = "$$" ,
265
296
blockClose = "$$" ,
266
- defaultRendererOptions,
267
- inlineRenderer = defaultInlineRenderer ( defaultRendererOptions ) ,
268
- blockRenderer = defaultBlockRenderer ( defaultRendererOptions ) ,
297
+ defaultRendererOptions = { } ,
298
+
299
+ inlineCustomElement,
300
+ inlineRenderer = inlineCustomElement
301
+ ? createCustomElementRenderer ( inlineCustomElement , md )
302
+ : defaultInlineRenderer ( defaultRendererOptions , md ) ,
303
+
304
+ blockCustomElement,
305
+ blockRenderer = blockCustomElement
306
+ ? createCustomElementRenderer ( blockCustomElement , md )
307
+ : defaultBlockRenderer ( defaultRendererOptions , md ) ,
269
308
} = { } ,
270
309
) {
271
310
const inlineMathRule = createInlineMathRule ( inlineOpen , inlineClose ) ;
@@ -277,8 +316,8 @@ export default function markdownItMath(
277
316
} ) ;
278
317
279
318
md . renderer . rules . math_inline = ( tokens , idx ) =>
280
- inlineRenderer ( tokens [ idx ] . content , tokens [ idx ] ) ;
319
+ inlineRenderer ( tokens [ idx ] . content , tokens [ idx ] , md ) ;
281
320
282
321
md . renderer . rules . math_block = ( tokens , idx ) =>
283
- `${ blockRenderer ( tokens [ idx ] . content , tokens [ idx ] ) } \n` ;
322
+ `${ blockRenderer ( tokens [ idx ] . content , tokens [ idx ] , md ) } \n` ;
284
323
}
0 commit comments