From ad8afd9794e0ab6f9af46b030a4d367619a60475 Mon Sep 17 00:00:00 2001 From: Syrupy Date: Sun, 28 Jun 2026 22:31:01 +0800 Subject: [PATCH 01/10] chore: update test snap --- src/__snapshots__/tokenize.test.ts.snap | 32 ------------------------ tests/list-complex.docx | Bin 10539 -> 10580 bytes tests/list-number-restart.docx | Bin 8853 -> 8892 bytes tests/markdown.docx | Bin 52693 -> 52776 bytes tests/math-example-from-file.docx | Bin 9671 -> 9985 bytes tests/test-math-comprehensive.docx | Bin 9782 -> 8906 bytes 6 files changed, 32 deletions(-) diff --git a/src/__snapshots__/tokenize.test.ts.snap b/src/__snapshots__/tokenize.test.ts.snap index 1c70787..1bcebf3 100644 --- a/src/__snapshots__/tokenize.test.ts.snap +++ b/src/__snapshots__/tokenize.test.ts.snap @@ -677,14 +677,6 @@ exports[`tokenize > parse images 1`] = ` "raw": "![alt text](https://github.com/adam-p/markdown-here/raw/master/src/common/images/icon48.png "Logo Title Text 1")", "text": "alt text", "title": "Logo Title Text 1", - "tokens": [ - { - "escaped": false, - "raw": "alt text", - "text": "alt text", - "type": "text", - }, - ], "type": "image", }, ], @@ -715,14 +707,6 @@ exports[`tokenize > parse images 1`] = ` "raw": "![alt text][logo]", "text": "alt text", "title": "Logo Title Text 2", - "tokens": [ - { - "escaped": false, - "raw": "alt text", - "text": "alt text", - "type": "text", - }, - ], "type": "image", }, ], @@ -2410,14 +2394,6 @@ exports[`tokenize > render image size 1`] = ` "raw": "![Alt text](image.png "600x400")", "text": "Alt text", "title": "600x400", - "tokens": [ - { - "escaped": false, - "raw": "Alt text", - "text": "Alt text", - "type": "text", - }, - ], "type": "image", }, ], @@ -2437,14 +2413,6 @@ exports[`tokenize > render image size 2`] = ` "raw": "![Alt text](image.png "50%x50%")", "text": "Alt text", "title": "50%x50%", - "tokens": [ - { - "escaped": false, - "raw": "Alt text", - "text": "Alt text", - "type": "text", - }, - ], "type": "image", }, ], diff --git a/tests/list-complex.docx b/tests/list-complex.docx index ef45cc1f76616e6770f0a7b8c2cfc95064a3dd99..788efcb12afe0fea30d0decae6b91fa0916674bc 100644 GIT binary patch delta 5637 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 delta 8911 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 O37#LVXJp*>NBST0R$Qh4 diff --git a/tests/math-example-from-file.docx b/tests/math-example-from-file.docx index cd4142dd377d4d6ededea437d35a52102e6498b3..3515fa0808585ce3d4f974ed80aebfa01db85725 100644 GIT binary patch delta 4883 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 Blz;#L delta 4430 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 UJpbAYJv+LeN0^|Q{iof3077Z;;Q#;t diff --git a/tests/test-math-comprehensive.docx b/tests/test-math-comprehensive.docx index 4641f212735a000eee0febf4114e2701ef2d94ca..e67d9152d6e3eff3605e5b42a11f6d0b8a86b7c9 100644 GIT binary patch delta 4137 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 M1{ny{eCqE10iw}5T>t<8 delta 5035 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 Nf^ZmE1jSF|{{Z$7e(3-J From 8d8a99d01bbd22201fedec81be21aef759f497ab Mon Sep 17 00:00:00 2001 From: Syrupy Date: Sun, 28 Jun 2026 23:14:38 +0800 Subject: [PATCH 02/10] feat: add font theme --- bin/help-texts.mjs | 6 +++ examples/sample-config.json | 8 ++- src/styles/markdown.ts | 17 ++++-- src/styles/styles.ts | 1 + src/types.ts | 8 +++ tests/index.test.ts | 4 ++ tests/list-complex.docx | Bin 10580 -> 10581 bytes tests/list-number-restart.docx | Bin 8892 -> 8892 bytes tests/markdown.docx | Bin 52776 -> 52769 bytes tests/math-example-from-file.docx | Bin 9985 -> 9986 bytes tests/test-math-comprehensive.docx | Bin 8906 -> 8907 bytes tests/theme-CLI.test.ts | 1 + tests/theme-styles.test.ts | 83 +++++++++++++++++++++++++++++ 13 files changed, 121 insertions(+), 7 deletions(-) diff --git a/bin/help-texts.mjs b/bin/help-texts.mjs index 6147c1b..5960690 100644 --- a/bin/help-texts.mjs +++ b/bin/help-texts.mjs @@ -47,6 +47,12 @@ SIZES & SPACING DEFAULT DESCRIPTION spaceSize 6 Paragraph spacing (pt) lineSpacing 1.0 Line spacing multiplier (1.0 = single, 1.5 = 150%) +FONTS DEFAULT DESCRIPTION + bodyFont (unset) Body/paragraph font (e.g., "Times New Roman") + headingFont (unset) Font for all heading levels (e.g., "Arial") + codeFont (unset) Font for code blocks, inline code, HTML, tags (falls back to "Courier New") + blockquoteFont (unset) Font for blockquotes (e.g., "Georgia") + BOOLEANS DEFAULT DESCRIPTION linkUnderline true Whether hyperlinks are underlined diff --git a/examples/sample-config.json b/examples/sample-config.json index dc6f098..e2f420e 100644 --- a/examples/sample-config.json +++ b/examples/sample-config.json @@ -37,6 +37,10 @@ "codeSize": 11, "spaceSize": 6, "lineSpacing": 1.0, - "linkUnderline": true + "linkUnderline": true, + "bodyFont": "Times New Roman", + "headingFont": "Arial", + "codeFont": "Fira Code", + "blockquoteFont": "Georgia" } -} +} \ No newline at end of file diff --git a/src/styles/markdown.ts b/src/styles/markdown.ts index f24328f..0a056c6 100644 --- a/src/styles/markdown.ts +++ b/src/styles/markdown.ts @@ -6,7 +6,7 @@ import { defaultTheme } from './themes' export const createMarkdownStyle = (_theme: Partial): Record => { const theme: IMarkdownTheme = { ...defaultTheme, ..._theme } - + return { space: { className: classes.Space, @@ -23,7 +23,7 @@ export const createMarkdownStyle = (_theme: Partial): Record): Record): Record): Record): Record): Record): Record): Record): Record): Record): Record { spaceSize: 18, codeSize: 20, linkUnderline: false, + bodyFont: "Times New Roman", + headingFont: "Arial", + codeFont: "Fira Code", + blockquoteFont: "Georgia", } }) diff --git a/tests/list-complex.docx b/tests/list-complex.docx index 788efcb12afe0fea30d0decae6b91fa0916674bc..c6d2c1af7a5fa40e352bcd5f9775868b618111a0 100644 GIT binary patch delta 3951 zcmZ8k2UHW=77ax~Y77XW6CnW<=~bjjFQGS)B1H%&MIs<|lmJqtgc?9ZM0zh$BosxE zh=7PxL3n@^>5oX2pZNa!<;|LzGw0m9&pm73J8PZ&*=*E|!Nh=ynhr$1I)hReV3ee{ zxX`)IplQ3lp-oA_6h{%D%ez~GA=*vxH%GWpN3}`ADr>f^3bYQpD^IWzq5A#^Z)rIrtQuieo913F zLS4pIgkN>nP$Fb{q=15tJF5Jl6p_8R>+$x~VzEnxd`SBl_QMA-1p^Imy(COuQ%d(l zF1H94(`!mYp*c5vVw#%hDNuvl{QcjVzGwKJWV`&K>E&|NPe7cR@3$tk2@DURCMS+Db&V!Ao`} z(#_zV?y%GY8;h9MKtu$jM)dmoXDEjF4Cdl$9SlOE?+vSFYm6RCQINf+1_xSPU0$mK zVTtTfjNk#*cb&ee31SkOX=-0x2d_iise{-%Xy~NG)^=Kicmg$fDH4Z3j0UCym$(L= zr#y~hmYR-p6t3z(Lp*luOt0B$ytuKKi zyIRH0NJ#4W6JtofVzBJjB$mE*L0=;(J2@3mPpXtcwHLpz;JGnXC9yG;#mlrCG%q9H zT`^Ci%|=kNslDO%>kGP9`}#rS{YA;ZTm@Mv-~(qadObq=r}!jan{bSi?8~+0<8;qC z7wB?=lt5v9e(7Y*(y6d*P=Fz^BR;4hn1|9#S>8$9zNy!pu$yGPs8m@GiZSVESN9B}LF9HuRl}>KSqV%p7 znDe>Yd_$EMyISAt`rc$sdZQ4(F${|&V-=18;IUCqYTVauVDd}(A#riJNx;|cr$Tpsw=<4Kt@a+`Cm|Dfbgi_rYQ`aiw)cSXjFSnG+7MQb*#|!OU6Kcar@e6}Ttc1M{p0 z<>^}&IvQPaLywN(M?HeOTX|9JL`;q#waYfU)2YEd8$(@PSxG0r{NxDG&O?FO?Od)6 zrn70U8(1624^FU$`&X&BJaTC_xe~j7R<|?(Hhld|rZ(uC^8MKLc|3E{n|q#dQ}ywC zIw1GtuG;-=VMe&>QXSZ1M~pby<+i0f zEVS9?)t1=)bZ(Dy(~Wo`^Ln9(!RvI-@`4l%zl3Kb@0#6XVeeZS!iRL~=dbAd>f4)9dPx|>9i%df{B+UaQPty)Oc|+s}YlBPC{?jeeW81f#-Rc9J zN{@fsZFWA%S3a~LDxzwKxyHWd-9h&_y00eIIr025q{Ts?>H_OQ2|uKv_C=0vuTrbN zFw52Gim^W8@y@<1|8YWfx>8Wuc%g5aJhOOz!q@G*7SoX6I4_fOZC_BVQc~P+ON+ml8jUXS9Z&%<1GK?{fxmt= z?bF{ZUqSVHTx~tT1vsRR&Q+n;T28*X6}i1?dUvQktE4@9*%(2Hch8MAoqt<%YZSjd z&I?=~r?1W(*4ca)q_VoGKk!Bh4Z(chJeuZuXR(N+Vn;AgOf~tBqSbGfu8h8p98x^` zxdcz2o`i1OkBg+doZ<1X&Opsa;bqjQ=;+4ge08_qm`$_&{L_de8VlbC&qCZ-N2m|_#D&s5oMd5 zqvh<$U5%dO&o>QX*^*z&6lNO%xjPpF=hQwUpNTBst2>JGXEa_=;%>>nx^*pTd(k*i z&Rnj~*jXa6HCuOVphE73rh}JxQq`o{^fHRSPIYpyE(<&+Gs5vhuJD&HFt99yM)=;8 zN<%3az$~e9O=>l1H&%8F?ek@4PIKU)d(}-mhpPYEiPjr2ygNf`>9K4OI6!Vp=X0d+ z@)RHth7triPwM$yeOyfZe0qpT4->e2sgb z>e2M$NvG+1I(TOV{sc8zmL1p@dHM$dFuM7X*s2%s?X@Q|3Z-pAsoh|fjf}D)1YOmN zWuDfZX*hf7J}Ak}UqlpOsl>>S+4`zKGJf9s0C6{}31$;r%YJic+C4==((aYfE;z{> zbA^32luAM9MJFd^<~84GdUGYtVLg$ak_Oc(4r;SoC^gJE-jRfPdah0n;AdB|U5afK zCaP^&k$a`xT43DY{tNP~46%40y?v;XfV(u}qYo-G5XtiG)K~*n)Abm~_zgn+C&X*! zR7B@rj?pcQ%*7q$>@{QZRy)j)G|tyDiVKpwll4RiPYUy}N$+e`Y!+sD{=lffic#_oK0rIcyC(FLSt}?7BoSzId zf^$=7VDG?r$xb|+TY;Wb|9_5&328l65Lqw&C3OCIp8ie;0!d+K|4K-K;HJpJ@*-g5 zgz5-x(@8cE$kFfiU9|W=v+)(CW-O6Xd?cMt`v0aPef|0mMvRR7e;~Gsv;-rTfFSdV z-6T1KSO%frj)V|5MJg64#77?SCOPKVc%k2wP>66-YVlxi@$g~Sgc!)f2c+S3ESvCe z8We=NDPChOh57l(ynPBhe&t0fBZTyD|6gG>Ff0Ma`*(^i63QAoBmDOY6fdy6A`)i} I1<9Cy0X+gER{#J2 delta 3953 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 delta 631 zcmdnvy2q6#z?+$civa{8izo6ZG66|_bs)JhLY)yvZEj@LW&zRbSdXy+>B(i>svMEU zcVaYeercM#m|LrU+b*Sry&HJftMM$$d84P|&YNxLVYK>xUFKE4ndQ5E?y2*?x6HM* zUtxB$`SYb0Y@(5ULKp6EtlZ8UwO;HckE)%4ZbY_;$qNp-vzcdgA09in+E^@R!h^{# zF3u~sy&#rjTEd&3d?KGCRZ4iwk7UjGtj-B+~;^gJeS&bPpr-#l8&$Nsd4Gs!>qImvP&99r`y9@t# zUEO(P{~B>l*;)7hS$tuK1vUpTus1XFdN6}R)K@?W6u^Z7yx;(D5Ig{)Cp!rr1W~La z`$4kDL_UB;cZe+maTCPPf)(paegX?COD_cppOW^5s*;~+5LIlMW>_NP62sJ~&2E@Cj09Ki) cBs1AaQ5PhVs0cQF0ff4*2)0sF392j@0O54`g8%>k diff --git a/tests/markdown.docx b/tests/markdown.docx index 65c35f145735186070830756f6cd45c24f3658e1..5f155312e84c56b77545d95d8db7c6f5d25c818f 100644 GIT binary patch delta 7211 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 delta 7348 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 F{|DQHbd>-A diff --git a/tests/math-example-from-file.docx b/tests/math-example-from-file.docx index 3515fa0808585ce3d4f974ed80aebfa01db85725..b849914048591f2f01c5e46b00e7872e527496e6 100644 GIT binary patch delta 940 zcmZqlYx3g>@MdP=VgP|Xl@oasnSi9eI*{BLq0R`THa9X>bAaf7oX1#!^yFjws`Yy+ z@5GpYK0VuP;IiM)NpjbaSzbI9&A~$F0q}c331|n_$y-wE7UgoF1 zw08sVdNrP9IdAk-+dfv~wfB?Tzt7n=>uu=dHwP*+OL{$~EoLz> zcY5X98+N+V%C(c&$=4V zHha8~Sl1h@b7b-DgwsFFZ!_q9s%a8sQHw~}A-t^2VA15D5007jF_*bnj$deClC@Ej zJSc9~5d805v)xXmsXXl5!EYZ^*s9M)qsQ8~+c_AAQ{`Z#s3?Z4q`C?StO$ z8dx9KzwlZx@eHw@&(3NL4KK6+Vj^zT`#I|u#B;yWkJljyse`C_rOi_qz5 z$1k2cdHluCR7>|QC%Qdn`Cm%frSf=E~e-yBYahrc~mIB`{QXMN;(pNR?U(IhiZy`acW6PW?p(RDD|Sdw7bpn$Wfs7V;tz(Gi9OLlk;h$=zz;a0B{)F>vx}H3PPviXi0xxs6#n delta 930 zcmZqjYxLs@@MdP=VgP}N;)y(pOh8g!9Y}7BP-g^En;RLcIY9J3&SR`Vdh#)T)%u9y zJ29^f?y{RPGB7kVF)#=Mb*JPf2NdNO6zeDF7p3Y|`HjQy@kbwS+LWo{~`1DV{m z1kKFty|&ub%DI#Oj>o+%Y*{5N{m<42O{?#^c5rsK?v4cq)GsF6h;DP+EueGsMz?In zyUiXmB=Vw`S9Z8>KRT^De;;eilgdt07QM;`JH(fjnJn5I)D@UnA7jk1#U=LjZW~_jS~Hs`u=mz(w03zbl=W5;x`K9rxjk7X8rWC;_%m&7r%uM$GFT9}- zix3WAgxrbQb$w=x05b!_6fp({Az(0<=NF}H&J@&O2F1l>5hYO6Y!~4LN7XUW10Z^G zhxkDdGNx@J3=Hu_ zsX4_!zcDh2Fo2R9#CP(GCrx_>4|8K(adldV)0K)m&8GE5((Ci6+lPoAmDBM)+-M&Gmt3xMgh zm=%&<5mwEdd_+|t9;Bwb&GN`mpqgVG=xQ=#AwdsJ-MP7`c_qc56prqjOXYvI=K{^G w24We6`9M~T{Nze`IgndGuFD6yj#*){f`SMisu3V}GX_jPqh`SNLlI;E0Md6x8UO$Q diff --git a/tests/test-math-comprehensive.docx b/tests/test-math-comprehensive.docx index e67d9152d6e3eff3605e5b42a11f6d0b8a86b7c9..1a355bd4b44b358aa5921598a3ab463190242dd5 100644 GIT binary patch delta 1051 zcmX@*dfJsIz?+$civa}oR8HhkWCD`<>OgX1ggPUT+T6(K%>ts&u^wXu(vzogtJd$S zyc2UR_UH-=Mh1pvCI$vUpzf6X;Hxc3xZUYU4bS--r8}1h1-9gZt-I52n=@J$`Ujl3UN?L*Vm^^NOMu<#J3*dh=6E z9P}YDvp&X{gXQ>z1}0e> zHO_Y{G8?QDlA&3 zW7}8eXZPv(^s7vvk+Xasmq?{=7M&R|>GH|sN%j-g@4MCeSSfV5(Em;IRIgt6^X>S` zI!0KOZ~&v^PE6hTnQu6l85qRH7#M_r0bQQI*_>C2859@M0!pB$sTbe{M^&HT0T4Yo zK=>et5*FDHlD#7G0W5k;J*jDlrSlCc{DMCkeED0UeOGs1||Zc+29-j zAS(b!#22OJ6zc~7og~5lN}QmOnEYB^#;OD^sRvSms^U&e%*wjBiNHj;m7Re>7;Y+v z(LC8vK}i8*b42BBrAa`MCqRs<##MN7g0Sf1845hHAcc?q%)K=ksOT9GgB*qc93n{R zJ+Ytwl-$vsa{l4-Lx+G)nFI74DB2L<< z5YAVWVN9Ofqo@GltOIh4CZC3I-YUv4sYy?El$M*Usl)>|FZpfUHCdpY&cNh?YUkO> SAxebol$tz6$$;$;*dYK2TwuWf delta 970 zcmX@@ddih2z?+$civa{8iYM|YG66|_bs)JhLY)yvZEj@rW&zRXSdXy+>B-Z$RqG>) z@5JoUTO4lA$iUFd#K0g3)SZ%_98i>BP^_PvUzDm>k(;x0(#5MLnmOmfwKebZjC;^OYuZU3+9|F;Y{`)yTcS;E|$(%wxfu7Vl& zxK^5*M(I8;>{NO_Q*2G9>6I4@d}lL`^433G+gg5GYC~L8cayvIA>ZC@_oSOPK8_AJ zquO{uF=l(1p?qIiGw);j9A*pu%S_rId<@PP==Yq>a8Y0SVDY6tx6%YS`W7;>-m;#f zD!Ffi+?pbOd7hJ^E0@?yRCLTcJn^2jWmD{R)w?MU&i{Gpb?@1=1tzcj?OW)uMQBa| z_nGbW)7F)&naLFRaP{fBM&9B&L9@Nn6z1`V->JR!SgdT*e=ig1j*k&@+w68Zx-8VO z>?`xLQ`cXA+Hz6lEb+pqBb7VPEK|`xvBl@o@=v?hmp$I$adqX9{cF-WWoO<0XYqv} z79$+M7`YQucYfv@4rT@haWMu4Az(O{=NE0ZjMD~MZuZnyCiyjwS2IA(6p9L$nll%l0Hj-Wn622+z4OJyS*;Td^r2m4fA&6p@ zGY3&NavmV6P0kiX9hI{NQB3ltobbdj*+Je6Bv>IY!zey^s=OkIvqN4+!e4-aA-*Uz zr&vD#Xo&~|D7k?=H~EdcjCC { expect(output).toContain('bodySize') expect(output).toContain('linkUnderline') expect(output).toContain('sample-config.json') + expect(output).toContain('bodyFont') }) it('markdown-docx help config outputs config field names', () => { diff --git a/tests/theme-styles.test.ts b/tests/theme-styles.test.ts index 423f207..fbf464e 100644 --- a/tests/theme-styles.test.ts +++ b/tests/theme-styles.test.ts @@ -1,5 +1,6 @@ import { describe, it, expect } from 'vitest' import { createDefaultStyle } from '../src/styles/styles' +import { createMarkdownStyle } from '../src/styles/markdown' import { IMarkdownTheme } from '../src/types' import { defaultTheme } from '../src/styles/themes' @@ -52,3 +53,85 @@ describe('createDefaultStyle', () => { expect(style2.document?.paragraph?.spacing?.line).toBe(240) // 1.0 default → 240 twips }) }) + +describe('createMarkdownStyle font-family', () => { + const defaultStyles = createMarkdownStyle({}) + + it('code font defaults to "Courier New" when codeFont is not set', () => { + expect(defaultStyles.code.run?.font).toBe('Courier New') + }) + + it('code font uses custom codeFont when set', () => { + const styles = createMarkdownStyle({ codeFont: 'Fira Code' }) + expect(styles.code.run?.font).toBe('Fira Code') + }) + + it('codespan font defaults to "Courier New" when codeFont is not set', () => { + expect(defaultStyles.codespan.run?.font).toBe('Courier New') + }) + + it('codespan font uses custom codeFont when set', () => { + const styles = createMarkdownStyle({ codeFont: 'JetBrains Mono' }) + expect(styles.codespan.run?.font).toBe('JetBrains Mono') + }) + + it('html font defaults to "Courier New" when codeFont is not set', () => { + expect(defaultStyles.html.run?.font).toBe('Courier New') + }) + + it('tag font defaults to "Courier New" when codeFont is not set', () => { + expect(defaultStyles.tag.run?.font).toBe('Courier New') + }) + + it('tag font uses custom codeFont when set', () => { + const styles = createMarkdownStyle({ codeFont: 'Source Code Pro' }) + expect(styles.tag.run?.font).toBe('Source Code Pro') + }) + + it('heading font is omitted when headingFont is not set', () => { + expect(defaultStyles.heading1.run?.font).toBeUndefined() + expect(defaultStyles.heading2.run?.font).toBeUndefined() + expect(defaultStyles.heading3.run?.font).toBeUndefined() + expect(defaultStyles.heading4.run?.font).toBeUndefined() + expect(defaultStyles.heading5.run?.font).toBeUndefined() + expect(defaultStyles.heading6.run?.font).toBeUndefined() + }) + + it('heading font is applied to all heading levels when headingFont is set', () => { + const styles = createMarkdownStyle({ headingFont: 'Georgia' }) + expect(styles.heading1.run?.font).toBe('Georgia') + expect(styles.heading2.run?.font).toBe('Georgia') + expect(styles.heading3.run?.font).toBe('Georgia') + expect(styles.heading4.run?.font).toBe('Georgia') + expect(styles.heading5.run?.font).toBe('Georgia') + expect(styles.heading6.run?.font).toBe('Georgia') + }) + + it('blockquote font is omitted when blockquoteFont is not set', () => { + expect(defaultStyles.blockquote.run?.font).toBeUndefined() + }) + + it('blockquote font is applied when blockquoteFont is set', () => { + const styles = createMarkdownStyle({ blockquoteFont: 'Georgia' }) + expect(styles.blockquote.run?.font).toBe('Georgia') + }) + + it('paragraph font is omitted when bodyFont is not set (body font handled at document level)', () => { + expect(defaultStyles.paragraph.run?.font).toBeUndefined() + }) + + it('combines multiple font theme options', () => { + const styles = createMarkdownStyle({ + headingFont: 'Arial', + codeFont: 'Fira Code', + blockquoteFont: 'Times New Roman', + }) + expect(styles.heading1.run?.font).toBe('Arial') + expect(styles.code.run?.font).toBe('Fira Code') + expect(styles.blockquote.run?.font).toBe('Times New Roman') + // code-related fonts all use codeFont + expect(styles.codespan.run?.font).toBe('Fira Code') + expect(styles.html.run?.font).toBe('Fira Code') + expect(styles.tag.run?.font).toBe('Fira Code') + }) +}) From ad77c1670dde534579075d0597608863be32cd97 Mon Sep 17 00:00:00 2001 From: Syrupy Date: Mon, 29 Jun 2026 12:27:16 +0800 Subject: [PATCH 03/10] feat: add image horizontal align theme --- bin/help-texts.mjs | 3 + examples/sample-config.json | 3 +- src/renders/render-image.ts | 17 ++++- src/renders/render-paragraph.ts | 4 +- src/types.ts | 5 ++ tests/index.test.ts | 1 + tests/list-complex.docx | Bin 10581 -> 10583 bytes tests/list-number-restart.docx | Bin 8892 -> 8892 bytes tests/markdown.docx | Bin 52769 -> 52862 bytes tests/math-example-from-file.docx | Bin 9986 -> 9987 bytes tests/test-math-comprehensive.docx | Bin 8907 -> 8910 bytes tests/theme-styles.test.ts | 112 ++++++++++++++++++++++++++++- 12 files changed, 138 insertions(+), 7 deletions(-) diff --git a/bin/help-texts.mjs b/bin/help-texts.mjs index 5960690..c6d73b3 100644 --- a/bin/help-texts.mjs +++ b/bin/help-texts.mjs @@ -56,6 +56,9 @@ FONTS DEFAULT DESCRIPTION BOOLEANS DEFAULT DESCRIPTION linkUnderline true Whether hyperlinks are underlined +ALIGNMENT DEFAULT DESCRIPTION + imageHorizontalAlign left Image horizontal alignment ("left", "center", or "right") + See examples/sample-config.json for a ready-to-use config file. `.trim() diff --git a/examples/sample-config.json b/examples/sample-config.json index e2f420e..9eabdd8 100644 --- a/examples/sample-config.json +++ b/examples/sample-config.json @@ -41,6 +41,7 @@ "bodyFont": "Times New Roman", "headingFont": "Arial", "codeFont": "Fira Code", - "blockquoteFont": "Georgia" + "blockquoteFont": "Georgia", + "imageHorizontalAlign": "center" } } \ No newline at end of file diff --git a/src/renders/render-image.ts b/src/renders/render-image.ts index e57f04a..1c90ff8 100644 --- a/src/renders/render-image.ts +++ b/src/renders/render-image.ts @@ -1,9 +1,11 @@ -import { ImageRun } from 'docx' +import { ImageRun, Paragraph } from 'docx' import { Tokens } from 'marked' import { MarkdownDocx } from '../MarkdownDocx' import { ITextAttr, MarkdownImageItem } from '../types' import { renderText } from './render-text' +import { renderParagraph } from '.' + export function renderImage(render: MarkdownDocx, block: Tokens.Image, attr: ITextAttr) { if (render.ignoreImage) { @@ -18,10 +20,21 @@ export function renderImage(render: MarkdownDocx, block: Tokens.Image, attr: ITe const { width, height, title } = parseImageTitleSize(block, image) + + const theme = render.options.theme + const imageHorizontalAlign = theme?.imageHorizontalAlign ?? "left" + + if (imageHorizontalAlign !== "left" && !attr.isAligned) { + return renderParagraph(render, [block], { + align: imageHorizontalAlign, + ...attr + }) + } + return new ImageRun({ type: image.type, data: image.data, - transformation: { width, height }, + transformation: { width, height, }, altText: { title: title || block.text, description: block.text, diff --git a/src/renders/render-paragraph.ts b/src/renders/render-paragraph.ts index 8bdc51f..f7945dc 100644 --- a/src/renders/render-paragraph.ts +++ b/src/renders/render-paragraph.ts @@ -7,7 +7,7 @@ import { renderCheckbox } from './render-checkbox' import { renderText } from './render-text' import { renderTokens } from './render-tokens' -export function renderParagraph (render: MarkdownDocx, tokens: IInlineToken[] | string, attr: IBlockAttr) { +export function renderParagraph(render: MarkdownDocx, tokens: IInlineToken[] | string, attr: IBlockAttr) { const heading = getHeadingLevel(attr.heading) const alignment = getTextAlignment(attr.align) @@ -25,7 +25,7 @@ export function renderParagraph (render: MarkdownDocx, tokens: IInlineToken[] | style: attr.style } - const children = typeof tokens === 'string' ? renderText(render, tokens, {}) : renderTokens(render, tokens, {}) + const children = typeof tokens === 'string' ? renderText(render, tokens, { isAligned: !!alignment }) : renderTokens(render, tokens, { isAligned: !!alignment }) if (attr.list?.task) { children.unshift(renderCheckbox(render, attr.list.checked)) diff --git a/src/types.ts b/src/types.ts index 1af9fc5..b501964 100644 --- a/src/types.ts +++ b/src/types.ts @@ -118,6 +118,7 @@ export type ITextAttr = { del?: boolean br?: boolean + isAligned?: boolean } export type IBlockAttr = { @@ -222,4 +223,8 @@ export type IMarkdownTheme = { codeFont?: string // Font for code blocks, inline code, HTML, and tags. Optional, falls back to "Courier New" in code when unset. blockquoteFont?: string // Font for blockquotes. Optional. + /** + * Image horizontal alignment + */ + imageHorizontalAlign?: "left" | "center" | "right" } diff --git a/tests/index.test.ts b/tests/index.test.ts index 6003b4d..39facb2 100644 --- a/tests/index.test.ts +++ b/tests/index.test.ts @@ -53,6 +53,7 @@ describe('markdown-docx', () => { headingFont: "Arial", codeFont: "Fira Code", blockquoteFont: "Georgia", + imageHorizontalAlign: "center", } }) diff --git a/tests/list-complex.docx b/tests/list-complex.docx index c6d2c1af7a5fa40e352bcd5f9775868b618111a0..a17a295781b59a6a269e6708a6f7f831e86bb77c 100644 GIT binary patch delta 4007 zcmZ8kcRZVI_fPDqRn#Ve7)6EJTh$hO)~>x3F=_YCm&;9va=d00}5v73+ArU#?f`q}}P?Vg67YxdK<(ye3 zyqbhTP<8@{e!Vs*MTcEMcUB>50>Rz7tDKvkiJy~p8c7M`lxSbTef4=q%h2lBTn&Vt z;@Leb%W^qLp06K9QkJ_~8hp*o=jq+}gz%*bDQc%rcQHsOCcVFkKPZx$*Ys;Xbj#*H zXd=LddkL*33nUs-sIC&#CP?W5viQ0b;HuRAKbXA{PZR24qTGg=7r!v++ROig{+Lobzy&=9Gta=?!Ta%k|}6c;!J0 zqimscX{@y0uP!O$*ai{ynBfim)xgPRd0Tv7C7B~SbE!`e_33aPw z$$g6=fWmaUXetu73rUN7?jU6cw%h2%O*rNYQ7)!4Ons|iq78lAG6I5P-3}XW&7_2+ z2ySN8_(qzrh#1Wm(vZ$iAqokci$gcF8;9zea$JXLe>SVFA++ax#5VC0U-!_O#LN1T>{#9cx(?{bD%5~y|r>NV?E@w zzMRmzEpxY#`&CC1(TU1cBvDYLs1LV^zT4Z#G=o|oe~xekVXKL^GP&ExI?4k&Hp^t> z#XW@SNPZy6MJfKMrsdW4ZLw)Us&$5A(vk;}F z2J>-qoxmSEe)tHsk1t<$Jbp(2RpZglHMlo3*_(oqUx3V{7GG-d~^`+97yS21qd<=1OeD93+1ckh3P>K&^r)y4u1=0hb8x=a6;BQ$n z8#aN|PFywAwi?rQN~XY^U-!_XyUw2X%A2-B;Pa-UN*%|D4RXhmngjt65rw)6{kTFU z6_R%h(^GQS(w^;+WJ`wF6qlg@M)Mw;4?XYP_&)11KK7y#`t=rD8G&zlGaT8942 z)>H`zAKYD#fWtJ8$hC>oNzhb& z@S}|s*zj}G4HM-$g5j{BJy~&TO=UyQPn*SR-Mq@p&murZZQg~Y_f8kqHp6~>2bJx_ znK+N9Z8j3iUytt@4!k?$yK#&V`K4dIF7Y*0D=&Y+*4i8L9B!kZoE*RV6m&|bq%4yK z<;)@Tu|G_YS3lc0o1?Mq^2=GN$-(qN{fwi?+rd=XD#_wFVb2j6(_Z-J=ELMW!mn0J_R1Ib>1 zv90PAc8!YHEM2ESinaP zNpp+7WR95USxv1C57=ZfLy_&Z#Vw_&=ERA9^BH>HWE9Zrsk!cUA@sMIphHA+t>dfk z^<&67mi}OS6U#V?%#{Z^~1(bqcuj-<+HU@H@IuB!ZqL z8|*srUZqrv{tDt_lDuovk=TG8$k`wh-n zgYtH@bq#&G3`cCUJ&@J_G3*VCS2;9?yW@15GG&J6UJecqyfnm?9t4uaM?ZlFY{m4C z3cao}6Mk)iD<@ODDi9U4{GG=3$o+O73=6aUoT+;B69^I=U2yt+8nSb+xf}199wHJf z%^X=a6!;t^LARqVtWkh-b?7yJb+91@>-!pHt(gCPCL2*>Z70rBhC=LNT&m?H&&*!h zzWH0?I$6DgjyW8ts-mHQ>5Y_!!=37j=hY&^Vp@1jK2ruh`^iMS>hYxufdK4~ zUTLrU$RV$_NYY@=s7VpKNOJeIJ@bQU{j|(!;CjlnBsPz+h`Qck`Fv%EzosbefRAw! zaIZMG^$r2@>$o*7&~jje}WR^?W2aCk=gWT~meO(i+ja*H$b z7m68?R2hN$_=C`+$?%=AiMx4TcjJ`kVhV}Ga?*kn)bY#-B%J8U^Wg*9R7jC=X_c_3yJ*_~L$5C6WCEqh@ipl}+b#s&na&W{r z98Ys;q@=S{Td9ze+$ZGc{fuiic~<$NB$T7@YnSS`WQm$0F&{f~#$=tM;`aqA^{vuI!gXCuYsWy5!;bj6>W9z;y+V-n~?r*`qzWl$_` z8Nsj63*Du)@{P7~ir(z}K_2j+$mxc_>lM$7gGXq0mZ5p}w`aaJe58D0Xnf}<);-|U zeHDUMKiVX-T0lq3p{aj`ycQ=%boZi#Qk*v;McmjxHGP37fQd_sp~;8YdpKzjCimX+ zilZPAIukq%{NjXpgJaVQLhVf|D%7gjn3}0pVl>zK9=1xXA5+S5ccP{r9!)KXc$F3A zu^0VtTbJ-|ZZB!GIT{UEZ-F(t)L}aCDzkFxvnBe4-8!xtU7{Q91NL7VcE(vmEaDLr z8&w)x9ifT~%i0I3TyR?C%GOa9Yj^5dVKgD#qbTpG29J+9xRL#0+uN(JP8#7_kRr)P z5sVMC^K*kWCZ9u6Lck)hWLdj)lcU_u!`#j>1~m+CF%g3BBMV)O_lx(Ss`a_vaGYR< z>_f2+Fb_T0TR~z6Ke+dG+}W{%8LCAXFC-~1VgjC!*A?Mq@?17gKlSZs`aGf9%tTh=unM%@6O zi4baMbrVJ{y&~fF;~8sv zs@UUwE1f62G}GdFuk~K}a|a`Q5F=VST7O{>Ij&LDs;VSBEpJr`nVS-*=RL|MMH<%ZJ^+tXGkCQw0*X5-5bLBeLOX^k8Jo7;!gcoPM2rXv0|Ad;sq!={zj_muXcl(is9#*6~FvL+a&ujxTO^H zz_`+v?D(-mhY^#tNMkmdGUAGQLWYDq!7PtL<&nSE-rL#tgj=-3Dj<)G+O8i;t=}h= zn?OKbQn!bcs_UzQzHz2le2`5F(o^K^7wM6CLoCppn(8iUlM?q-x8zN4q4Vii^Tzwu z`D-Q%cB9p?R5)J*8~*CQx?NpBr$l(!>JX~eVl{yEkK+WF)C1kS(oIB{wJC%otq$BGAf$&+{_|GTrHaXc!Z zzqgR{_3k(9;#2>VO3=cP%ViI30AU5Hp}im+mpF+KR%uFF0Km!D(ZJu=FF?dV2S`8< zxL6VYEH?k1o_|7$qvs%;muacqZ#|(UJWt680Gwm}gI=ORyx_~2e;5HIe=9WS(lpwR z_qzN=`JlX%wB>V4-}$6o{X6DTI7hbgclHVpxq0#YpCZwfysSWKbT2R0+U)aup+v>jzX|MgVQoAd9+SfXe7|IP+1 OM1usNBzim-wf!GiZxPD? delta 4143 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 delta 726 zcmdnvy2q6_z?+$civa`#z-|r5WTsHQHur4SkHQt6~vfa&aF}p zq+|F$a@LzOGB7kVF)#=M%}B{l4k*emDArHTFG|&`$jw{molT+Oj98?%VZ7{Kf}?>35fzb3M8IuXa zGQr}70~9YY>$Kv|N-;Aqa7!>S2m!;nJilnO1g|kOI5PYM6v44mB)|iSuSUWBV8&!; z;R9e5Y$E%>Dvpc1he+%cTM8CP6h8yeVj%euBBLU`1T1q}+6$&sZnBwdC)k`rvIb!K ztE?HA){}Dw(-m?yV0ycp6`1}aXTkwX9+M5^&B20M^0r`lmAoOCz9$bcL|nlR%#VQ5 nGZn1C{Obx3^;t^NlZ_O0!D2~@5Q`Q<=?97s2WTn5)CK_n*g`+w diff --git a/tests/markdown.docx b/tests/markdown.docx index 5f155312e84c56b77545d95d8db7c6f5d25c818f..11475687bf40ebf675b00c50022cf3c8c8ec9e33 100644 GIT binary patch delta 9105 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 delta 8926 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 diff --git a/tests/math-example-from-file.docx b/tests/math-example-from-file.docx index b849914048591f2f01c5e46b00e7872e527496e6..2bea885c603c535312d8604e3704999031044145 100644 GIT binary patch delta 962 zcmZqjYxd&}@MdP=VgP|n3U?>+Dlmg612qt}F;a~YL~m|ltl|JO{&OB>1u-Tc=U1r* z(lG}01^E_?3=GXo3=D!mGg9)C1B&tsiuIH8i&FI}a&wkWiuFHaAky~#)TQ5RZwp*W z)9#d7r(!6$=;OLf{tG+mmaOIZxA$%X<3wxy+uvVK{yt~ztal-ka}HK!mh^V%xN~OY zwOn~Er7OPq3!|!?fo?>y$(0O#Ip55qy7do_9h_|}7Bk_&;-H>Q^=JB#{p(B_7HT|Alx}$mRn|(sMRY?|M#~1SF33%#w z^DUk`ssG~V(@AX^GpA2BnZM-eW2ODdKWFs3+x&6IpI575Ezbp&>U`9H?dkOU*>!uq zzpSu`;Q&QU%&zM*V+5EP7^a9ZFbDwyx;%e#x}X*_I5MV)D1u{WhX@ZOzK)CT2Qwyj ziXQ;0@R8UDR>3Rz9wPByYAIM?x%3%`mNMCo5Sc9bC14pr1uvLVxydz(onUh~lnlVM zwUQZ_E>Us^)BBWc!1P}wD==-PY{Cgo9+S(JA*wehOEY>*KBKG%R`Wqw+O$K2fg!#q zHK$lVz?+dtgaMQgA^w$LJZai9AnzP7VQ~X#1XwfKK}8B|Lad53A08` zl8zD9&7OQjRUsavrn}AZ$Wfr0V;tyevSdLKQj`Kr^|`sJc_qc5l#lMCOXYvI=K{^G x24We6`9M~j{Nze`Ignexjx7K>k5yr^f`SM?ni-RUE@upyd`8WH?Uy3R2msMzVD$h1 delta 911 zcmZqnYx3g_@MdP=VgP|Xm3JocDlmg612qt}F;a~YL~m|ltl|JO{&OB>1u-Tc=U1r* z(lO?rPtP`IWMF7!Vqg#invs&998i>BP^_PvUzDm>k(;x0Qf&4i1Ch4>UMFj3FY{Ah z+Pi^wy&BK5oHu$Z?!4J{9!9JG*JWN^b!K<0+WX1v-{)+b^)__!n*)`ZCA}Wg7PFX` zJH7Jl4Le}7gtm_TdIkNb6!s#F8w;A+4)ijB+s6`~~5MEYhuxN772gl6%n9JNO$1gN6$=aw% z9uzlg2>$o3*>0!OR33Kj@{7e57pnEyH{{-4Bl|VujsJ(|kG}4eH=Vlcwg|h6_CfD= z4XlsrUwAE_r70k~Z`T{K8wT=Xg_pBAAH6I%`uD8Wor8X5@tu?AN%URKe6d*CMdRChWMh? zoMND78JR>FK*k diff --git a/tests/test-math-comprehensive.docx b/tests/test-math-comprehensive.docx index 1a355bd4b44b358aa5921598a3ab463190242dd5..a460f5eee956bac70eb52484f30445273facac76 100644 GIT binary patch delta 1003 zcmX@@dd`(Mz?+$civa{SDcqgNtH2DR4Ael>#z-|r5WTsH(TfGlIL~^N6~vf4om-_I zNXJxggnhJTWMF7!Vqg#invs&998i>BP^_PvUzDm>k()DhQfz*cfk@kbu9vo376iL9 zOwRq7rRKft=BC}tY_p7iP248@_q+Crj+y4WbM7zqzgN6qhJ1?b+k;jMLpv|EEZ`8i z9J3;~^V(`x8|R6iLkgp^Syio?oIkHhP^(YBb!hfgwl(4p7Ci{mOJC+<{oc24W3u&x zE2@nFigz-!SMs~>KH9b^e;4ZuT8U!kDF>VjkVUcJn~h#E{s} zx8;}rVui&G2Pkf0>dw!6!@9i?Rk_ znnlhGOxw!2gXwlT8!&xL&I(L3%bRe*lgDHSd5G#td1*%J$y4PO!D@EOOG^d|Ffhay zrREgt2Y53wi7Ets|-g_WVb27J*Hdv*lk~HIm$)QS+zy%t` PC_8zok^$RMS&%~j^IB>K delta 916 zcmX@-dfJsYz?+$civa}oRNk4$tH2DR4Ael>#z-|r5WTsH(TfGlIL~^N6~vf4om-_I zNXJ}@J-Whzk%6I^iGe{7XhuqYazIgjL9u>veo?AkMQ+a0NwN7&1|n_$xn9~%IaIQY z(P!Jy)iZTwrk#E_>s!a!7w)(GzTD>z2sD0Qc5|Qq{5{Vd4DYX2yVdyl(hH%9Dz1VV zc`a8;JFl&FwQ-)v@56mff>+h5!Ts~92h-|{9zQrM$*t${A@KRdc}3BSayh0Yz4<97 z^4Zhw?ImZ~x4icM@ch%)S_#u>yY7pyhln-> zziVK9T)%2-pJ}iHS54_n{SAqBI=g-IRXUa*7X5Dix{%%aX8qDGo+A}He$MiD6&9`2 zvF$7Kv-|XX`cM^L_ucA!tQ5Lj=>Mj9s#h=k`F4C| z9V0AaI6x5-Q+Iym8xCd$25~V41|eWTm*;P`=2c<_M@E8xA~<$h1b86vHCb>!m@zq2 z_yAaigvdUyikl+uArhy>mVyO}#m_*rI7xnl$e2kl0n6N#_JS#uo9rRm2{z}7tO1y2 zmoo#?4sz~bx=YRmOrMmq0@G~rCY?)%f}(-~$obuE zmPd{P)g0qMS7RhOIZ#p { it('converts bodySize (pt) to half-points for docx', () => { @@ -46,7 +53,7 @@ describe('createDefaultStyle', () => { const theme: IMarkdownTheme = { ...defaultTheme, bodySize: undefined } const style = createDefaultStyle(theme) expect(style.document?.run?.size).toBe(24) // 12pt default → 24 half-points - + // lineSpacing defaults to 1.0 (from defaultTheme) const theme2: IMarkdownTheme = { ...defaultTheme, lineSpacing: undefined } const style2 = createDefaultStyle(theme2) @@ -135,3 +142,104 @@ describe('createMarkdownStyle font-family', () => { expect(styles.tag.run?.font).toBe('Fira Code') }) }) + +// --------------------------------------------------------------------------- +// renderImage – imageHorizontalAlign +// --------------------------------------------------------------------------- + +describe('renderImage horizontal alignment', () => { + + // --------------------------------------------------------------------------- + // Helpers for image alignment tests + // --------------------------------------------------------------------------- + + function createMockImageToken(overrides: Partial = {}): Tokens.Image { + return { + type: 'image', + raw: '![test](https://example.com/test.png)', + href: 'https://example.com/test.png', + title: '', + text: 'test image', + tokens: [], + ...overrides, + } + } + + function createMockImageItem(overrides: Partial = {}): MarkdownImageItem { + return { + type: 'png', + data: Buffer.from('fake-image-data'), + width: 100, + height: 200, + ...overrides, + } + } + + function createImageRenderer(themeOptions: Partial = {}) { + const renderer = new MarkdownDocx('', { theme: themeOptions }) + renderer['_imageStore'].set('https://example.com/test.png', createMockImageItem()) + return renderer + } + + it('returns ImageRun directly when imageHorizontalAlign is not set (defaults to left)', () => { + const render = createImageRenderer() + const result = renderImage(render, createMockImageToken(), {}) + expect(result).toBeInstanceOf(ImageRun) + }) + + it('returns ImageRun directly when imageHorizontalAlign is explicitly "left"', () => { + const render = createImageRenderer({ imageHorizontalAlign: 'left' }) + const result = renderImage(render, createMockImageToken(), {}) + expect(result).toBeInstanceOf(ImageRun) + }) + + it('wraps in Paragraph with center alignment when imageHorizontalAlign is "center"', () => { + const render = createImageRenderer({ imageHorizontalAlign: 'center' }) + const result = renderImage(render, createMockImageToken(), {}) + expect(result).toBeInstanceOf(Paragraph) + expect(result!.toString()).toContain('alignment="center"') + }) + + it('wraps in Paragraph with right alignment when imageHorizontalAlign is "right"', () => { + const render = createImageRenderer({ imageHorizontalAlign: 'right' }) + const result = renderImage(render, createMockImageToken(), {}) + expect(result).toBeInstanceOf(Paragraph) + expect(result!.toString()).toContain('alignment="right"') + }) + + it('returns ImageRun directly when isAligned is true regardless of theme alignment', () => { + const render = createImageRenderer({ imageHorizontalAlign: 'center' }) + const result = renderImage(render, createMockImageToken(), { isAligned: true }) + expect(result).toBeInstanceOf(ImageRun) + expect(result!.toString()).not.toContain(' { + const renderer = new MarkdownDocx('', { ignoreImage: true }) + const result = renderImage(renderer, createMockImageToken(), {}) + expect(result).toBe(false) + }) + + it('falls back to text when image is not in store', () => { + const renderer = new MarkdownDocx('', { theme: { imageHorizontalAlign: 'center' } }) + const result = renderImage(renderer, createMockImageToken(), {}) + expect(Array.isArray(result)).toBe(true) + }) + + it('preserves other text attributes when wrapping in aligned Paragraph', () => { + const render = createImageRenderer({ imageHorizontalAlign: 'center' }) + const result = renderImage(render, createMockImageToken(), { style: 'MyStyle' }) + expect(result).toBeInstanceOf(Paragraph) + const str = result!.toString() + expect(str).toContain('alignment="center"') + expect(str).toContain('style="MyStyle"') + }) + + it('center-aligned Paragraph contains the ImageRun as child', () => { + const render = createImageRenderer({ imageHorizontalAlign: 'center' }) + const result = renderImage(render, createMockImageToken({ text: 'alt text' }), {}) + const str = result!.toString() + expect(str).toContain(' Date: Mon, 29 Jun 2026 13:19:26 +0800 Subject: [PATCH 04/10] feat: add imageDefaultSize theme --- bin/help-texts.mjs | 3 + examples/sample-config.json | 3 +- src/renders/render-image.ts | 72 +++++++- src/types.ts | 10 ++ tests/index.test.ts | 1 + tests/list-complex.docx | Bin 10583 -> 10584 bytes tests/list-number-restart.docx | Bin 8892 -> 8893 bytes tests/markdown.docx | Bin 52862 -> 52852 bytes tests/math-example-from-file.docx | Bin 9987 -> 9986 bytes tests/test-math-comprehensive.docx | Bin 8910 -> 8906 bytes tests/theme-styles.test.ts | 278 +++++++++++++++++++++++++---- 11 files changed, 328 insertions(+), 39 deletions(-) diff --git a/bin/help-texts.mjs b/bin/help-texts.mjs index c6d73b3..8773fee 100644 --- a/bin/help-texts.mjs +++ b/bin/help-texts.mjs @@ -59,6 +59,9 @@ BOOLEANS DEFAULT DESCRIPTION ALIGNMENT DEFAULT DESCRIPTION imageHorizontalAlign left Image horizontal alignment ("left", "center", or "right") +IMAGE SIZING DEFAULT DESCRIPTION + imageDefaultSize actual Image sizing behavior: "actual" (native size), "auto" (scale down to fit page, no upscale), "fit" (scale to fill page, may upscale) + See examples/sample-config.json for a ready-to-use config file. `.trim() diff --git a/examples/sample-config.json b/examples/sample-config.json index 9eabdd8..11ee561 100644 --- a/examples/sample-config.json +++ b/examples/sample-config.json @@ -42,6 +42,7 @@ "headingFont": "Arial", "codeFont": "Fira Code", "blockquoteFont": "Georgia", - "imageHorizontalAlign": "center" + "imageHorizontalAlign": "center", + "imageDefaultSize": "auto" } } \ No newline at end of file diff --git a/src/renders/render-image.ts b/src/renders/render-image.ts index 1c90ff8..aab0ff4 100644 --- a/src/renders/render-image.ts +++ b/src/renders/render-image.ts @@ -6,6 +6,20 @@ import { ITextAttr, MarkdownImageItem } from '../types' import { renderText } from './render-text' import { renderParagraph } from '.' +/** + * Maximum image dimensions in "pixels" (at 96 DPI) for an A4 page with 1" margins. + * A4 = 210mm × 297mm → 8.27" × 11.69" at 96 DPI. + * Subtract 1" margin on each side (2" total): + * Usable width: 8.27" - 2" = 6.27" → 6.27 × 96 ≈ 602px + * Usable height: 11.69" - 2" = 9.69" → 9.69 × 96 ≈ 931px + * + * - "auto": scale down only when either dimension overflows; never upscale. + * - "fit": scale so one axis reaches exactly its max (may upscale small images). + * Like Word's "fit to page". + */ +const MAX_IMAGE_WIDTH_PX = 602 +const MAX_IMAGE_HEIGHT_PX = 931 + export function renderImage(render: MarkdownDocx, block: Tokens.Image, attr: ITextAttr) { if (render.ignoreImage) { @@ -18,12 +32,16 @@ export function renderImage(render: MarkdownDocx, block: Tokens.Image, attr: ITe return renderText(render, `[!${block.text}](${block.href})`, attr) } - const { width, height, title } = parseImageTitleSize(block, image) - + const { width, height, title, isExplicitSize } = parseImageTitleSize(block, image) const theme = render.options.theme + const imageDefaultSize = theme?.imageDefaultSize ?? "actual" const imageHorizontalAlign = theme?.imageHorizontalAlign ?? "left" + // Scale down oversized images to fit page margins ("auto" mode). + // Explicit sizes (from title attribute) are never scaled. + const finalSize = scaleImageToFit(width, height, imageDefaultSize, isExplicitSize) + if (imageHorizontalAlign !== "left" && !attr.isAligned) { return renderParagraph(render, [block], { align: imageHorizontalAlign, @@ -34,7 +52,7 @@ export function renderImage(render: MarkdownDocx, block: Tokens.Image, attr: ITe return new ImageRun({ type: image.type, data: image.data, - transformation: { width, height, }, + transformation: { width: finalSize.width, height: finalSize.height }, altText: { title: title || block.text, description: block.text, @@ -57,7 +75,8 @@ export function parseImageTitleSize(block: Tokens.Image, image: MarkdownImageIte return { width: image.width, height: image.height, - title: block.title + title: block.title, + isExplicitSize: false, } } @@ -68,6 +87,49 @@ export function parseImageTitleSize(block: Tokens.Image, image: MarkdownImageIte width, height, // remove title - title: '' + title: '', + isExplicitSize: true, + } +} + +/** + * Scale image dimensions to fit within page margins when imageDefaultSize is "auto". + * Images wider than MAX_IMAGE_WIDTH_PX are scaled down proportionally. + * Images already within bounds are left unchanged (no upscaling). + * Explicit sizes (from title attribute) are never scaled. + */ +export function scaleImageToFit( + width: number, + height: number, + imageDefaultSize: "actual" | "auto" | "fit", + isExplicitSize: boolean = false, +): { width: number; height: number } { + if (imageDefaultSize === "actual" || isExplicitSize) { + return { width, height } + } + + if (imageDefaultSize === "auto") { + // Constrain both width AND height to ≤ max. Scale down only; never upscale. + if (width <= MAX_IMAGE_WIDTH_PX && height <= MAX_IMAGE_HEIGHT_PX) { + return { width, height } + } + const ratioW = MAX_IMAGE_WIDTH_PX / width + const ratioH = MAX_IMAGE_HEIGHT_PX / height + const ratio = Math.min(ratioW, ratioH) + return { + width: Math.round(width * ratio), + height: Math.round(height * ratio), + } + } + + // "fit" mode: scale so one axis reaches exactly its max value. + // The other axis will be ≤ its max. May scale up small images. + const ratioW = MAX_IMAGE_WIDTH_PX / width + const ratioH = MAX_IMAGE_HEIGHT_PX / height + const ratio = Math.min(ratioW, ratioH) + + return { + width: Math.round(width * ratio), + height: Math.round(height * ratio), } } diff --git a/src/types.ts b/src/types.ts index b501964..780ef9d 100644 --- a/src/types.ts +++ b/src/types.ts @@ -227,4 +227,14 @@ export type IMarkdownTheme = { * Image horizontal alignment */ imageHorizontalAlign?: "left" | "center" | "right" + + /** + * Image default sizing behavior + * - "actual": use the image's native pixel dimensions (default) + * - "auto": scale down only when either dimension overflows the page bounds, + * preserving aspect ratio. Never upscale. + * - "fit": scale so one axis reaches the page bound (may upscale small images), + * preserving aspect ratio. Like Word's "fit to page". + */ + imageDefaultSize?: "actual" | "auto" | "fit" } diff --git a/tests/index.test.ts b/tests/index.test.ts index 39facb2..4ee4801 100644 --- a/tests/index.test.ts +++ b/tests/index.test.ts @@ -54,6 +54,7 @@ describe('markdown-docx', () => { codeFont: "Fira Code", blockquoteFont: "Georgia", imageHorizontalAlign: "center", + imageDefaultSize: "fit", } }) diff --git a/tests/list-complex.docx b/tests/list-complex.docx index a17a295781b59a6a269e6708a6f7f831e86bb77c..a9d08140febecb85046135f1b150c945234926ec 100644 GIT binary patch delta 3892 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 OnomrI!dQ@ax_<-0GyTT^ delta 4071 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 diff --git a/tests/list-number-restart.docx b/tests/list-number-restart.docx index cd308ddeefe34eb8364cc36466cd978e7d7ef519..2774158873541077775f1a6649c94da38aa2464d 100644 GIT binary patch delta 866 zcmdnvy4RH_z?+$civa`-wI=c?G66|_bs)JhLY)yvZEj@LW&zRbSdXy+>B(i>s`Z9i zcVmSATRyg6WMF7!Vqg#i>Q2c|4k*emDArHTFG|&`$jwEm7{afa~*e}0eQQEz?n`-CVRi1B5+818Bh57l?i>jw4iMTG< zDHs&48ns^Rqll}Wfo?>u$&?oia%VFS>efFzc5t?_Sj>b6i?1!VeYnl#wt&vT8=rMG zo=u*1A$NzN-^L4av8}p~@2_E+v;3umHiyrK0|n|mZxdY9mp*8|^l!&5agM%)Y^+ul zb5tewZD5@9sa*ccNzs)l77;tT=N)dmS8dtgds*e|3isRpB>%scu7uTq_B^OHldch{R zHT7iSmf}x_RdtcN0%tGR$Si+sF@NnP_es7dUMSA=RgaI|Dt+8_m7nUrR9o+i`+vS2 zU$`F@B^QtP}UGc zeUUW>QMz&-AgWx>7DR26vj$P04g%Opvl_mjYp8zqcLi5Qb3ZNjFJVQZ-@z><73i4nL=N~>lbO>nj95zT0B23;r z`LhDpota89Ol!p^pAeIuEUm-?G9pn?hB0(O#Y*&4U*AR Yl40CG*-Z&%3M0?tHYEeLEwUg>0K+OMf&c&j delta 879 zcmdn%y2q6#z?+$civa|56({m2G66|_bs)JhLY)yvZEj@LW&zRbSdXy+>B(i>s`a{x zcVi0AevdR~WMF7!Vqg#i>Q2c|4k*emDArHTFG|&`$jw0;g?1(CM+r4RSDURyhJ z$Sz4EjPw8T>Hp_!oAtJI@|y#dS7%8*m2~8k zxagH?W*VjY{3Wwj%>%bj%S;0nGgp`-Pu)--vV|`$Hv1qet6ituvPJNjz)DWS{ zD#}-pQ7;=k^GX5lrbFV>|1wFxJFJvfwbsE-PH)Hl$bRb^EB|S4tWh|YTq^bJ1>4Lc zo4#1wvaFnMW2^tXLv)EoaL}@&C7$mzW?ou!X4&^Ao7a~;{W0}baA$qwc_A~C{r?JY z@WWz+0~jNBW7cWKot0u{VBnTuU=RX^b9sKzW=URSW>8%C2`GW0rbvJn5>%_*t-G1IbTdVHN46AmP)}-cVKYlg(v2LHZBL8iJ^= zvgRO4PtF5GRmjpDJMKJOg54?0|{oy%P@YQ+%B&O;;fRFk#H1XV2CeD z%_-Io09qo#07`Bk&rQAuRGB*Yx4e`B$dH(ob#W7cDQYV_1A{P72?CS|PM#p*ee@q70+*OV9 eRn!J?w3K8R_f2+Jg4x8#J-J=UfNirZ$VdQyfF@f2 diff --git a/tests/markdown.docx b/tests/markdown.docx index 11475687bf40ebf675b00c50022cf3c8c8ec9e33..35d7fe01690919acf17a6e84f0ae83701040fe43 100644 GIT binary patch delta 7390 zcmZ8mWn7fswjR1;Xpn9YhIZ(ZE>TMUbV*AIDlvm}*Qj)NNDU=OHw@j)&>$&F#|7{2 zoO93JANI4K{jR;%+VOta`?*U)`<;e{udR-Tjth7!VD5N)Ce(+Tj{^tHy=08JWnqvI zZ^j9o(R4}Wr@}g}AaUcPI+Ye#viO;&wm@j~KE}x@u)QZn0Oi;2ww-#ansbeYYToiH z)6FfseW(ARS2dzLBqgKt?QXF2F-6T&a->P^Z-^A+dw+B6`+Auo+3DMyitmS%hhNLh zylZQ(o)iDJ(PZ26%eUVy=eJ?4KAhD3q+}Bb<))DZjJMIg`M@VcNo2j7j78!d*=slf z?bnYwNr32YGTPgkQ8Vux@Yo%Z#1|KtcteN%64x;*h=@kSe8DOj(MG+t?K-Ca7N=dv!HLnf6rO*V1dhwz| zbGNOhK>gUuwIk)XV_?Na#&cMH!E+bfF@1p|`SiC&!714yKVK$NQXE?PBud2OnsMpj z>@{^u4)KDY*GHs>{c-B@wY!Kae82jvI@wuRBu}4FCoZp_=YV|amGgIEJ4!DaUloI# z-hnuWI6ZRmT-2ef4%Zc;N^McsWI{?`sNcoA``hhX`$NdiM`iJx?dl2ymL+6}d zOpu6pffwoNSN5L-Pq2T<@IW z#>T38fE)m@hVi4ZL-!}^=pk$ajSG{->uKvXbF*_&KJ#z!65_BUS*ZY@%l6OKZ{OW- z-m<;NWaOIrY7_s}X261;go`BbqXj=2Ar|!Vrwvsc3M?XW$Msw7k}(U9dvI^=GIGB6 zbp6}5qk=unM`2>1gz*!B+Orv#d%^t=9h&kK_9Ttz_01|Odr)*&zu9@V&S`q;o^MMc zsBJ7$)IEpDlnT#9d*RPN;c+DgaZRr{$EFs_v7h8DY=Ru|gMZT;yeYMhvE(u?ATxJY z$VJhkZa8Ka2EwsHUcvaqAv$x8LAqzK4|rL6NMVVY)Oo11+4Kp;s~5cAVfOi zyVC!bTHwUz*@83GrFf{I%Wd#($srvwso9w}#~RjOl_i_Mb*!NBKl22*9YH!ivM7?o zW}jTk`8@gK@mh2XuT3pjQZ=QKLC{t@`V_chI*i3L1(gV@UvTx~7HOjGv?Ir?p7}8L z0Ya+XgwDuVxzvc`P{?0&i)rbJHk#JxOF(Syi8h|5=0`V9wstls=dcp=PMdIiSW{(W zP_8js%UtD(P4?u3Di;}JK-D3~LPn40)zed1dsHnJs{Cv^qcE@*8M7-V>Z|1|D0(eM zD;@qq3~J2|;C$f&Vd6YMJOfwqPE8gLWCp!Pq_uw-YKxX%1&T|@94lSWrN*9*`=;-{ zZ0oBO%4$c>MtBvJhX4Jn z|H~abmTaRo1B%UivIwE)ij?&}=k?RUKuaiXNtqtwb;gdG5A7M8McKr?$OgPw8006< zxArZ_2W0x20Bc!LD;m;xIR|xmA^J+w(0n%^hhNep*=X>jMD-hBm($i137Thhz4z=d z>4_FH)e(+x%ZQz9#uO}iodw0D>lBQyO#}XEp~<%8dGmk5&%T!cA}PKVZp%`9g4$u= zDC{<}pPZ=hh^X3b7$)YkAHT%mu`*}>w&0FkY86@Q^5Xk=HyWPPAAPuPbS`U6J@mw! z*cvQy>gdwEU(aK#@dOcy6i8GH{D}n=A*qJO!RrtRT&(0;tbC_YMxO zq$=^E&>|OaRR|Ww&cIhC^t_gGg;>bD2W-e`jCE{fpNIb%l4R|Ob5yKhbb&TVtEQ=0 z-RdBiU3J!2vBRu0N%UvIhEazaLjUBy+ZNF&-x!uM4u}B$CS(@@$*M3i(ULO3K}9>v z;VEM|rqJ%PUr(pNvD8gbA4QiLWFV~=WB1o9_f_|ITqJAbVHafV%1O*t?14aJJXQiK zgUqn(0-Fte^tw>3CWI`d30mxlXE(`l!Sh8Mi+x@bP9J3uApE?2HLFh?o&1hMqqi~Cwm!CWbnl5}mJdVYi(Ja&l zPxNsa(_${0RFxRRnXu>;vLsc$BQeVF)dm6uu58eg|c6}v5b%t%u!8TpSNawdzYR1w3wEu_RTay_hNA0@1c_>RWC98*L{kppLRz} zy7gj+aa-l0Y@?(@N8dHsfe@56Ej3h;V$Q=L8-ZR&j-JXaF8SunyWg&xMc1kcamp90 zwwt?Qfh5+G>w8tKUg*%TIt%t#Azy?#-ixq?G|y@1{>C|pKc@OkVu%iN>`2;1X#-Dq zH*GEtZRXVJVb@w3;-2>&&N)1Zg}+Om9iCwNL$#OdDe#hMVOQ8x_)ob*6~Tvm4a+q4 z;?e^kC{9k&Us|mz#EU28(}ida2sG^0jum((iasYx-sKvAuMh{_p-NM`5`B5z5hhUp z`jD8Uh<3+!Q}&T0A*>Y8NzC}6yZ>4M2UVPjH!nQIx()SC^fNDF^d?=76D50d=S6L* zyHT#9jHz^CiOc>x?uUkfiQPmomjf^3%szPi>Mz!Vv#1OA)K|b*5Y(JB)T+Aqz8MwJ>F07bEIOlHqv#x|0J1E_{#umn9^`U z@>ZO(qzM6}i>)t|{GG=p`jYXFEXvv)Gdy2Kbki@}Y_&kBE6bgUUFMG>&0n_tjeAPI z2eFo?+`0^nXL8o^F>#&>UdQP#E~lT^dl6%0di%M3WJ=G2-g99$I`JNze_cH%GqX+S z=;S=XG76AY>h!rP6N5J=_=bgJVXT(}t#Jl$8IOFRWQ{A^kzkl*0?U1~6cGZWX4n}u0jcnm*>;E91{ zP(P4YY1)F&d>~(7At{7WnqNg*YlCvF5>(gb`{`!bcdWUQnyHXyBrlPtBPs$FG7d*Q zk5G84=+r>2?$&O6E8Cp4Pag*Wejw6lOAyX~CUt=e9sfLAzE9O8q@ACsSkL><$=!BK z7Nx2ggr?_k4RxyCi!9VjP^kO)XOv*kA#C$R=g7ki9Z{8>6)#0ZV~NDO5AN;C!kVMtf<(hvUca46L07b5AO!2l}p%E)vq+uhWJ&8 zT?x+<)LGJZT@Q7GeC88P8uWQ~hF9I#7L!SSK`$hZJZ=6LEnob_|r&AE}Hk;647n?Y6q5n3pTep6Za<)rU}V3(<&RUy9;z& zs5PC=q`;<;0+q&9xYf_5{BzxlA%7urf4Y;b*#XK<9#W_~rVy@6)H?%oltna;#qodz zaqIROMf>FQ3iX{%oG?ivD*wJj^c;@9Mm|gp8UhQ_3ce@JbFbCHJ6_fNNIyQ6m>K$G zZASTaIyUl%x}VD=kIfm$e>i*b>4Q1y2-Hn=iqpkIoT{ZjS)PbPEz4_4;W|VMd%q3#R#j4EV-jqbR$sFo-iAg3is>C=d z(ozV%42+*f&T|d?T2witRrY;~v2`cl*I82d#_v z$ht2vU!jYyyT#(}b$@=~i8|?6!lk+~l(YUmFycENAwb$JBv&gf7eo0xgo0q%gVMf- z)LfB!<_-IdaYkSHKK()fGpfEQI9cLORZXDlyjrj4v{ai0T)6|0M=!q8py}dH?j|xoE1efyu8BIB7o7fDRTuSQOi;hG5n6k;FhWE~ zVY#$?5*EqHfH!CFFgHFipEk8sRwO1-R4tZDCHqCt7H(4E(D=_>KWfxia>!U#K5>=n z?kuwL&ch*X*iWh4q=Z1vxhR6BWLxi;SDR0R@2}?a+``^omA`->XTrhQdpA?T|1=n` zwddrr@7^K4nu;Q&WT5`{gWd~Zz1Z(q(LhCmdu621SK^Y@isrEM zu*zp%|H5e7W(V5rgYo;i#sDN>X|D#b+wqf*2|j(TxiT8*5=>_T9b>El4y5dj*vhFDV-6hgdztQGM4ag>p!6qa#+;#Y3|jM=9v}WAEJZz z7{#aipL`!9drTasYCa}E*Hy_aGfoUE)TB$a%bAga*#U|MMT3$g;rRR z=2*ooHl57n*ZF0taC!ANH$5sB*7M^^td%V4uSkjG-ZTA;?H+Rf`LnnX=Pc(d9>Rv< zt}vFM{u(`sh3{t*8C(pGJxKXOe+Gutlk01tRiVC$1lUnAJb2W#HewO7hP5^ zj2f*&Xb9Hs?I(=!6+JhrWjuqbsZE-yvQ?i~14r<$iX0RvVXr=KSdf((BRqPY;e z>nvavo{zp8UKATA`sdX02fI@l%X>cFy~gswc1GU{M&9)pqX=wr!(0zNK7uhyp(36I z*Gt4sdYj>U_DI8@eTh-qA6t}X0q1`R+k)#$EecGli)qUFe{_72Mc7%=v%f+%k+TT? zHVpc+5}MHCkb1L0stgD_p^)_JY2%7td7r|jXU>N6UsxPIsz`nD%a9*c1O2Y z*JSyJ*%BKvQHHu!vPd2yEvrDy0abj~WjIimq%&i1*f#jtv#`th2Q^aDsMc6j$lUB@ zMaQal4JEi#N52NtVBFft)oSwRy{JJ^*$xSTaWlRSU#G4m^_z-0CoMyleh8%FC$BOy zzP&CZUV&O)YmZoHs`BNF?(==QzCcogSJAx!^%M-cDY86@%+IyBmU$=fxe_#O7zWy@tz_1?G-zvbVG&l(p} z85BXD+Qs1AewqT)wvKlbxedqCD{L(we&&trPJH4#3)lyD|EuX{+Zc@LGL%vR#$I|l#Y>Rk%Gm=Fz1e@NH zt;a1TdISh{&S|GEN82hdil0+8Hhe0#DxCv*X-N~kr^R{Y5OJ>h6`lInTEWsE|D0Uw zSe*ILQ;uG5uAgUe$h=%$wi{FY(K6xziZu8|Q_nk<`O#!M>udNbhM5;*%g1_n}xC_|yNDq6uW_tF@vn3pj$|wIszSES8V5W20h5RM6wfU08O_xU3 zr{Xhv=mwL{Lfz9NB?F?ar_Xgv{jg}s$i_SR{CLf0r6Qq05Ty|Lvwpa(sF75lP?@%Z zGUw_h&e_R>D z_@w*w?yG$%>h9Ig6p7YDQ-;QV7@(w$60=j!D&Jc>hl2)loD33Mau3gWzoUJR#+?=K zF=1j~(Pb#K<&-wI{ia$4?Rn5-f_wVfbl_#m!?oA-=O08#&3WfuHZ)r-Ch?I>iIxnE$Qoy#ocss5nDMDxw$4ZE5OqJ^*OIW7v5F@~@v>S+a}0Y9sTZG_w#*7uK-CPV#f`PggvNIX||PKV7aoTF(_2mKbxiztSp8a4_U< zCr+V`Ne*$iiHD!|>RriJb5Xy5oj9FM={30-=k4jPnN7ok&W2o|v{!il_q83~%P5QX zxV$*5%ntzPWhFp)L`k-`M}*z6w?9HVN9$v60H+S>Bc0(cc%;y$Lw}96cz^vhmgmcV z?B3;5|4V1MA2uIB48wftiT+oT;-iH95g>jv!4g!}e8gAKY>`L&Q^QL7fUqZh0*|28 z2mX(21&isEWB4y!-~<2w{*}4@RZ+nX`xqYw68F=h0AalS^p8ZdpH`HG;Xy}mvC?*T zarNNSe#naq@Tideuh8)KD4_rVfvErAp&Bf^pYd-{!iVQ8610c!lmGz9zvBJHD%fg2 z(_fqa+l~2eLj2G=g)t70OFSmekel#z>!D}(Ar{`hZ5|txtN?(SyN#0vALz0E?<8Ta z1GFgYu;_uu-GNm-kR90Y0Q29lYd7ihum=Z^ZXbjFrxejfOPjOzMtp$ zJ>U75`7V+qG^>OpV`H>N-URUkZQ+0jgXa6CqJ20N;xYr59%VxJntdEu4 z$#e?auy#KUAn>aQRo0d-eX%S(gkWB3P4}_-bbWQ4+hb{Y$qzC5lfOiw=6B)?!oq1~ z8^zn9Q+LA;t#g`evW@K;4CNK$rAK;c0(B4ohZy5UgCyp5{nlDWY5GCN&Cr^O?W$1~ zp_wMuOU)(pm@Q=D41RnR2SOL^KwV+TR_UZmQ{p1ZwmZjr@voIWejsn&7s05*Xl-A( z)sj1SMN*>0i-#I;jiWGcoLL_9qN$~}rF!FM*j`ZmX6wPZs)>#2y4Hw+@{?G~YF$Hw zD&)UU9Lw{ofNw{MrAuIqqhbul-$Te>{rYx5Juj~ro0rJje-(=6^&%;)>3vowlAnW3wVRil~5` zY#p*bWp&Rha30!bFiiu-9k$gIJUoTmhc}ijA1bd$d!Y06=P7kfGA5{{{`R7-cW?Ll zL9rLd?B@GpTX#nOrIP5aoI}K_g$_~bp4cIl9Lg81t+S5TLk%S~B9R#d1ecZvVFIYcq52_98eKO01bwUMNUwF-PQ|>;C-+yOio0CN}&q4^x;9z0hmqZdl`I z@18~2iL#d^bbM6bGLH`@?Ph)65tWP9?;oip9>_I>NKlF@(fb*}Gm5)eBsVjsGs_ag zn&=st8G$U0C1bDO7q!5J9!B^IJ4tS4daYUf77#xm@Wy)X(srrxF?QbQpPP&N=jJYg zgE1)tCI|rlLl_4lJtS?ShBBa2b=OfnKf*0~e5?E5pgwdnRAfMoM>ms@c z@qzTE17+oF=yY=|l3kO+r6N0x4N2gE9c{IcdJIHvV>K7t7Y>Z)tS z0p2;UI%Zza9aTpQe+qN;CsM1%ch!DQ*WlYjXd>y}xM1<=Ta01$qCMZBDr@M#7X-y< z8{V(Xh{Q`_^rl2@U8OP9lg`ZVKgIM1;5i|lCD|Sv1@7UtI#QY&caF+{vX!5k3cp27 zb!U~>(VmiEAA^)RoX~GZ?^ICh0tBJ5*CLcKRU$I*84p#kj}%6`G3$q^rF-)unK5d= zPeAq$Kds0^gS!0QbZWT)BdDNFT_8sAAx{TwjtH3-IFb(^?yygcIPw#X>R?et@GwVq zjf*!x)cP=1b61`R1pmFvRu-4p+#S6m~oIxatszDWmY~)B&nNu_Dvt7~4ZE%quK^@#S zC3z8Fcs{4`3|mwNRdebmTA~Dw?8ByLK0|_~8aZ#3%_Cc}Gpe*S>~JloM@P|H2gp4k zU|dvarF9l^M$z}|Pl#^D$G!Cyt*q>k^1X*WoMAiA@0u8q#T+C6fBCvRpx3H-Z?#J4 zd8U63mDAasnRUeW#i@=i(paO_nGzv}Z0U`y-dmnI9Fl76Pl*+X{e(x7K)9!t3A23P zm7)Uh4X}~k_AQd3i;(`ig#76H;;3SX!urL;hCizWiX|6E;uQ^a7XF>?*{-?MdHJS) zo>XBaG3y@$W=rU@is(^nY|Vnuiyd5#Ai z^H5q_kJYh_8|tlOS5R8X#?$F;Rn)7U#L?;@B418-&Hac%G_%`mSxEL)&e{pG-bU5y zXuCDN^nTV!w=Ria2cx4F%#2z3QgLgg9chFI14yJrwmls?@&@)y^+e$dbs3%&IU3`e zpi%-KZ3bSdk#68)gg59WrCXwTj5ddCp`Oh(HV~&uMHTOY?8?gq@#GZK^t%#^cdomH z&SU}{WzLG00(UxJ_4DiAat9?yn@8^aUa&rm?6s*U|}cm)BX6d@15{g}{N>LMjuBQoQHz*jGq4f$lLmJ(QZ-!#p_8nXGW zy3xI8dz>MJ&9p$kv~0c|x2HQ7U4npkck zis<}?#WLRL`%fSEj0L>o_~GjK7DMXs5c25ocwZ|ERiIf@Pogl1j7r9k33*E?``qtN z5YZv=iw|$~@C4Siob>@DZ;I`!YUWC%hQx~`>sq)kry<%H26AvPC>2MeRfXhO+Bp$s z&27%#4ak)x_yEJ$=Ia|d7!g}VIh1~uk|TK%)c=zqY_#%uvHDWivYUyn0-F;>pY?LN z8er8OzRbprAcrAzM1`;^-jB)Qe6OuW86{L_1~j61eeY~;hMNWvvxm!g)y>%920L}( zkf)<{MUwlJTK9G*Ewwxj+UKG#g5@?*3;8M^7`ND^@(z~*lFSo30z<*HI7wI~df;u; zZ%5>v-rc|4P?fwQx7z*0_Y?*ylE$}ws}Z?1d75INr+_AIcT}*aqZ=~m(0oEvT&FUk z1sTOXM~7Ax3%qq+IRl5! z&OsP!z%x}4f0fxNMrY4A4>qSwhyN;P)F1~=fnVhm`-cTjHCLBKPHi4E&Ggh<+J4M7{;IxX$T&UUi5=TBU2?A z+wJj*kfy)c^i*qyW`=SL+{dnL{RX}-yym)w0m2o@NFwjn9^$>xxZb=F|6XmP+=$bQ z&~3Gm9#}978BC!Yg@+9$W0Ftf+C|}Z2bX|A->*db4*i_Yhy0Fgo^ca639v$H$-jEF2jXJ) z^tZF@i*5MWBr$-Ti*IkWfwd5-*VcLEHm46YGeWtE@A**n{zen%&bzOqlwgFw{b_9m zC%&^HCdH?E)h8vahutR%q{MOB!($GUp^4jId6Y05et^ek{W44Q7>S%a6=V7G29Wd1 zz8i=r0g=zSn_4pzaCsZ@_A=JH`JKA&x9%@%?VA^@@3Z`v%?qQTtfNvqP=0%G1TOvC zDw5d{p+Kg@?%%V#NXJ3qA6!8#xZxfZ$Xn6Te~Q`$QGA@NYK{z#t2$DOw~JW+K`yMPEU)Tne?DtE2n}mVzl={P$aJ# zxsCl6j0EC>pS9V7Rj_0x$}9}VP8(%FqpiL>LnfZjDCV2P!yeVo(y`g>Sthrx(tbZ? zQPhq43b+R(oaU#qOGU}BF3XJZA{#)zULy?{NB)u!A*kOg0(1DH?NNpe_0H#`xO`8I zDuvt-V|Ny|YFv?4!p%RmGcB~?@{DcnIXGq#sw4QhDU)uC7@PBFt1pSKInj!}=`maWp0Y03Ahb2>e)N%+ zhRfM~K;Ar{Tpx8Sml_9rKGx%x+Sy>CK9_&(f}Mv1tr0n zmf!t2Ez-3L?3gMtJ0xEPv$invyX!ny;{$q(`&$ve0&%!Uc2+cU3oL4L>Iwy|Fzy7r z6d6Z1>L-ouaH0l#_d9chisMx8++P(1IgI+r&!_0{f>_4}*mDIj6#PUm>srU&^< zSnQwJhwg=VIvIv}PF3+ciWxQDZKRp)$2%7{KTuTK1YFCnE<^ZqDY8<3Zo`bO{MYt_ zUU_*G5;@mIveXO}v3#*OGLaS&x1tAJOc)HbIvDA`y-7qEimO~i}H zz<~*%7w=4!&**jhi*Jn=`Bv&5;qb%5&udDNway^|a}ba)T3QOlqnaOAccJ9NT}=eU zNa;5Pq9`SADjhVl>o;4Lbxu+L;GqvR)HsU0Gw!W#k7iNS?-uOj9wsi%{=SfhU4^Op zTih_-7Oz)T9|tOOsbcND%CNra4Jd`&7Gr$H1Jy0%fGl%TrAlWBw^+^yPiAe$(WnCE zL5^QD;vwr*3E4kDYX(2iUK}#Yny!y!~F3ba$i zMC|I!G+F~l-R7r1t}jTF^*H=-M|LtHfV~2>w?+`oHnn9iR#mw@ zIu%&{k~hYPt+gyf6l>MAJVquNP?QG}pE2+lo%xg^1Bt6gmvYQn!`4`?4ohX1aqZrn<7<# z`CB|0E3>HcT^FNY-$sks=r^j^xLG8lN#&&NQ&25o<0N+Ltm$cmp#xOMNyu$$Rjq>b zjUmJ%H5O~$FVndt=J|R0CL$|YWLmyr`A>eBd1PWzea{x(yVR0!GakS^=hj6b7XcZI z>yfr>E-HwbEsIlHWGLKacF%vt=bGr-XVO+bd&8sXEG#T@VqoqS@iu<=WM6@cJWh35 zfINGh9V~W!?rieS8=t3K`ol**u3eJZyJ?65sDHxxgu$Ni)`tr;1o8yH5_Jp#4XY}ut;g?q$i;v%G%yH-PnDKRQJc6OY z+vNddBEcy_0rTrL0t~D^ejA>N8^>Cgq!Rl(lNn1l?|q%>L##(?^i(o;qUs?Cru`oD zs|(vFj?bs;b`>uhsAr1$@h8XIE2m;PNQY1TAmzY=ofm=VPTC!cCFbf}U=#09mY}53 zP7%eNb}tqg^Iw&yb}iU+pC+-cXBnaaIP3dfH&H?Apn6?qxYnMA=>@@$#gqpf+PDlS zHEeKtQo{!7SVFQ)l~gCrT>?ZGxl^;=j>10>%B>t}A66O1#+6@Mwh)xaw4)r+=grfe zT4P(EVA=XJ%P_R<+?vBtE3d%Xz`i~pR6U^fpv<{cMRk-grPdcW&oHF069f<7VMFD= z-)3ls)>!tbC@rm_(m4!?^8`;scF8* z;b2rXKT$>kP80wrGWr^@#mLXao8%bSP&7}HiCjT0++cLWixg7n;ylVKa zg-HC~hH-lRI`mSr#ManQqGF52Q21kYrA}F1iLdxB1DRIoQs;*^87g!h=i_p9_dyN* z#b0zcCnF&ugqDyE7hto|>wrh!6a3BJG6U?Z=aLyNx=qp3kUEFL2YBNteIoJR<0oet z8X`4HV_!CO{DnoRED;I~Y(jh2-yc5T)hT@yUC4W0;G#{79F`7OFtaBB6|sBsRi|QSlI=bnAn1!3e-Otu~Yi<1@7*lT|5`aRQ~OB}&)tSqm-o;`|li zC7klUbB67g%IG}zQsKxH48^v4$VQj$h1}(N)!kE0Cu|h0Gc2Eo$u8t=>L_ah%Ak1E zh@J9-oJkZdx8GVlzdq$+;@RJkD5W^gay}z^C&ZpaI)?7 zC7l^RqQnnww=QC{T!o5DbAn)XJ#ZYK_O{D8U!8H>_kh9a&69Itb({*P99j#uiIA7wxN=b-xmkjZp_?9lNCe~iR=?Mp}^XStaS+7fvy9Wzv zE2UlFIVh*l_<$RSTw;I=mait%~FTd~+W|4}ck(lIi?>%QDt~>+MQM=Ok zm|<#IV*{1;)CB2^!v&mPToq8!ruQJxgG2ebUWK{fkdKI%zc6WVwrJj}5WeB_1Vj8z z`Bu_m5bU7flU^4N#YJnWx48t_WA|5@ed#lKa!>S?$2eH6e(*i;|&lW^TfL2^$602sMi*t`8n z@;@G)3K%f9ehMHpOunD&Z#>|_0K-@y08otr0O0@Y?&*gU7Tgc|%hBwk-C{kQ0%3p|w)p2@ z?BEzrCMpIffNrp%fxqD#{ShQ!nDD;>2b==P4^xD*Jkfmq2#c@;_`g<|xnLq(FIoOC z%BKS3|K<_>U;j^e9D`90l0BJvJxGCY%LT*a7W&WX|6k;350ouZ=KEtw008*&{in&m nS_WmPo;>8Au*?tt39tW8|6k5d73{W32xd5h^9-~1Y3=_5Uv!%s diff --git a/tests/math-example-from-file.docx b/tests/math-example-from-file.docx index 2bea885c603c535312d8604e3704999031044145..2a54c4af4a22cc999e33f392f74af114b75f41fe 100644 GIT binary patch delta 879 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 Hf~)}m=UWz1 delta 1051 zcmX@*dd`(6z?+$civa{SDNN*1WCD`<>OgX1ggPUT+T6(K%>ts&u^wXu(vzogtJZH) zxEoW!5%$rVk%6I^iGe{7s5>P;IiM)NpjbaSzbI9&A~$F1q}co>1Ch4>TrX|6EC_aI zn4J4DOU--P%}u+P*=8C4nz&8)?|1DL9W%{$=iFcJf3JAK4EYqH3 zIc7y}=e5(K10Y-_|HEP4>Am%hx!`n_-8#$@XW zS5zAV6z^ncujF^%eY9;;{w~%zf<_00Y@S{TzQdJ#S^8q+$;kC4_S@dE%t>6~*z}2S zxo6kMB%{vF$3-QdKT(wTo%}K9*VVAyg)vJ%#XP!y?dE~1i6OC{ zZ_6+L#R`iR4q&X@jj207^9=_x1B1921A`C)!)6m+Rc26JL<=Z^qNZMe7aUc6f(JnK z7^jy8`9oTRq~TvWII9n&&wKu zC?+{`5M?dr0is&vY(dl!IcpHbC~wLMPYjdo<;~==I2W9_AcXYfDe{VDAT>yW3~X?Y z0FV_7B;t!wbBgr?fKC!&03}XPFid_eFJn~>m(&9(K~-@#CT3+_+(cla+{(_tAPhGZ z#AuuBsGy_(vN@viw$db^$P*w&RpTK%IYC%-@(cx@SdhX;f9Bqr3{>xJr^ib4aBlYDi|2{O?Fh& z0flhBq6}l& { const theme: IMarkdownTheme = { ...defaultTheme, bodySize: undefined } const style = createDefaultStyle(theme) expect(style.document?.run?.size).toBe(24) // 12pt default → 24 half-points - + // lineSpacing defaults to 1.0 (from defaultTheme) const theme2: IMarkdownTheme = { ...defaultTheme, lineSpacing: undefined } const style2 = createDefaultStyle(theme2) @@ -144,42 +144,42 @@ describe('createMarkdownStyle font-family', () => { }) // --------------------------------------------------------------------------- -// renderImage – imageHorizontalAlign +// Helpers for image rendering tests // --------------------------------------------------------------------------- -describe('renderImage horizontal alignment', () => { - - // --------------------------------------------------------------------------- - // Helpers for image alignment tests - // --------------------------------------------------------------------------- - - function createMockImageToken(overrides: Partial = {}): Tokens.Image { - return { - type: 'image', - raw: '![test](https://example.com/test.png)', - href: 'https://example.com/test.png', - title: '', - text: 'test image', - tokens: [], - ...overrides, - } +function createMockImageToken(overrides: Partial = {}): Tokens.Image { + return { + type: 'image', + raw: '![test](https://example.com/test.png)', + href: 'https://example.com/test.png', + title: '', + text: 'test image', + tokens: [], + ...overrides, } - - function createMockImageItem(overrides: Partial = {}): MarkdownImageItem { - return { - type: 'png', - data: Buffer.from('fake-image-data'), - width: 100, - height: 200, - ...overrides, - } +} + +function createMockImageItem(overrides: Partial = {}): MarkdownImageItem { + return { + type: 'png', + data: Buffer.from('fake-image-data'), + width: 100, + height: 200, + ...overrides, } +} - function createImageRenderer(themeOptions: Partial = {}) { - const renderer = new MarkdownDocx('', { theme: themeOptions }) - renderer['_imageStore'].set('https://example.com/test.png', createMockImageItem()) - return renderer - } +function createImageRenderer(themeOptions: Partial = {}) { + const renderer = new MarkdownDocx('', { theme: themeOptions }) + renderer['_imageStore'].set('https://example.com/test.png', createMockImageItem()) + return renderer +} + +// --------------------------------------------------------------------------- +// renderImage – imageHorizontalAlign +// --------------------------------------------------------------------------- + +describe('renderImage horizontal alignment', () => { it('returns ImageRun directly when imageHorizontalAlign is not set (defaults to left)', () => { const render = createImageRenderer() @@ -243,3 +243,215 @@ describe('renderImage horizontal alignment', () => { expect(str).toContain('altText-title="alt text"') }) }) + +// --------------------------------------------------------------------------- +// scaleImageToFit (max: 602×931 px — A4 with 1" margins at 96 DPI) +// --------------------------------------------------------------------------- + +describe('scaleImageToFit', () => { + it('returns original dimensions when imageDefaultSize is "actual"', () => { + const result = scaleImageToFit(1200, 800, "actual") + expect(result.width).toBe(1200) + expect(result.height).toBe(800) + }) + + it('returns original dimensions when imageDefaultSize is "auto" but image is within bounds', () => { + const result = scaleImageToFit(400, 300, "auto") + expect(result.width).toBe(400) + expect(result.height).toBe(300) + }) + + it('returns original dimensions when imageDefaultSize is "auto" and image exactly at max width', () => { + const result = scaleImageToFit(602, 400, "auto") + expect(result.width).toBe(602) + expect(result.height).toBe(400) + }) + + it('scales down by width when image is wider than max', () => { + // 1200×800 → ratioW=602/1200=0.5017, ratioH=931/800=1.1638 → use width + const result = scaleImageToFit(1200, 800, "auto") + expect(result.width).toBe(602) + expect(result.height).toBe(401) // 800 * 602/1200 = 401.33 → 401 + }) + + it('scales down proportionally preserving aspect ratio', () => { + // 1800×600 → ratioW=602/1800=0.3344, ratioH=931/600=1.5517 → use width + const result = scaleImageToFit(1800, 600, "auto") + expect(result.width).toBe(602) + expect(result.height).toBe(201) // 600 * 602/1800 = 200.67 → 201 + }) + + it('scales down tall images by height constraint in "auto" mode', () => { + // "auto" constrains both axes. 800×2000: ratioW=602/800=0.7525, ratioH=931/2000=0.4655 → use height + const result = scaleImageToFit(800, 2000, "auto") + expect(result.width).toBe(372) // 800 * 931/2000 = 372.4 → 372 + expect(result.height).toBe(931) + }) + + it('rounds dimensions to integers', () => { + // 1000×753 → ratioW=602/1000=0.602, ratioH=931/753=1.2364 → use width + const result = scaleImageToFit(1000, 753, "auto") + expect(result.width).toBe(602) + expect(result.height).toBe(453) // Math.round(753 * 602/1000) = Math.round(453.306) = 453 + }) + + it('returns original dimensions when isExplicitSize is true (regardless of mode)', () => { + const result = scaleImageToFit(2000, 1500, "auto", true) + expect(result.width).toBe(2000) + expect(result.height).toBe(1500) + }) + + it('isExplicitSize takes precedence even when mode is "auto"', () => { + const result = scaleImageToFit(2000, 1500, "auto", true) + expect(result.width).toBe(2000) + expect(result.height).toBe(1500) + }) + + // ---- "fit" mode: scale to fill bounds (may upscale) ---- + + it('upscales small images in "fit" mode to fill one axis', () => { + // 600×400 → ratioW=602/600=1.0033, ratioH=931/400=2.3275 → use width + const result = scaleImageToFit(600, 400, "fit") + expect(result.width).toBe(602) + expect(result.height).toBe(401) + }) + + it('scales down by width when width is the more constraining axis', () => { + // 1200×800 → ratioW=0.5017, ratioH=1.1638 → use width + const result = scaleImageToFit(1200, 800, "fit") + expect(result.width).toBe(602) + expect(result.height).toBe(401) + }) + + it('scales down by height when height is the more constraining axis', () => { + // 600×1200 → ratioW=602/600=1.0033, ratioH=931/1200=0.7758 → use height + const result = scaleImageToFit(600, 1200, "fit") + expect(result.width).toBe(466) // 600 * 931/1200 = 465.5 → 466 + expect(result.height).toBe(931) + }) + + it('scales down a square image that exceeds both width and height equally', () => { + // 1000×1000 → ratioW=0.602, ratioH=0.931 → use width + const result = scaleImageToFit(1000, 1000, "fit") + expect(result.width).toBe(602) + expect(result.height).toBe(602) + }) + + it('scales by width when image is wider than max but height is exactly at max', () => { + // 1248×931 → ratioW=602/1248=0.4824, ratioH=931/931=1.0 → use width + const result = scaleImageToFit(1248, 931, "fit") + expect(result.width).toBe(602) + expect(result.height).toBe(449) // 931 * 602/1248 = 449.26 → 449 + }) + + it('scales by height when image is taller than max but width is exactly at max', () => { + // 602×1728 → ratioW=1.0, ratioH=931/1728=0.5388 → use height + const result = scaleImageToFit(602, 1728, "fit") + expect(result.width).toBe(324) // 602 * 931/1728 = 324.42 → 324 + expect(result.height).toBe(931) + }) + + it('upscales small images in "fit" mode when height is the more constraining axis', () => { + // 300×500 → ratioW=602/300=2.0067, ratioH=931/500=1.862 → use height + const result = scaleImageToFit(300, 500, "fit") + expect(result.width).toBe(559) // 300 * 931/500 = 558.6 → 559 + expect(result.height).toBe(931) + }) + + it('rounds dimensions to integers in "fit" mode', () => { + // 1000×753 → ratioW=0.602, ratioH=1.2364 → use width + const result = scaleImageToFit(1000, 753, "fit") + expect(result.width).toBe(602) + expect(result.height).toBe(453) // Math.round(753 * 602/1000) = 453 + }) +}) + +// --------------------------------------------------------------------------- +// renderImage – imageDefaultSize integration +// --------------------------------------------------------------------------- + +describe('renderImage imageDefaultSize', () => { + it('uses actual width when theme does not set imageDefaultSize (defaults to "actual")', () => { + const render = createImageRenderer() + const result = renderImage(render, createMockImageToken(), {}) + expect(result).toBeInstanceOf(ImageRun) + expect(result!.toString()).toContain('width="100"') + expect(result!.toString()).toContain('height="200"') + }) + + it('uses actual width when imageDefaultSize is "actual"', () => { + const render = createImageRenderer({ imageDefaultSize: 'actual' }) + const result = renderImage(render, createMockImageToken(), {}) + expect(result).toBeInstanceOf(ImageRun) + expect(result!.toString()).toContain('width="100"') + expect(result!.toString()).toContain('height="200"') + }) + + it('leaves small images unchanged in "auto" mode', () => { + const render = createImageRenderer({ imageDefaultSize: 'auto' }) + const result = renderImage(render, createMockImageToken(), {}) + expect(result).toBeInstanceOf(ImageRun) + expect(result!.toString()).toContain('width="100"') + expect(result!.toString()).toContain('height="200"') + }) + + it('scales down large images in "auto" mode', () => { + const render = createImageRenderer({ imageDefaultSize: 'auto' }) + render['_imageStore'].set('https://example.com/test.png', createMockImageItem({ + width: 1200, + height: 800, + })) + const result = renderImage(render, createMockImageToken(), {}) + expect(result).toBeInstanceOf(ImageRun) + expect(result!.toString()).toContain('width="602"') + expect(result!.toString()).toContain('height="401"') + }) + + it('does not scale image when title has explicit size (even in "auto" mode)', () => { + const render = createImageRenderer({ imageDefaultSize: 'auto' }) + render['_imageStore'].set('https://example.com/sized.png', createMockImageItem({ + width: 1200, + height: 800, + })) + const result = renderImage(render, createMockImageToken({ + href: 'https://example.com/sized.png', + title: '600x400', + }), {}) + expect(result).toBeInstanceOf(ImageRun) + expect(result!.toString()).toContain('width="600"') + expect(result!.toString()).toContain('height="400"') + }) + + it('upscales small images in "fit" mode', () => { + // 100×200 → ratioW=6.02, ratioH=4.655 → use height → 466×931 + const render = createImageRenderer({ imageDefaultSize: 'fit' }) + const result = renderImage(render, createMockImageToken(), {}) + expect(result).toBeInstanceOf(ImageRun) + expect(result!.toString()).toContain('width="466"') + expect(result!.toString()).toContain('height="931"') + }) + + it('scales down wide image by width in "fit" mode', () => { + const render = createImageRenderer({ imageDefaultSize: 'fit' }) + render['_imageStore'].set('https://example.com/test.png', createMockImageItem({ + width: 1200, + height: 800, + })) + const result = renderImage(render, createMockImageToken(), {}) + expect(result).toBeInstanceOf(ImageRun) + expect(result!.toString()).toContain('width="602"') + expect(result!.toString()).toContain('height="401"') + }) + + it('scales down tall image by height in "fit" mode', () => { + const render = createImageRenderer({ imageDefaultSize: 'fit' }) + render['_imageStore'].set('https://example.com/test.png', createMockImageItem({ + width: 600, + height: 1200, + })) + const result = renderImage(render, createMockImageToken(), {}) + expect(result).toBeInstanceOf(ImageRun) + expect(result!.toString()).toContain('width="466"') + expect(result!.toString()).toContain('height="931"') + }) +}) From 6e22d4cda9380bbebf5ac7fb790eb484499d0a10 Mon Sep 17 00:00:00 2001 From: Syrupy Date: Mon, 29 Jun 2026 16:27:45 +0800 Subject: [PATCH 05/10] fix: handle image alignment at the paragraph level --- src/renders/render-image.ts | 9 ---- src/renders/render-paragraph.ts | 8 ++- src/types.ts | 2 - tests/index.test.ts | 2 +- tests/list-complex.docx | Bin 10584 -> 10581 bytes tests/list-number-restart.docx | Bin 8893 -> 8891 bytes tests/markdown.docx | Bin 52852 -> 52782 bytes tests/math-example-from-file.docx | Bin 9986 -> 9986 bytes tests/test-math-comprehensive.docx | Bin 8906 -> 8906 bytes tests/theme-styles.test.ts | 79 +++++++++++++++-------------- 10 files changed, 48 insertions(+), 52 deletions(-) diff --git a/src/renders/render-image.ts b/src/renders/render-image.ts index aab0ff4..b6799e5 100644 --- a/src/renders/render-image.ts +++ b/src/renders/render-image.ts @@ -4,7 +4,6 @@ import { Tokens } from 'marked' import { MarkdownDocx } from '../MarkdownDocx' import { ITextAttr, MarkdownImageItem } from '../types' import { renderText } from './render-text' -import { renderParagraph } from '.' /** * Maximum image dimensions in "pixels" (at 96 DPI) for an A4 page with 1" margins. @@ -36,19 +35,11 @@ export function renderImage(render: MarkdownDocx, block: Tokens.Image, attr: ITe const theme = render.options.theme const imageDefaultSize = theme?.imageDefaultSize ?? "actual" - const imageHorizontalAlign = theme?.imageHorizontalAlign ?? "left" // Scale down oversized images to fit page margins ("auto" mode). // Explicit sizes (from title attribute) are never scaled. const finalSize = scaleImageToFit(width, height, imageDefaultSize, isExplicitSize) - if (imageHorizontalAlign !== "left" && !attr.isAligned) { - return renderParagraph(render, [block], { - align: imageHorizontalAlign, - ...attr - }) - } - return new ImageRun({ type: image.type, data: image.data, diff --git a/src/renders/render-paragraph.ts b/src/renders/render-paragraph.ts index f7945dc..ba1d5ba 100644 --- a/src/renders/render-paragraph.ts +++ b/src/renders/render-paragraph.ts @@ -9,7 +9,11 @@ import { renderTokens } from './render-tokens' export function renderParagraph(render: MarkdownDocx, tokens: IInlineToken[] | string, attr: IBlockAttr) { const heading = getHeadingLevel(attr.heading) - const alignment = getTextAlignment(attr.align) + + let alignment = getTextAlignment(attr.align); + if (!alignment && tokens.length === 1 && typeof tokens !== "string" && tokens[0]!.type === "image") { + alignment = render.options.theme?.imageHorizontalAlign + } const hasList = !attr.listNone && attr.list @@ -25,7 +29,7 @@ export function renderParagraph(render: MarkdownDocx, tokens: IInlineToken[] | s style: attr.style } - const children = typeof tokens === 'string' ? renderText(render, tokens, { isAligned: !!alignment }) : renderTokens(render, tokens, { isAligned: !!alignment }) + const children = typeof tokens === 'string' ? renderText(render, tokens, {}) : renderTokens(render, tokens, {}) if (attr.list?.task) { children.unshift(renderCheckbox(render, attr.list.checked)) diff --git a/src/types.ts b/src/types.ts index 780ef9d..fa28a07 100644 --- a/src/types.ts +++ b/src/types.ts @@ -117,8 +117,6 @@ export type ITextAttr = { codespan?: boolean del?: boolean br?: boolean - - isAligned?: boolean } export type IBlockAttr = { diff --git a/tests/index.test.ts b/tests/index.test.ts index 4ee4801..abd80e0 100644 --- a/tests/index.test.ts +++ b/tests/index.test.ts @@ -54,7 +54,7 @@ describe('markdown-docx', () => { codeFont: "Fira Code", blockquoteFont: "Georgia", imageHorizontalAlign: "center", - imageDefaultSize: "fit", + imageDefaultSize: "auto", } }) diff --git a/tests/list-complex.docx b/tests/list-complex.docx index a9d08140febecb85046135f1b150c945234926ec..afcc2bc4c0a52ec31d0d0ebf7c33ad12206fe801 100644 GIT binary patch delta 4169 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 delta 3954 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 B2E_mX diff --git a/tests/list-number-restart.docx b/tests/list-number-restart.docx index 2774158873541077775f1a6649c94da38aa2464d..c3d5731472ca99fa8b53a49535890a864de117e2 100644 GIT binary patch delta 879 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 F{ts3XM%e%W diff --git a/tests/math-example-from-file.docx b/tests/math-example-from-file.docx index 2a54c4af4a22cc999e33f392f74af114b75f41fe..513ab997726805c15e7d421fefdf137e0dabf13f 100644 GIT binary patch delta 631 zcmZqjYx3g>@MdP=VgLbK=ZQRuOh8g!9Y}7BP-g^En;RLcIY9J3&SR`Vdh#)TRSsL{ zyD@+F?(mrWnP01Z+oFsN<($K-Ih!@5cXOW%JUokk(wSHLq#jo4kUSCz3yXXk}GS=*#HYwSIi!ImgP`zVOQGBe4Tc}3J z_Lgv7_7?7gLOr(k8fwuroWBV1eK~lVG3T~fw!5v=Z}A_+ zKY!ippXGHow~Kkv)CVor2?s59U0a#P<srk>2);{D0cqN*-ZS3vi3(WGaSx6E1lNmKK9ip}X$MPIIl?k@MdP=VgLbst%*E}Oh8g!9Y}7BP-g^En;RLcIY9J3&SR`Vdh#)TRStcv zyD=FnWE&=b=GUrUW^~snI#D{#SHkD!2R#*c-fTM$qt*ZGGOw;WvpZJp{p9xVbGFTS z7drXPfy&I1R*z|mSxn5GUir38>yG@@AtXOTY>lCmRtZD@veJ{fPmdkkZ7dcu;lbn= z7v~j4FU;kbmh|SQn8@cyl@gxo$27$rUCiB(`e$}7gLtLgF)k)yoqB^ioWa%-7dtea)v`ApWNi02i(#JH0!@R&X1Ys)z;j)`-P>mcnP5npq zzi$`&XL;St?P6Z#eNeOfKvUt@pyjhP1yuL#dLwqjK>k_b1gD%palKT6gh%2L@B5v66yV1?_I?LboRm5o4@vI(yi?SE%ZOM3$?9O@9WVRMo&%=Bq)K1p@#B-Z$RqJh? z@5Yp~1~r;9GB7kVF)#=Mb*JPf2NdNO6zeDF7p3Y|~*S*^Tf|S+}E~9X_c_Fi*0$btp35;R`c6Z8{(R}o7{Id&E|T$$DH+8-+Kqc z=`2p|1-GM))>zzVU z*ZMW=tM43UcP?_)dfCq=w`h975`MqFgzKfA=8_jK*dLw0`ug|8D-o~if@K7BS@n0Y zK8vpRHn+Ow)2Q+BZ0i04ZI=7FX5aG?@INm7F8|tNv2UCHdzr{~e2kdaZnx9XWnoUC z)Z0llKJ((QdAk@-dTMy`an3%q%}TSyE>})^_GIvtY%xlAplBhSEzx!Z)P7p{nF3yU2Ee^q-eC1W`>&%tFO3Iaj0Z6$00ssI2 delta 685 zcmX@*ddih2z?+$civa}mwI=c?G66|_bs)JhLY)yvZEj@rW&zRXSdXy+>B-Z$RqOS& z?#8GzWJQ=WGB7kVF)#=Mb*JPf2NdNO6zeDF7p3Y|ub(z#?N;dL&vC1ej5chdbC@>SCbg(G?~3`y^R{5;7c`I~gzc zJTjI(_`2Zp!3i-FqK@uup8Y~o=4EVv@{Mh|*ZkPFy!QY2{L$B13DeMJ_opy~hz1!v zY;=EJzj~@C?{x+4n!=m<8y+g^?ebkOdSdxs*6-%83;Cn3)-UbiJ5r(3=PZ9mVe&d1 z>z*<%JGJxrr!7|%P4W*m^8I{Vb!YOIdA=Fbf92@K@z*9Vk(w3%-{Pu1 zEJiqhF>*Ji?)=O*9Lx+1;$jR8Lcnk?&oA0+!K=s&ii>CgB~aAV3-E%Ys!#9$h@KoE zd=Nwli|hx~K7Ck1m48+Y7KMPiDEBOg5Y$&}HBz!~K8>&ivvWsjdNdI|RLlDIz zXAYvQ = {}): Tokens.Ima href: 'https://example.com/test.png', title: '', text: 'test image', - tokens: [], ...overrides, } } @@ -176,43 +176,56 @@ function createImageRenderer(themeOptions: Partial = {}) { } // --------------------------------------------------------------------------- -// renderImage – imageHorizontalAlign +// renderParagraph – imageHorizontalAlign integration // --------------------------------------------------------------------------- -describe('renderImage horizontal alignment', () => { +describe('renderParagraph imageHorizontalAlign', () => { - it('returns ImageRun directly when imageHorizontalAlign is not set (defaults to left)', () => { - const render = createImageRenderer() - const result = renderImage(render, createMockImageToken(), {}) - expect(result).toBeInstanceOf(ImageRun) - }) - - it('returns ImageRun directly when imageHorizontalAlign is explicitly "left"', () => { - const render = createImageRenderer({ imageHorizontalAlign: 'left' }) - const result = renderImage(render, createMockImageToken(), {}) - expect(result).toBeInstanceOf(ImageRun) - }) - - it('wraps in Paragraph with center alignment when imageHorizontalAlign is "center"', () => { + it('wraps single image in center-aligned Paragraph when imageHorizontalAlign is "center"', () => { const render = createImageRenderer({ imageHorizontalAlign: 'center' }) - const result = renderImage(render, createMockImageToken(), {}) + const result = renderParagraph(render, [createMockImageToken()] as any, {}) expect(result).toBeInstanceOf(Paragraph) expect(result!.toString()).toContain('alignment="center"') + expect(result!.toString()).toContain(' { + it('wraps single image in right-aligned Paragraph when imageHorizontalAlign is "right"', () => { const render = createImageRenderer({ imageHorizontalAlign: 'right' }) - const result = renderImage(render, createMockImageToken(), {}) + const result = renderParagraph(render, [createMockImageToken()] as any, {}) expect(result).toBeInstanceOf(Paragraph) expect(result!.toString()).toContain('alignment="right"') }) - it('returns ImageRun directly when isAligned is true regardless of theme alignment', () => { + it('does not set alignment when imageHorizontalAlign is not configured', () => { + const render = createImageRenderer() + const result = renderParagraph(render, [createMockImageToken()] as any, {}) + expect(result!.toString()).not.toContain('alignment=') + }) + + it('explicit attr.align takes precedence over imageHorizontalAlign', () => { const render = createImageRenderer({ imageHorizontalAlign: 'center' }) - const result = renderImage(render, createMockImageToken(), { isAligned: true }) - expect(result).toBeInstanceOf(ImageRun) - expect(result!.toString()).not.toContain(' { + const render = createImageRenderer({ imageHorizontalAlign: 'center' }) + const result = renderParagraph(render, 'plain text', {}) + expect(result!.toString()).not.toContain('alignment=') + }) + + it('ignores imageHorizontalAlign when there are multiple tokens', () => { + const render = createImageRenderer({ imageHorizontalAlign: 'center' }) + const result = renderParagraph(render, [createMockImageToken(), createMockImageToken()] as any, {}) + expect(result!.toString()).not.toContain('alignment=') }) +}) + +// --------------------------------------------------------------------------- +// renderImage – basic behavior (alignment is tested above via renderParagraph) +// --------------------------------------------------------------------------- + +describe('renderImage', () => { it('returns false when ignoreImage is true', () => { const renderer = new MarkdownDocx('', { ignoreImage: true }) @@ -221,26 +234,16 @@ describe('renderImage horizontal alignment', () => { }) it('falls back to text when image is not in store', () => { - const renderer = new MarkdownDocx('', { theme: { imageHorizontalAlign: 'center' } }) + const renderer = new MarkdownDocx('', {}) const result = renderImage(renderer, createMockImageToken(), {}) expect(Array.isArray(result)).toBe(true) }) - it('preserves other text attributes when wrapping in aligned Paragraph', () => { - const render = createImageRenderer({ imageHorizontalAlign: 'center' }) - const result = renderImage(render, createMockImageToken(), { style: 'MyStyle' }) - expect(result).toBeInstanceOf(Paragraph) - const str = result!.toString() - expect(str).toContain('alignment="center"') - expect(str).toContain('style="MyStyle"') - }) - - it('center-aligned Paragraph contains the ImageRun as child', () => { - const render = createImageRenderer({ imageHorizontalAlign: 'center' }) + it('produces ImageRun with altText from token text', () => { + const render = createImageRenderer() const result = renderImage(render, createMockImageToken({ text: 'alt text' }), {}) - const str = result!.toString() - expect(str).toContain(' Date: Mon, 29 Jun 2026 16:31:06 +0800 Subject: [PATCH 06/10] fix: use orignal image size if size is not positive when scale --- src/renders/render-image.ts | 2 +- tests/list-complex.docx | Bin 10581 -> 10578 bytes tests/list-number-restart.docx | Bin 8891 -> 8892 bytes tests/markdown.docx | Bin 52782 -> 52773 bytes tests/math-example-from-file.docx | Bin 9986 -> 9987 bytes tests/test-math-comprehensive.docx | Bin 8906 -> 8907 bytes 6 files changed, 1 insertion(+), 1 deletion(-) diff --git a/src/renders/render-image.ts b/src/renders/render-image.ts index b6799e5..f3fa5a9 100644 --- a/src/renders/render-image.ts +++ b/src/renders/render-image.ts @@ -95,7 +95,7 @@ export function scaleImageToFit( imageDefaultSize: "actual" | "auto" | "fit", isExplicitSize: boolean = false, ): { width: number; height: number } { - if (imageDefaultSize === "actual" || isExplicitSize) { + if (imageDefaultSize === "actual" || isExplicitSize || width <= 0 || height <= 0) { return { width, height } } diff --git a/tests/list-complex.docx b/tests/list-complex.docx index afcc2bc4c0a52ec31d0d0ebf7c33ad12206fe801..f52e9c788ab1a3a5115b11781f0330372d410407 100644 GIT binary patch delta 3868 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 delta 3979 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 delta 759 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 diff --git a/tests/math-example-from-file.docx b/tests/math-example-from-file.docx index 513ab997726805c15e7d421fefdf137e0dabf13f..a628830c2c0e66a23cea762973cce1396068afb8 100644 GIT binary patch delta 896 zcmZqjYxd&~@MdP=VgP};6SHO&W@O&-`|_53#fq8byL0}pkN;P^V8;7W*|!HOug(x!%IPR5 zanU1nmC)MoZVUH`{C7O!%-Ot382X>B5tvrrb?o5mY@Hno4!F-fUZIuKxlJ*mYomDd zg*)o9iMt9eTby++FA?1qQ}dat!0m)cHb=~-1BLoMZ!=ufmx?UD^lwL%fJfs(HeR)g zIcl2wHZaclRxZzTQgmggMZ}Kod50(7t2S-Qy{+~(#bNh9&3`fb_VF)1cIwM)p@s-W zR#Co+jCz^q**6M!HysF{{+B8H-Qi8QzqmElSj809Z7_%@@kb_KF7g_^ zI(6xB#`7o1pZ;u$QkXU|M{08BoU>sn%Om~dKc~3K?faEw-q#&6-|Nrms%aY*{(Rei zxQ-DP85|6tfZla|W{dzc1H%+C1_mKuK$qulP8ZZ-21dms5oKV!Y!l%F#nMsHgFtF> zyZ9j>=_PRhD8w!K5hV0iYB`XzRQeo9S&8gtkXVNNG9ZUv!3Uy1VRDUPCs3G8$p}bV zDp>%@A|+2Cxkt$kNd8u`0g@KVW}NV-pIokN1{7PTEX(LI`HZq6ko`_s*0e)}fg!#q zHK$lVz?+dtgaMSOApVeFJZai9AnzP7!Egg<1XwfKK}8CvKUzhWarfj(6=3?CJO{|G zoxBUoz6)eKO#ZDR4-}VHm1Sg{Y^e&eZ=ISf(`Tv4eA4ohXR7kZgPf+(H|@a!V5%%; zg``S^C9@|VQB{Zssp)RBJaQDM<`@UMnk-pR@D`;2({OHXYF^8w<5Kyb?YTg6 xtASVsVLp%*CqKDTUJm3IpyTp@j$>7rte_ymi(&%E)r>)t&!`!&{Za&J2LNX>K(zn> delta 845 zcmZqnYx3g`@MdP=VgLc#iQGzzwiER<7;QI(YcMj}Zf;<#;Q&&9Ighh4+D<;ouU2pC zd^hIr-W?w1j0_CTObiTyKz%9s$pJ$({Jv?S{)X8R-?zW!#&AJba&Z|c_CN#0OStn+(D_d!^%1`-r+;p!)0S~Xng@cck zv_DMceK4i|#{&O657omL4>^Ak;`?&&G-J+fvut-;so&y1ihusP*FVeaZf+OzqNxvB ztP>7e)bF~sGL6fnHD7NxtJ#_M)H`3?nkuaB71VF$E8j5vZulZsf1cy7Y`&c2Rq9MV znYqRLlVMd|q^^MO=b}l^CU2Ru_LHXO@f4fWr;5H@4c%QFv-DNWqxfsxE#J<*ub24+ zj|&b4P&n_pJ~KvunSo)77z2Y4Fr3Tti#BHpYBB?(VzP)bFkZHc@PT6KnCL+uHMv9l z5RmkiH~OJy@oc+^j>P&NaKtyh+1bf0`ySrN#7uPkfYF2cYNUzD0t ztRLXb$Rxr5N>mV!$SBP^_PvUzDm>k(;x0Qmp?W1Ch4>r!M_o zdpp2r_F9#!9g~i@bR65g%+}%YuZi1?eta)uR&#l`C+Gfh|9i#Ts5`F#}2MG7K@qiVDgKL^9pV+$mN)p z@aCtO$md9v5}xbFG{qiW%-xXsr#qKndZpb_E+%0egFD>8)>0QeHGizwa(|sHOH*=& zVAC8+rcc>Q@>byZq_n~D?c7>icdIQ6LG|My=uqt!>r%UUl+1l->g@S;yF^W#@|`~ zuEL~hC8nfBsbFqLKdcOgrDx?Wu7SHz|D&4ZAyae(hH6lt7X!odIz=<_q*a4<74h>I~W2mu4SJb$w}uM#sbDxw6Gf$>r&zz2$@UcrMv zYO=rZAs{IvasViFS>z)~=&0CoASYM+97vgsvIqr0*6zuU ziaNkR&Qp|SOrG4Mr~qWI1+tAMp9ZtvD9SRaNl$i^mYb}p!~-@g`EA@aS)hf^z;uCX V;n~R{N`x$wnmk3xfb9_26#ydbOS}L8 delta 943 zcmX@@ddihMz?+$civa{|Cvqz>+D_EdV6@#BuEEG?ySahUhXqKTWj)TyXgirvUU>2f zZsB@c=esfGtU-QmYVmno11novrRINnzc>1_P1!rl{33zxBb7a|KBn|k8f4yw}iPlrLC7* z7I2v4w_Yi2HG7?E<2>=R5BIe#Qd%V}?P6P=EUSO8w$=Q$)P}gG?k4x$O|!Y)?lEUQ z*7x4Qa5{@qd%^9fqcs+{q@<7SkL0ybRyodPBYejA4tKJ#)Wt~6A1h4kw@I=zC1*G^ ze&bv2*|mNR`|3M~*`14=wO;nK$t{{*u!P^QFX4Krr@7>X3-(9nufG00@k+$2x?mXr zT~_@atk0tBz0Iwz`7~;LJe#`zK%3=$uG#mz1pJRnzstY&SnS)T|6V4t9Umj+wcG7< zbXk~FDD`$yjnBOJYu+x#lb#x$e4MjSZL`vBvCEZ{o;_K;zU=u9ud6$c>|Z0!DLd=_ ze~T~Tu=wC$0EKhi`I&Dxm>C$v#TXcbfZ<%8U$ohhSCJVQ9nk{Hz__Uw-~+`}pWs0t zH90`|5ReoWIRF&8BJvR=bWChHkdr5V4y4Rh@-s-xPpL6rVg*UJ=ONE-x$YFTlVM zUzD0ttRLXb$Rxr5N?1UTOnxmdYh4VN(*vnMQ2_L5%*wjBiNF-Km7Re>7^n>angl1$ z7ZjZwp}?a6vOl8ow$db^>=PhHRp=r-IZ;@2@=OIDa2kE|XYQ@ZKt<1h7-%;VU>8A3 zv55r*pahHVp7Rf%A36kd&m1;L$Ro6$0O|(DLyCS{ett<_eo1OEhW^RrO0rD5#3o-C zlb@`m!~+bSd_`Htq{+RC3PAQcAlq>A88F*WT6mHY7o+NAZY6D?l(~{D Date: Tue, 30 Jun 2026 19:05:26 +0800 Subject: [PATCH 07/10] chore: remove unused imports and use type-safe getTextAlignment in image alignment --- src/renders/render-image.ts | 2 +- src/renders/render-paragraph.ts | 4 ++-- tests/theme-styles.test.ts | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/renders/render-image.ts b/src/renders/render-image.ts index f3fa5a9..b696dc2 100644 --- a/src/renders/render-image.ts +++ b/src/renders/render-image.ts @@ -1,4 +1,4 @@ -import { ImageRun, Paragraph } from 'docx' +import { ImageRun } from 'docx' import { Tokens } from 'marked' import { MarkdownDocx } from '../MarkdownDocx' diff --git a/src/renders/render-paragraph.ts b/src/renders/render-paragraph.ts index ba1d5ba..049dc7c 100644 --- a/src/renders/render-paragraph.ts +++ b/src/renders/render-paragraph.ts @@ -11,8 +11,8 @@ export function renderParagraph(render: MarkdownDocx, tokens: IInlineToken[] | s const heading = getHeadingLevel(attr.heading) let alignment = getTextAlignment(attr.align); - if (!alignment && tokens.length === 1 && typeof tokens !== "string" && tokens[0]!.type === "image") { - alignment = render.options.theme?.imageHorizontalAlign + if (!alignment && typeof tokens !== "string" && tokens.length === 1 && tokens[0]!.type === "image") { + alignment = getTextAlignment(render.options.theme?.imageHorizontalAlign) } const hasList = !attr.listNone && attr.list diff --git a/tests/theme-styles.test.ts b/tests/theme-styles.test.ts index 780299f..0ff1c27 100644 --- a/tests/theme-styles.test.ts +++ b/tests/theme-styles.test.ts @@ -6,7 +6,7 @@ import { createMarkdownStyle } from '../src/styles/markdown' import { IMarkdownTheme } from '../src/types' import { defaultTheme } from '../src/styles/themes' import { MarkdownDocx } from '../src/MarkdownDocx' -import { renderImage, parseImageTitleSize, scaleImageToFit } from '../src/renders/render-image' +import { renderImage, scaleImageToFit } from '../src/renders/render-image' import { renderParagraph } from '../src/renders/render-paragraph' import { MarkdownImageItem } from '../src/types' From 073c4630aa9f1695c6f1b1feb048cba5a14d8388 Mon Sep 17 00:00:00 2001 From: Syrupy Date: Tue, 30 Jun 2026 19:44:05 +0800 Subject: [PATCH 08/10] fix: adapt page margin in image default size --- src/MarkdownDocx.ts | 4 +- src/renders/render-image.ts | 50 +++++++++++++++++-------- src/utils.ts | 57 ++++++++++++++++++++++++----- tests/index.test.ts | 4 +- tests/list-complex.docx | Bin 10578 -> 10574 bytes tests/list-number-restart.docx | Bin 8892 -> 8885 bytes tests/markdown.docx | Bin 52773 -> 52846 bytes tests/math-example-from-file.docx | Bin 9987 -> 9979 bytes tests/test-math-comprehensive.docx | Bin 8907 -> 8900 bytes 9 files changed, 88 insertions(+), 27 deletions(-) diff --git a/src/MarkdownDocx.ts b/src/MarkdownDocx.ts index 0026108..c02c944 100644 --- a/src/MarkdownDocx.ts +++ b/src/MarkdownDocx.ts @@ -1,4 +1,4 @@ -import { Document, FileChild, IPropertiesOptions, IStylesOptions, Paragraph, ParagraphChild } from 'docx' +import { Document, FileChild, IPageMarginAttributes, IPropertiesOptions, IStylesOptions, Paragraph, ParagraphChild } from 'docx' import { Tokens } from 'marked' import { renderBlocks, renderTokens } from './renders' @@ -57,7 +57,7 @@ export class MarkdownDocx { const section = await this.toSection() const pageMargins = this.options.theme ? resolvePageMargins(this.options.theme) : null - const sectionProperties = pageMargins ? { page: { margin: pageMargins } } : undefined + const sectionProperties = pageMargins ? { page: { margin: pageMargins as IPageMarginAttributes } } : undefined const doc = new Document({ numbering, styles: createDocumentStyle({ theme: this.options.theme}), diff --git a/src/renders/render-image.ts b/src/renders/render-image.ts index b696dc2..fd07688 100644 --- a/src/renders/render-image.ts +++ b/src/renders/render-image.ts @@ -3,10 +3,15 @@ import { Tokens } from 'marked' import { MarkdownDocx } from '../MarkdownDocx' import { ITextAttr, MarkdownImageItem } from '../types' +import { getUsablePageDimensions } from '../utils' import { renderText } from './render-text' /** - * Maximum image dimensions in "pixels" (at 96 DPI) for an A4 page with 1" margins. + * Default maximum image dimensions in "pixels" (at 96 DPI) for an A4 page + * with 1" margins. These are used when no theme/margin configuration is + * provided; when the theme specifies custom margins, the actual usable area + * is computed via `getUsablePageDimensions()`. + * * A4 = 210mm × 297mm → 8.27" × 11.69" at 96 DPI. * Subtract 1" margin on each side (2" total): * Usable width: 8.27" - 2" = 6.27" → 6.27 × 96 ≈ 602px @@ -16,8 +21,8 @@ import { renderText } from './render-text' * - "fit": scale so one axis reaches exactly its max (may upscale small images). * Like Word's "fit to page". */ -const MAX_IMAGE_WIDTH_PX = 602 -const MAX_IMAGE_HEIGHT_PX = 931 +const DEFAULT_MAX_IMAGE_WIDTH_PX = 602 +const DEFAULT_MAX_IMAGE_HEIGHT_PX = 931 export function renderImage(render: MarkdownDocx, block: Tokens.Image, attr: ITextAttr) { @@ -36,9 +41,14 @@ export function renderImage(render: MarkdownDocx, block: Tokens.Image, attr: ITe const theme = render.options.theme const imageDefaultSize = theme?.imageDefaultSize ?? "actual" - // Scale down oversized images to fit page margins ("auto" mode). - // Explicit sizes (from title attribute) are never scaled. - const finalSize = scaleImageToFit(width, height, imageDefaultSize, isExplicitSize) + // Compute max dimensions from the theme's page margins (falls back to + // default A4 + 1" margins when no margins are configured). + const { maxWidthPx, maxHeightPx } = getUsablePageDimensions(theme) + + const finalSize = scaleImageToFit( + width, height, imageDefaultSize, isExplicitSize, + maxWidthPx, maxHeightPx, + ) return new ImageRun({ type: image.type, @@ -84,16 +94,26 @@ export function parseImageTitleSize(block: Tokens.Image, image: MarkdownImageIte } /** - * Scale image dimensions to fit within page margins when imageDefaultSize is "auto". - * Images wider than MAX_IMAGE_WIDTH_PX are scaled down proportionally. - * Images already within bounds are left unchanged (no upscaling). - * Explicit sizes (from title attribute) are never scaled. + * Scale image dimensions to fit within page margins when imageDefaultSize + * is "auto" or "fit". + * + * - "auto": Scale down only when either dimension exceeds its max. + * Never upscale. Both width and height are constrained. + * - "fit": Scale so one axis reaches its max value (may upscale small + * images). Like Word's "fit to page". + * + * Explicit sizes (from the title attribute) are never scaled. + * + * @param maxWidthPx Usable page width in pixels at 96 DPI + * @param maxHeightPx Usable page height in pixels at 96 DPI */ export function scaleImageToFit( width: number, height: number, imageDefaultSize: "actual" | "auto" | "fit", isExplicitSize: boolean = false, + maxWidthPx: number = DEFAULT_MAX_IMAGE_WIDTH_PX, + maxHeightPx: number = DEFAULT_MAX_IMAGE_HEIGHT_PX, ): { width: number; height: number } { if (imageDefaultSize === "actual" || isExplicitSize || width <= 0 || height <= 0) { return { width, height } @@ -101,11 +121,11 @@ export function scaleImageToFit( if (imageDefaultSize === "auto") { // Constrain both width AND height to ≤ max. Scale down only; never upscale. - if (width <= MAX_IMAGE_WIDTH_PX && height <= MAX_IMAGE_HEIGHT_PX) { + if (width <= maxWidthPx && height <= maxHeightPx) { return { width, height } } - const ratioW = MAX_IMAGE_WIDTH_PX / width - const ratioH = MAX_IMAGE_HEIGHT_PX / height + const ratioW = maxWidthPx / width + const ratioH = maxHeightPx / height const ratio = Math.min(ratioW, ratioH) return { width: Math.round(width * ratio), @@ -115,8 +135,8 @@ export function scaleImageToFit( // "fit" mode: scale so one axis reaches exactly its max value. // The other axis will be ≤ its max. May scale up small images. - const ratioW = MAX_IMAGE_WIDTH_PX / width - const ratioH = MAX_IMAGE_HEIGHT_PX / height + const ratioW = maxWidthPx / width + const ratioH = maxHeightPx / height const ratio = Math.min(ratioW, ratioH) return { diff --git a/src/utils.ts b/src/utils.ts index 2556e6a..10251d1 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,4 +1,4 @@ -import { AlignmentType, HeadingLevel, IPageMarginAttributes } from 'docx' +import { AlignmentType, HeadingLevel } from 'docx' import { Tokens } from 'marked' import { IBlockAttr, IMarkdownTheme, MarkdownImageType } from './types' @@ -126,6 +126,11 @@ const PT_TO_TWIPS = 20 const IN_TO_TWIPS = 1440 // 1 inch = 2.54 cm => 1 cm = 1440/2.54 ≈ 566.93 twips const CM_TO_TWIPS = (1440 / 2.54) +// A4 dimensions in twips (used when computing usable page area for images) +const A4_WIDTH_TWIPS = 11906 // 210 mm +const A4_HEIGHT_TWIPS = 16838 // 297 mm +// Word default page margins: 1 inch on all sides +const DEFAULT_MARGIN_TWIPS = 1440 function parseMarginValue(val: string | number): number { if (typeof val === 'number') return Math.round(val * PT_TO_TWIPS) @@ -144,11 +149,19 @@ function parseMarginValue(val: string | number): number { return isNaN(num) ? 0 : Math.round(num * PT_TO_TWIPS) } +/** Simple internal type for resolved page margins in twips (plain numbers). */ +export interface ResolvedPageMargins { + top?: number + right?: number + bottom?: number + left?: number +} + /** * Resolve page margin twip values from a theme's margin properties. * Returns null when no margin properties are set. */ -export function resolvePageMargins(theme: Partial): IPageMarginAttributes | null { +export function resolvePageMargins(theme: Partial): ResolvedPageMargins | null { const hasShorthand = theme.margin != null const hasVerbose = theme.marginTop != null || @@ -158,12 +171,7 @@ export function resolvePageMargins(theme: Partial): IPageMarginA if (!hasShorthand && !hasVerbose) return null - const margins: { - top?: number - right?: number - bottom?: number - left?: number - } = {} + const margins: ResolvedPageMargins = {} if (hasShorthand) { const m = theme.margin! @@ -192,5 +200,36 @@ export function resolvePageMargins(theme: Partial): IPageMarginA if (theme.marginBottom != null) margins.bottom = parseMarginValue(theme.marginBottom) if (theme.marginLeft != null) margins.left = parseMarginValue(theme.marginLeft) - return margins as IPageMarginAttributes + return margins +} + +/** + * Compute usable page dimensions (width and height in pixels at 96 DPI) + * from the theme's margin settings. + * + * Falls back to Word's default 1-inch margins on A4 when no margin properties + * are configured. Used by image auto/fit scaling to determine the maximum + * image size that fits within the document's page margins. + */ +export function getUsablePageDimensions(theme?: Partial): { + maxWidthPx: number + maxHeightPx: number +} { + const margins = theme ? resolvePageMargins(theme) : null + + // Use explicit margins if set, otherwise fall back to Word default 1" margins + const marginLeft = margins?.left ?? DEFAULT_MARGIN_TWIPS + const marginRight = margins?.right ?? DEFAULT_MARGIN_TWIPS + const marginTop = margins?.top ?? DEFAULT_MARGIN_TWIPS + const marginBottom = margins?.bottom ?? DEFAULT_MARGIN_TWIPS + + // Usable area in twips + const usableWidthTwips = A4_WIDTH_TWIPS - marginLeft - marginRight + const usableHeightTwips = A4_HEIGHT_TWIPS - marginTop - marginBottom + + // Convert twips → inches → pixels at 96 DPI (1 twip = 1/1440 inch) + const maxWidthPx = Math.round((usableWidthTwips / IN_TO_TWIPS) * 96) + const maxHeightPx = Math.round((usableHeightTwips / IN_TO_TWIPS) * 96) + + return { maxWidthPx, maxHeightPx } } diff --git a/tests/index.test.ts b/tests/index.test.ts index abd80e0..1f64c10 100644 --- a/tests/index.test.ts +++ b/tests/index.test.ts @@ -54,7 +54,9 @@ describe('markdown-docx', () => { codeFont: "Fira Code", blockquoteFont: "Georgia", imageHorizontalAlign: "center", - imageDefaultSize: "auto", + imageDefaultSize: "fit", + marginLeft: "2inch", + marginRight: "3inch" } }) diff --git a/tests/list-complex.docx b/tests/list-complex.docx index f52e9c788ab1a3a5115b11781f0330372d410407..b2253e5a2e2ed833fdf2923257adf8e26e32d468 100644 GIT binary patch delta 4803 zcmZ8l2RK|?*B(R{y+$w5qDCi55JU+>5TZm2!WcE8Wwfg^7`;UcF}moz*Qlce;YJy~ z_Y(X=zI^xp?s?96_Fm^*d+l}Jv)0*XuQBZ*?fY74829i1w@16te9V0&jN3+l9T(LY zseCUDXNxiAf($#f3lMahe(v|VUnW=`+HRHFX_go&EvGUk%Ua&hX@%UT62^OGK0zpb z;c{?JHQVn!{fcb6^*mO9Wa$GNi=2jSs0WM8WT_aDd0kRV0Fds*S$2^(c}b?GVw;il z^K~~gz4IjQ*66-ogDz&*x}vywINh?PaD8IQCNrOO4n#Kvr$)7h#c=o08C1;5pkN`{ z6@+%Kio5OsZpBtcI{#Gs)$O!La^QL17mX~hrghAMTKmJsv7MyY6qPzvet@no%qiOXl1XcNQq#d@v#dLIhz<-v1g@v6oK@*Cs+NvL>_0@}+!AR-nFbwt z2Wv!AK%0q0=Y&WxzX!bKDMnsx-`Kj}5EXhKtcT<|)A*`mZUiuANzpC(@;x;eg#~0m z($36xN!ob)mMd38j6H-@&PE{iyMH=h(g^xs7gh68}(0XF8 zNB2hgfJ)I``<_g)OBH;d8pfQImPxd5?`w(agaNH`41^B^kbagA1Y<_W;dp`bldgLb zq+ge{F^?b$&EF(#xpNu?vx!f#NbrE`3&DXC7M^i7+1dKo4ywW;?GzXOXo{2Q)P0k2 zF4S$6z-Ky!3Q}+){j#+*B3~qTU4qD05p#2{(J$ZRY&#i~?A*yq6BD&r+TY}cG2g>l zUphU+*z{x30FYp@wtIfbXw|xU^7$QowB~CQ48<=H!{BAamnoJBvyv8x++NRIpF!s1 zBIO4*gtqAtF@IUs;&OhL>`^RMCX6V9PGu5|XKa{r9;vmi9__8n_(~ag6!a5y0lmkT z7LN2C;|x7hSo5%2elC*sQ|p#k=A5F+WC9t`z3 zEgP9b#PiYlXa_?!-mKve7u>J~o*fTI^;Kz}umTBZ`1um3 zN)t++tVEIID+L*(e=RjGTfJ7ew7|v`Eb4ZphqY*{dy`{C0`u}kPK2Hfewl~1$6G5~ z?KXs{70$MCOt_Fuj#=4xS3kM=V0Eo4DBFJpfgIskU)3sd^7G5olxkw;$tqzNQ2dyc z0wzGiRn%EVRVJoFhzfAra#@5~;}5`MTbtpE)Lp;GHrFeqy%KRkLsm7+#!~3M=G_=) ze5xFRQY7vs?qqODzv6CgKFf1-iO*~#axWA4Mi67=7XcUYN6cf?$HOz$ew5HgbCM`S zDBzi||LT)&c!rUJtu3d^+^`K-?#GgAfqtaY>Hy^xnO`sVZ+o2}8H>t;)vY=cwi_@X zQ-rJO*c(=Ww|)(uK!xl?CSsp2)oz#=fx0F{j5SB1!}nDgu3=AFB?2BZEfCuhpT5Eg zzA-v)W3GseksG#sY7uD`op(=HMV?L&63Glo$;VP?D*B2?D&D)hL~QW|bKNh_l6!0}HSM<@$Mg66oKLqv&1}K(h zJXpU*i=G`w?IXRk>9<23zXKG*P7$6lUFWMs%(OprxNT}nsg2esF)&&M`FJY!N_+={r5 zlB=u3#RK0-A(Y$6>@GMiYk-&MuMbk&#g%MZITR=Ef$_+|Riw>}HSZ%};Pe*DrX)*- z=BB-NPe)kb8=h;HEeO}!&ZIzc46+lki5Bp9D3;T;NcW+Ut=V|JYnAI^n%jc@<%STY z_$2F(*HWJ>hl(ws)riJ{j`TqHC&V zfWL%fvFXQx;$D@inDC2H4IcP0UA*Y0zhc4`i>wn3oJ*RQ4w!jQuXB+X?F)|Szfw;{ zKFyV%*Nly4yX_X;d{~+r$%xE|YYdKx#C&68-uMw&$l9Ts&T}wJMo^uJZkFj~*~8g7 zBKhL_(kJ9^h$d6>;PFpfO0lx0dN~UwQn9iFj_JzccI420z8F8vLT}c`Iro7lg9_Yn zK{xS1;=V0)@ThHK&|HR(PErwXq@fEmxjy_n|C_$cbc09KgxYrD(n)$<6hE0zY89Ru z(%L$JV)JHWEWd1+85TKTD+4x7eRM6U1CG1Dxo3?I86oe$*?2x>VfpELjr;0JL%eI% z$1=ZX&VD#sjsr$@PD2;h4iA$(o&@V?fmfNT8wE@alZ@-GTNVp9+c5NL*lGhg%|gh5 zb2;wM0u&sL9@cP+SnJ9Rt8|RSx;9ShpxPGJ>bKmb3iG>30jFW~U~)oEV+t z*%~SKA?JGAXOqRRhoZp4k%kBz`^_)X=ar8SXEHo(t^^E>OsbndSzpa7FlM?w0!Lo8 z=RRfUuIV<>mcU@r9S!bd;*zISl#nD2&OZ9iF3Al|6DBjLNVgulbfefoC@EdANgq`s zj~{umOiVrA73b(e(%9L)Eq>2k>6ZCDd1Crp5VAR@TcP)E9;n8X(vhZ$Yphg~BbA+B zR}j!XRka>sAqwI8;ZOwB!dBQ}d^zc|**2&;=m3g54rq3dXx7hAPoNt9PL|UdYSspK zTPhdPE2A`-&VkNH9(s2U#y<$QTw%Ky{`*u)ETW)46^l@v7`+;_319WE)<+4NOH>IiHk9eGXf#QUmGF#q;``Y8LnhBfHLDoIyiq3zxNMiDx+fN0D8zjBp6e3W za5DUDDm%qNi*so}r<+gPMTS>G`SSxCsz zSdFM$e=64Hg^3@IQ_3Ej0sBdAjKw;~G50iuCMz_jIUgfMFLju%X2ZlVqdcSOBlz$3 z>Q6Fn*6U}S-3Dim<9#9fx=!b2f{=3IryU;+Ynv-3j}9DpiMzgSNjrM`LG{V8N$DGD0?HcZx5^5FvE zDnjDb!R1==%%MWpuW?u>zBn7GBBXI9kHNSq-Z?v`ZKQb*Fkmikgiy~bM-X^*TuB$F z_tL=;i2nEIZb@~nFb)#{AmIf7h){pd?qFw2eiv5{dn*^d4KaZa;?aZ>%)dID^8h(_!2ySC$b*4mN>KjfuPSqYvPULo8O-2C;0{3qC&@TEwx@dFR;p?91K$FH|ysR}E&59XU z*`FIK9MnRAG-re>zI#FHe2~?1yvR7U8N76V>iJfIdp1O*jbO_F9KL>V&ZFl0!b}2Y z`O8WqR~XhFK0noMPGdA2v!nF~qr|uJVNfC&$m~XK6x2LWL6^9owu?H}Ea}=xd|Kk5 z^4Ev0O$>c+?VIb6N#z0g)uGkn69S>2rIl0VH$y3ZYy32yK6`J0fo2?JBoQ1Vp8VvR ztKPJ(7FZQJ#w@3(gsXQc>|0g}-3ybGs|3GEzfgWivd2ZMwWbz^1dP(-JJ(sf-wM?i zg~VBjav7>$=2E&mnC}gK!R?J{vXeDg%OL}wt9tM5t{IxrB4wLV)`5c!ZPEKx^wL)c z*o>~izXDCXCMUL{_wb9klE+i`Ty%Mfwn)KGW9Yf{YBVRUeJAq|0wdb$Rnf?T+aYT9p+w1f5}WsuP8zU4;joI&{&+);$5#a|OL| z{loNIp-v$+dUCopFROO9kg7XBa1`OnBTA=~p~g}*@GpkBy{59Y+-5LkeToSh2+7sn z*FsWJ4^LfSI?*Upwi$(BzoM8pC%!r(D?$N5D1cw{}wk$`R7M*xhmym$>V%vs7sOpmI^~9}8+6 z<{B&u)4?T=%nrL7&5CGy!f)0RZvcOC@ovWoqay#qyLJKcpc~abpVaYe*oe~iAbm0{9ntqxu{l8^jBLphke2Fq zxJ2ffy7a{RTM0`6C zVkX__wb`nS$!sgluC>5j8954!2>9;5!fc0&2(sH0fo_k2%a#^{!2l>u@|*iHY77!P zfd#Y?Yq@deTJ@%;r|4V)$fOh9THP*=S|@)A1;J73`_p# zc;RLmij)?l8$gUGi}mL6szGzoVZ)0^Hwk5XMI~6A`j|h@VH%~5YWMV6!PyRcPMlBM zhkKuY)1dugrAC(U65|iwzc;po6}zFN7$}aZ007e8-@dQaWREaz>jto8O6J@4D-IO_ z+Fgf=y5+6|o2F^K(@1;Jd>;iAJ=9bFH<+~4(9p>NxAl_WZ2UXw{xR|hHuvzZm=eoQiylJ;D<>mIts;L$ z|BhWbc3KexB>-URY-R7l{}1}xHe*g~!V1dZ5Gtba|1pf}ox-BoAKW=u%ub7j1?yvH zxs!HKQZEdT_X{u6oYbz%$x)uw}k>&qWc1H@zakO+89hU&sGqzg`{|6##(qI4p delta 4741 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 VRswVNQJM~Nq^3nVGGwT2oGG#5Eu~o{ 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 QUJRIcR1UVL@2|1{1K{3eH~;_u diff --git a/tests/math-example-from-file.docx b/tests/math-example-from-file.docx index a628830c2c0e66a23cea762973cce1396068afb8..ed65fa33842db396b4ecb888fff1c0d6c64229c1 100644 GIT binary patch delta 1800 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 diff --git a/tests/test-math-comprehensive.docx b/tests/test-math-comprehensive.docx index 9272e0fedd83d9473d3b2185b9c47655858ec226..adab67a78814807eaa83df307f498f543d217d2c 100644 GIT binary patch delta 1798 zcmX@@dc>7Cz?+$civa}o#@w68tH2DR4Ael>#z-|r5WTsH(TgPt$cTCDb$9g?Rt5$^ zT?PhzpqBFdq7?n&lFFRaV!evooTrh|#kZ^k{%OnYH{X{qdxGZM0?x^2TITu8K38eB zjlnnP~Wqn&tUSA-JdpXR%4T4s`owcHS6Hld&)c3N!@X>{jMA} zg-v>a)}?ZWKm2Y6Q63wfKN34VOY7+@t7>-5-TJ1x?YP%&3w-~%_HpuF>4TGIb6fCk zJ9(!cUA;G^d71&se?7)uCv!s??=I?o zSv5B>ZqHh-g)b!iH{B|+fAGpfUBb9U@(16uh7WB%diBqLa`jH}zQr}SN#foC1C|Va zp*{I2%^Z5C@)v9G<26w*NL>EJP4F*sdS&ecpN#JleG3*%2tV6r@n-pC0ZzO6+pl)? z^(VDBhYGCRaa3Yb;*5W(7B?+FZTVC2<~4J8P0;^;9oO7XJ3T-5{OdO!&uq8iX z?k{&$!4I0!0WZ9}o-$mN!i=5f+OLTgQKfWxKdG8p$1e=+?(14^!(Je^yG1C;$9K6!m~@?mZ*7VU1~>61TlYu779 z_6c3M!?DtwH%j;UOA%E&1Ko&h6O$JVa%VHn<{s^B4o}zFp>RpqUpVXm0;Ts2H!MndDmxEZ%DcKCT6bYJ?n?5%=;j59Y^ z$%h#!EdMt#&iQ06&vTM>Wr{__j?Q_9C*G@;vTTaIo*HYoV59v(`R?i46R(84stcA8 zSj)P8@>U)dA1}5fn`_G#_U8$B>O{-BTdTi6diirv-wT!bQ!?Y0x$aY0qV;a|?)IFh zDf4T$Y9C)8GS}8fcL7XJL&?_3WL1rAWzv{{wclo?bUO^y{%1Q$z<0z8oNX@cN> zFk^C%@By$2QIUOM71u=GLnKa!Ed>h{h@XLIv6uV^kujED0+zWY?FCaRH`!IT6Ku{! zSpzW5B4-AsZROm-bi14lFG_hh`GTB*JV*pwl0peiI7a};YMv}FFM)_gdwDU&Rg=Ty z!3FN*N_lBU!O2tQ6~V^ul$VzD1nP+|O3f+O5AbGW5@7(9(co~H{8nDtIu|ah2U3Hk zBqnBMUED-Q28ONd3=G0>SAZBbf|KV9icXGD;86fMH=^>k(j=hp6Cg%aXeT^5QCM{H zOa-2LkitiQ=H8kNRP+ppLB2r%MiB;vl>Fp?qWpql{ltO-P(^_5p7Rf%A36kd&m1-e z1|fu2AnOoNH@Fr_%g-;#%P)acBq;isfKgtlB+ax%Z1Qz6`N>*JJm5eoRFr0nncS-g w3BV0Np7!K3P~LkWPku7Dk~UbSrIIw`vB{xIkiZ2R#V9;^s*(ZQZds6103WdM2><{9 delta 1770 zcmZWq3piA17(Rn!naNCMM$CPb8kaGvF{vrFPq{=f#S{`s)23}qxn!tqP^js`IHl}7 zB+b8d1*@jP_( z3<2%RT-z%{QFXO~WvLa{{45b#c|8H)uICRa0diO6GWi?;aIpmdV<;qA6u!$YA~I&5 zAc83t?tAIC&HKp;^t3hku4&Lt?y=CG#zbUuD)~xYL>6h=dUki3H6!<97p3v0qih3{ zgNSWF_HB>3e%(@^s3TFtz3ohRTj{!gyTh%-*mthwOHiCO{M->hO*s`@o*LX%Z=3GG zf0#L>BIT;89;qg6%6nWY+diF684uI*2xIoKyDhD|FrJC78O3=nhO3t%D)ypbw}^@;+yw^fyit@8|$|yRGxE$e~c9=r>3%Z16sCGJbI#OVhN!EW&f| zL`F~7+!A%}v<9O|OYg7GY&-eUY&Y_O;yERLIad>=W7-6YmT}PSf`)Su3r-9)4_wR< zq+8SZBF5O!<818V(NJJV5Tzd%AGhau^@{NncY2>UC%gSTwh58L#Y+aw8&%yVrMq@! zBp8PEpekZ4F8UOV;=~on{sUR+{DWORy}hfVgwwTo@1-g?UJ_;=SyHS<6ak8y!*fyt zn<;i02K8Z&TF2sZBKE?^d$01bef8Y=`o~tk5TvcJ3taLcB1kR+U)qI4zh>OC#gD#f z4SVpW=dw#>3wtmsL84$9G^rN{^!e3?hAiEZDKnVhW<*^Y>!|ayxkHWjP$9zm|BICp2esQ2KOvB>0lF3EJZ)B z^OCWbsM+gO)PQ)5qIpmG>T-gqMhgwJxA4fmk2LUCBP+cpJbO7fWMnO|DkCn+uE1;- znV0*wb{H;lV%hrsz-GS&$Sr$XZ2Rxm6fMOEr1pWYm0A0rWD5<_gH;oF><7Pvk;tz5 z4EzhF@Mpo)Ng;4P#;M*=$Ha#9)X1A_u3XPh=a)Y(A?YQA?D;N!9@*3{Uh)|5oRAwQ z4JP>56K$TZYwLF#sWd0nl)Nnqv(LUJiC>Mk6V>GxJknfor1~3qf+fg>R{qF);;UY3 zDZSJ*-*loYcku|Qc=eK~w6{})I&Ex976i)5=%4sode4DVND4f1$S4P0tpaXA(_lv| z8aXqJPGIiB3g}@{4KwCpt6)YOc4P*q!RNt_P}Am_5J$7I8N`N=3nLu__kXEm(1~;c z&hwDOf~AJUfhC9R3d=b1O4L`w4{RjQFsH}_N2w72>=K3W!bSTd?06ms9W0<7rv}<_ z3ZIlC0sxNc002fiV`tYj(2GK)z?`-Wm4Pk*nBoCo{w%Il7Jz3cG>Mk;rCWd2Ktmc2 zdIg0G_Wgfv%H_25KOjacv^P}a7b|i$hN+GGZ_xn-M*?L~(KqG-fC&IHsYt|8kV~b* z%?PFv5YFJ?f2>Q8WdK%E;WGoDLsldBnM#A16dFP24jydBQ^0LBB<$KtBOpS+BpUpa z0Sh3@9;~NPsoGEcEqdyv5GwKz^bo%&762>>AeTVaCV~4EG936j2`X!gJ Date: Tue, 30 Jun 2026 19:51:00 +0800 Subject: [PATCH 09/10] docs: add font and image theme in README --- README.md | 36 ++++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 24aa3c8..1cfecf7 100644 --- a/README.md +++ b/README.md @@ -203,8 +203,21 @@ const docx = await markdownToDocx(markdownText, { // marginBottom: "2cm", // marginLeft: 72, + // Font families (optional; uses Word defaults when unset) + bodyFont: "Times New Roman", + headingFont: "Arial", + codeFont: "Fira Code", + blockquoteFont: "Georgia", + // Remove blank-line paragraphs between content blocks collapseEmptyLines: false, + + // Image sizing: "actual" (use native size), "auto" (scale down only), + // or "fit" (scale to page bounds, may upscale). Respects page margins. + imageDefaultSize: "auto", + + // Image horizontal alignment within the page + imageHorizontalAlign: "center", } }) ``` @@ -215,7 +228,12 @@ All theme properties are optional — override only what you need. See [`example | Property | Type | Default | Description | |---|---|---|---| -| `heading1`–`heading6` | `string` | (various) | Hex color (no `#`) for each heading level | +| `heading1` | `string` | `"2F5597"` | Hex color (no `#`) for H1 | +| `heading2` | `string` | `"5B9BD5"` | Hex color (no `#`) for H2 | +| `heading3` | `string` | `"44546A"` | Hex color (no `#`) for H3 | +| `heading4` | `string` | `"44546A"` | Hex color (no `#`) for H4 | +| `heading5` | `string` | `"44546A"` | Hex color (no `#`) for H5 | +| `heading6` | `string` | `"44546A"` | Hex color (no `#`) for H6 | | `link` | `string` | `"0563C1"` | Hex color for hyperlinks | | `code` | `string` | `"032F62"` | Hex color for code blocks | | `codespan` | `string` | `"70AD47"` | Hex color for inline code | @@ -225,7 +243,15 @@ All theme properties are optional — override only what you need. See [`example | `del` | `string` | `"FF0000"` | Hex color for strikethrough text | | `hr` | `string` | `"D9D9D9"` | Hex color for horizontal rules | | `html` | `string` | `"4472C4"` | Hex color for raw HTML blocks | -| `heading1Size`–`heading6Size` | `number` | 18/16/14/13/12/12 | Font size in pt for each heading | +| `tag` | `string` | `"ED7D31"` | Hex color for tags | +| `border` | `string` | `"A5A5A5"` | Hex color for table borders | +| `tableHeaderBackground` | `string` | `"F2F2F2"` | Background fill for table headers | +| `heading1Size` | `number` | `18` | H1 font size in pt | +| `heading2Size` | `number` | `16` | H2 font size in pt | +| `heading3Size` | `number` | `14` | H3 font size in pt | +| `heading4Size` | `number` | `13` | H4 font size in pt | +| `heading5Size` | `number` | `12` | H5 font size in pt | +| `heading6Size` | `number` | `12` | H6 font size in pt | | `bodySize` | `number` | `12` | Base body font size in pt | | `codeSize` | `number` | `11` | Font size in pt for code blocks | | `lineSpacing` | `number` | `1.0` | Line spacing multiplier (e.g. `1.5` = 150%) | @@ -236,6 +262,12 @@ All theme properties are optional — override only what you need. See [`example | `marginBottom` | `number \| string` | — | Bottom margin; overrides `margin` | | `marginLeft` | `number \| string` | — | Left margin; overrides `margin` | | `collapseEmptyLines` | `boolean` | `false` | Omit blank-line separator paragraphs | +| `bodyFont` | `string` | — | Font family for body/paragraph text (e.g. `"Times New Roman"`). Uses Word default when unset. | +| `headingFont` | `string` | — | Font family for all heading levels (e.g. `"Arial"`). Uses Word default when unset. | +| `codeFont` | `string` | — | Font family for code blocks, inline code, HTML, and tags. Falls back to `"Courier New"` when unset. | +| `blockquoteFont` | `string` | — | Font family for blockquotes (e.g. `"Georgia"`). Uses Word default when unset. | +| `imageDefaultSize` | `"actual" \| "auto" \| "fit"` | `"actual"` | Image sizing: `"actual"` (native px), `"auto"` (scale down only to fit margins; never upscale), `"fit"` (scale to page bounds; may upscale) | +| `imageHorizontalAlign` | `"left" \| "center" \| "right"` | — | Horizontal alignment for images within the page | #### Page margins From befa89b2fc61da82a69278b57b854c23f1b5242b Mon Sep 17 00:00:00 2001 From: Syrupy Date: Tue, 30 Jun 2026 19:54:17 +0800 Subject: [PATCH 10/10] docs: add margins in CLI help --- bin/help-texts.mjs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/bin/help-texts.mjs b/bin/help-texts.mjs index 8773fee..10c7d96 100644 --- a/bin/help-texts.mjs +++ b/bin/help-texts.mjs @@ -47,6 +47,14 @@ SIZES & SPACING DEFAULT DESCRIPTION spaceSize 6 Paragraph spacing (pt) lineSpacing 1.0 Line spacing multiplier (1.0 = single, 1.5 = 150%) +MARGINS DEFAULT DESCRIPTION + margin (unset) CSS shorthand: 1 value=all, 2=t/b+l/r, 3=t+l/r+b, 4=t r b l. Units: pt (plain number), "cm", "in"/"inch" + marginTop (unset) Top margin; overrides shorthand. Number (pt) or "cm"/"in" string. + marginRight (unset) Right margin; overrides shorthand. Number (pt) or "cm"/"in" string. + marginBottom (unset) Bottom margin; overrides shorthand. Number (pt) or "cm"/"in" string. + marginLeft (unset) Left margin; overrides shorthand. Number (pt) or "cm"/"in" string. + collapseEmptyLines false Omit blank-line separator paragraphs + FONTS DEFAULT DESCRIPTION bodyFont (unset) Body/paragraph font (e.g., "Times New Roman") headingFont (unset) Font for all heading levels (e.g., "Arial")