@@ -36,61 +36,35 @@ function replaceImageSrc(
3636 return publicSrc ;
3737}
3838
39+ interface InlineOptions {
40+ enabled : boolean ;
41+ maxFileSize : number ;
42+ }
43+
3944interface SVGOpts extends MarkdownItPluginOpts {
4045 notFoundCb : ( s : string ) => void ;
4146 imageOpts : ImageOptions ;
47+ svgInline : InlineOptions ;
4248}
4349
44- function convertSvg (
45- token : Token ,
46- state : StateCore ,
47- {
48- file : path ,
49- log,
50- notFoundCb,
51- assets,
52- rootFile,
53- root,
54- forceInlineSvg,
55- imageOpts,
56- rawContent,
57- svgInline : { maxFileSize} ,
58- } : Opts ,
59- ) {
50+ function getSvgContent ( file : string , from : string , { rawContent, notFoundCb, log, root = '' } : Opts ) {
6051 try {
61- let raw = rawContent ( path , assets ) ;
62- if ( ! raw ) {
63- throw new Error ( 'Asset not found' ) ;
64- }
65- raw = raw === true ? '' : raw ;
66- if ( raw . length > maxFileSize ) {
67- if ( forceInlineSvg ) {
68- log . warn ( `Svg size more than in params but forced inline: ${ bold ( path ) } ` ) ;
69- } else {
70- log . info ( `Svg size more than in params: ${ bold ( path ) } ` ) ;
71- token . attrSet ( 'YFM011' , `Svg size more than ${ maxFileSize } ` ) ;
72- return null ;
73- }
74- }
75- const content = raw === '' ? '' : replaceSvgContent ( raw , imageOpts ) ;
76- const svgToken = new state . Token ( 'image_svg' , '' , 0 ) ;
77- svgToken . attrSet ( 'content' , content ) ;
78-
79- return svgToken ;
52+ return rawContent ( file ) ;
8053 } catch ( e : unknown ) {
81- log . error ( `SVG ${ path } from ${ rootFile } not found` ) ;
54+ const path = file . replace ( root , '' ) ;
55+ log . error ( `SVG ${ path } from ${ from } not found` ) ;
8256
8357 if ( notFoundCb ) {
84- notFoundCb ( path . replace ( root , '' ) ) ;
58+ notFoundCb ( path ) ;
8559 }
8660
87- return token ;
61+ return null ;
8862 }
8963}
9064
9165type Opts = SVGOpts &
9266 ImageOpts & {
93- rawContent : ( path : string , assets : Record < string , string | boolean > ) => string | boolean ;
67+ rawContent : ( path : string ) => string ;
9468 calcPath : ( root : string , path : string ) => string ;
9569 replaceImageSrc : (
9670 state : StateCore ,
@@ -99,16 +73,21 @@ type Opts = SVGOpts &
9973 imgSrc : string ,
10074 opts : ImageOpts ,
10175 ) => string ;
102- forceInlineSvg : boolean ;
103- assets : Record < string , string > ;
10476 file : string ;
105- rootFile : string ;
106- svgInline : {
107- enabled : boolean ;
108- maxFileSize : number ;
109- } ;
11077 } ;
11178
79+ function shouldBeInlined ( token : Token , opts : InlineOptions ) {
80+ if ( ! token . attrGet ( 'src' ) ?. endsWith ( '.svg' ) ) {
81+ return false ;
82+ }
83+
84+ const forceInlineSvg = token . attrGet ( 'inline' ) === 'true' ;
85+ const shouldInlineSvg =
86+ forceInlineSvg || ( token . attrGet ( 'inline' ) !== 'false' && opts . enabled !== false ) ;
87+
88+ return shouldInlineSvg ;
89+ }
90+
11291const getRawFile = ( path : string ) => {
11392 return readFileSync ( path , 'utf8' ) . toString ( ) ;
11493} ;
@@ -146,42 +125,41 @@ const index: MarkdownItPluginCb<Opts> = (md, opts) => {
146125 }
147126
148127 const imgSrc = getSrcTokenAttr ( image ) ;
128+ if ( isExternalHref ( imgSrc ) ) {
129+ return ;
130+ }
131+
149132 const forceInlineSvg = image . attrGet ( 'inline' ) === 'true' ;
150- const shouldInlineSvg =
151- image . attrGet ( 'inline' ) === null
152- ? opts . svgInline . enabled !== false
153- : forceInlineSvg ;
133+ const shouldInlineSvg = shouldBeInlined ( image , opts . svgInline ) ;
154134 const imageOpts = {
155135 width : image . attrGet ( 'width' ) ,
156136 height : image . attrGet ( 'height' ) ,
157- inline : shouldInlineSvg ,
158137 } ;
159138
160- if ( isExternalHref ( imgSrc ) ) {
161- return ;
162- }
163-
164- const root = state . env . path || opts . path ;
165- const file = calcPath ( root , imgSrc ) ;
139+ const from = state . env . path || opts . path ;
140+ const file = calcPath ( from , imgSrc ) ;
166141
167- if ( imgSrc . endsWith ( '.svg' ) && shouldInlineSvg ) {
168- const svgToken = convertSvg ( image , state , {
142+ if ( shouldInlineSvg ) {
143+ const svgContent = getSvgContent ( file , from , {
169144 ...opts ,
170145 rawContent,
171- forceInlineSvg,
172- calcPath,
173- imageOpts,
174- rootFile : root ,
175- file,
176146 } ) ;
177- if ( svgToken ) {
178- childrenTokens [ index ] = svgToken ;
179- } else {
180- image . attrSet ( 'src' , replaceImage ( state , root , file , imgSrc , opts ) ) ;
181- image . attrSet ( 'yfm_patched' , '1' ) ;
147+ if ( svgContent ) {
148+ if ( svgContent . length > opts . svgInline . maxFileSize && ! forceInlineSvg ) {
149+ image . attrSet (
150+ 'YFM011' ,
151+ `Svg size: ${ svgContent . length } ; Config size: ${ opts . svgInline . maxFileSize } ; Src: ${ bold ( file ) } ` ,
152+ ) ;
153+ } else {
154+ const svgToken = new state . Token ( 'image_svg' , '' , 0 ) ;
155+ svgToken . attrSet ( 'content' , replaceSvgContent ( svgContent , imageOpts ) ) ;
156+ childrenTokens [ index ] = svgToken ;
157+ }
182158 }
183- } else {
184- image . attrSet ( 'src' , replaceImage ( state , root , file , imgSrc , opts ) ) ;
159+ }
160+
161+ if ( childrenTokens [ index ] . type === 'image' ) {
162+ image . attrSet ( 'src' , replaceImage ( state , from , file , imgSrc , opts ) ) ;
185163 image . attrSet ( 'yfm_patched' , '1' ) ;
186164 }
187165 } ) ;
@@ -201,7 +179,10 @@ const index: MarkdownItPluginCb<Opts> = (md, opts) => {
201179 } ;
202180} ;
203181
204- function replaceSvgContent ( content : string , options : ImageOptions ) {
182+ function replaceSvgContent ( content : string | null , options : ImageOptions ) {
183+ if ( ! content ) {
184+ return '' ;
185+ }
205186 // monoline
206187 content = content . replace ( / > \r ? \n < / g, '><' ) . replace ( / \r ? \n / g, ' ' ) ;
207188
0 commit comments