@akairos/pipeline 0.18.1 → 0.18.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (212) hide show
  1. package/ARTICLE-THEMES.md +2 -0
  2. package/README.md +5 -3
  3. package/package.json +5 -4
  4. package/src/article-theme.test.ts +55 -0
  5. package/src/article-theme.ts +10 -2
  6. package/src/commands/article-theme.ts +1 -1
  7. package/src/commands/init.ts +2 -0
  8. package/src/commands/publish.ts +1 -1
  9. package/src/commands/typeset-assets-sync.test.ts +9 -1
  10. package/src/commands/wechat-export.ts +9 -4
  11. package/src/providers/index.ts +4 -2
  12. package/src/runtime-package.ts +4 -3
  13. package/src/wechat-preview/assets/browser-dist/.vite/manifest.json +1280 -5
  14. package/src/wechat-preview/assets/browser-dist/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
  15. package/src/wechat-preview/assets/browser-dist/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
  16. package/src/wechat-preview/assets/browser-dist/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
  17. package/src/wechat-preview/assets/browser-dist/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
  18. package/src/wechat-preview/assets/browser-dist/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
  19. package/src/wechat-preview/assets/browser-dist/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
  20. package/src/wechat-preview/assets/browser-dist/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
  21. package/src/wechat-preview/assets/browser-dist/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
  22. package/src/wechat-preview/assets/browser-dist/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
  23. package/src/wechat-preview/assets/browser-dist/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
  24. package/src/wechat-preview/assets/browser-dist/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
  25. package/src/wechat-preview/assets/browser-dist/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
  26. package/src/wechat-preview/assets/browser-dist/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
  27. package/src/wechat-preview/assets/browser-dist/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
  28. package/src/wechat-preview/assets/browser-dist/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
  29. package/src/wechat-preview/assets/browser-dist/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
  30. package/src/wechat-preview/assets/browser-dist/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
  31. package/src/wechat-preview/assets/browser-dist/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
  32. package/src/wechat-preview/assets/browser-dist/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
  33. package/src/wechat-preview/assets/browser-dist/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
  34. package/src/wechat-preview/assets/browser-dist/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
  35. package/src/wechat-preview/assets/browser-dist/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
  36. package/src/wechat-preview/assets/browser-dist/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
  37. package/src/wechat-preview/assets/browser-dist/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
  38. package/src/wechat-preview/assets/browser-dist/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
  39. package/src/wechat-preview/assets/browser-dist/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
  40. package/src/wechat-preview/assets/browser-dist/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
  41. package/src/wechat-preview/assets/browser-dist/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
  42. package/src/wechat-preview/assets/browser-dist/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
  43. package/src/wechat-preview/assets/browser-dist/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
  44. package/src/wechat-preview/assets/browser-dist/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
  45. package/src/wechat-preview/assets/browser-dist/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
  46. package/src/wechat-preview/assets/browser-dist/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
  47. package/src/wechat-preview/assets/browser-dist/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
  48. package/src/wechat-preview/assets/browser-dist/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
  49. package/src/wechat-preview/assets/browser-dist/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
  50. package/src/wechat-preview/assets/browser-dist/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
  51. package/src/wechat-preview/assets/browser-dist/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
  52. package/src/wechat-preview/assets/browser-dist/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
  53. package/src/wechat-preview/assets/browser-dist/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
  54. package/src/wechat-preview/assets/browser-dist/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
  55. package/src/wechat-preview/assets/browser-dist/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
  56. package/src/wechat-preview/assets/browser-dist/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
  57. package/src/wechat-preview/assets/browser-dist/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
  58. package/src/wechat-preview/assets/browser-dist/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
  59. package/src/wechat-preview/assets/browser-dist/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
  60. package/src/wechat-preview/assets/browser-dist/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
  61. package/src/wechat-preview/assets/browser-dist/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
  62. package/src/wechat-preview/assets/browser-dist/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
  63. package/src/wechat-preview/assets/browser-dist/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
  64. package/src/wechat-preview/assets/browser-dist/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
  65. package/src/wechat-preview/assets/browser-dist/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
  66. package/src/wechat-preview/assets/browser-dist/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
  67. package/src/wechat-preview/assets/browser-dist/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
  68. package/src/wechat-preview/assets/browser-dist/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
  69. package/src/wechat-preview/assets/browser-dist/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
  70. package/src/wechat-preview/assets/browser-dist/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
  71. package/src/wechat-preview/assets/browser-dist/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
  72. package/src/wechat-preview/assets/browser-dist/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
  73. package/src/wechat-preview/assets/browser-dist/assets/apl-B4CMkyY2.js +1 -0
  74. package/src/wechat-preview/assets/browser-dist/assets/asciiarmor-Df11BRmG.js +1 -0
  75. package/src/wechat-preview/assets/browser-dist/assets/asn1-EdZsLKOL.js +1 -0
  76. package/src/wechat-preview/assets/browser-dist/assets/asterisk-B-8jnY81.js +1 -0
  77. package/src/wechat-preview/assets/browser-dist/assets/brainfuck-C4LP7Hcl.js +1 -0
  78. package/src/wechat-preview/assets/browser-dist/assets/clike-B9uivgTg.js +1 -0
  79. package/src/wechat-preview/assets/browser-dist/assets/clojure-BMjYHr_A.js +1 -0
  80. package/src/wechat-preview/assets/browser-dist/assets/cmake-BQqOBYOt.js +1 -0
  81. package/src/wechat-preview/assets/browser-dist/assets/cobol-CWcv1MsR.js +1 -0
  82. package/src/wechat-preview/assets/browser-dist/assets/coffeescript-S37ZYGWr.js +1 -0
  83. package/src/wechat-preview/assets/browser-dist/assets/commonlisp-DBKNyK5s.js +1 -0
  84. package/src/wechat-preview/assets/browser-dist/assets/crystal-SjHAIU92.js +1 -0
  85. package/src/wechat-preview/assets/browser-dist/assets/css-BnMrqG3P.js +1 -0
  86. package/src/wechat-preview/assets/browser-dist/assets/cypher-C_CwsFkJ.js +1 -0
  87. package/src/wechat-preview/assets/browser-dist/assets/d-pRatUO7H.js +1 -0
  88. package/src/wechat-preview/assets/browser-dist/assets/diff-DbItnlRl.js +1 -0
  89. package/src/wechat-preview/assets/browser-dist/assets/dockerfile-BKs6k2Af.js +1 -0
  90. package/src/wechat-preview/assets/browser-dist/assets/dtd-DF_7sFjM.js +1 -0
  91. package/src/wechat-preview/assets/browser-dist/assets/dylan-DwRh75JA.js +1 -0
  92. package/src/wechat-preview/assets/browser-dist/assets/ebnf-CDyGwa7X.js +1 -0
  93. package/src/wechat-preview/assets/browser-dist/assets/ecl-Cabwm37j.js +1 -0
  94. package/src/wechat-preview/assets/browser-dist/assets/eiffel-CnydiIhH.js +1 -0
  95. package/src/wechat-preview/assets/browser-dist/assets/elm-vLlmbW-K.js +1 -0
  96. package/src/wechat-preview/assets/browser-dist/assets/erlang-BNw1qcRV.js +1 -0
  97. package/src/wechat-preview/assets/browser-dist/assets/factor-kuTfRLto.js +1 -0
  98. package/src/wechat-preview/assets/browser-dist/assets/fcl-Kvtd6kyn.js +1 -0
  99. package/src/wechat-preview/assets/browser-dist/assets/forth-Ffai-XNe.js +1 -0
  100. package/src/wechat-preview/assets/browser-dist/assets/fortran-DYz_wnZ1.js +1 -0
  101. package/src/wechat-preview/assets/browser-dist/assets/gas-Bneqetm1.js +1 -0
  102. package/src/wechat-preview/assets/browser-dist/assets/gherkin-heZmZLOM.js +1 -0
  103. package/src/wechat-preview/assets/browser-dist/assets/groovy-D9Dt4D0W.js +1 -0
  104. package/src/wechat-preview/assets/browser-dist/assets/haskell-Cw1EW3IL.js +1 -0
  105. package/src/wechat-preview/assets/browser-dist/assets/haxe-H-WmDvRZ.js +1 -0
  106. package/src/wechat-preview/assets/browser-dist/assets/http-DBlCnlav.js +1 -0
  107. package/src/wechat-preview/assets/browser-dist/assets/idl-BEugSyMb.js +1 -0
  108. package/src/wechat-preview/assets/browser-dist/assets/index-B13lCSuc.js +1 -0
  109. package/src/wechat-preview/assets/browser-dist/assets/index-BDdU9pNh.js +1 -0
  110. package/src/wechat-preview/assets/browser-dist/assets/index-BFLGVgsp.js +1 -0
  111. package/src/wechat-preview/assets/browser-dist/assets/index-BHJY0B4E.js +8 -0
  112. package/src/wechat-preview/assets/browser-dist/assets/index-BOnKEJxh.js +7 -0
  113. package/src/wechat-preview/assets/browser-dist/assets/index-BPmBcGI-.js +1 -0
  114. package/src/wechat-preview/assets/browser-dist/assets/index-BTVIa90Y.js +1 -0
  115. package/src/wechat-preview/assets/browser-dist/assets/index-BYV6TA8f.js +1 -0
  116. package/src/wechat-preview/assets/browser-dist/assets/index-BlVpb0dF.js +1 -0
  117. package/src/wechat-preview/assets/browser-dist/assets/index-BqKARoyW.js +1 -0
  118. package/src/wechat-preview/assets/browser-dist/assets/index-BzHql5Rp.js +20 -0
  119. package/src/wechat-preview/assets/browser-dist/assets/index-CPFEJ9fX.js +1 -0
  120. package/src/wechat-preview/assets/browser-dist/assets/index-CdxKyTX6.js +1 -0
  121. package/src/wechat-preview/assets/browser-dist/assets/index-CyXDvcwY.js +1 -0
  122. package/src/wechat-preview/assets/browser-dist/assets/index-DA7Z4paG.js +13 -0
  123. package/src/wechat-preview/assets/browser-dist/assets/index-DDQGWU_D.js +3 -0
  124. package/src/wechat-preview/assets/browser-dist/assets/index-DENMoE5l.js +1 -0
  125. package/src/wechat-preview/assets/browser-dist/assets/index-D_EI5vFS.js +1 -0
  126. package/src/wechat-preview/assets/browser-dist/assets/index-DpuVrwze.js +1 -0
  127. package/src/wechat-preview/assets/browser-dist/assets/index-IBlhKHQr.js +8 -0
  128. package/src/wechat-preview/assets/browser-dist/assets/index-ifI5svkD.js +2 -0
  129. package/src/wechat-preview/assets/browser-dist/assets/index-vRiJxvj2.js +1 -0
  130. package/src/wechat-preview/assets/browser-dist/assets/javascript-iXu5QeM3.js +1 -0
  131. package/src/wechat-preview/assets/browser-dist/assets/julia-DuME0IfC.js +1 -0
  132. package/src/wechat-preview/assets/browser-dist/assets/livescript-BwQOo05w.js +1 -0
  133. package/src/wechat-preview/assets/browser-dist/assets/lua-VAEuO923.js +1 -0
  134. package/src/wechat-preview/assets/browser-dist/assets/mathematica-DTrFuWx2.js +1 -0
  135. package/src/wechat-preview/assets/browser-dist/assets/mbox-CNhZ1qSd.js +1 -0
  136. package/src/wechat-preview/assets/browser-dist/assets/mirc-CjQqDB4T.js +1 -0
  137. package/src/wechat-preview/assets/browser-dist/assets/mllike-CXdrOF99.js +1 -0
  138. package/src/wechat-preview/assets/browser-dist/assets/modelica-Dc1JOy9r.js +1 -0
  139. package/src/wechat-preview/assets/browser-dist/assets/mscgen-BA5vi2Kp.js +1 -0
  140. package/src/wechat-preview/assets/browser-dist/assets/mumps-BT43cFF4.js +1 -0
  141. package/src/wechat-preview/assets/browser-dist/assets/nginx-DdIZxoE0.js +1 -0
  142. package/src/wechat-preview/assets/browser-dist/assets/nsis-LY0VT_u5.js +1 -0
  143. package/src/wechat-preview/assets/browser-dist/assets/ntriples-BfvgReVJ.js +1 -0
  144. package/src/wechat-preview/assets/browser-dist/assets/octave-Ck1zUtKM.js +1 -0
  145. package/src/wechat-preview/assets/browser-dist/assets/oz-BzwKVEFT.js +1 -0
  146. package/src/wechat-preview/assets/browser-dist/assets/pascal--L3eBynH.js +1 -0
  147. package/src/wechat-preview/assets/browser-dist/assets/perl-CdXCOZ3F.js +1 -0
  148. package/src/wechat-preview/assets/browser-dist/assets/pig-CevX1Tat.js +1 -0
  149. package/src/wechat-preview/assets/browser-dist/assets/powershell-CFHJl5sT.js +1 -0
  150. package/src/wechat-preview/assets/browser-dist/assets/properties-C78fOPTZ.js +1 -0
  151. package/src/wechat-preview/assets/browser-dist/assets/protobuf-ChK-085T.js +1 -0
  152. package/src/wechat-preview/assets/browser-dist/assets/pug-DeIclll2.js +1 -0
  153. package/src/wechat-preview/assets/browser-dist/assets/puppet-DMA9R1ak.js +1 -0
  154. package/src/wechat-preview/assets/browser-dist/assets/python-BuPzkPfP.js +1 -0
  155. package/src/wechat-preview/assets/browser-dist/assets/q-pXgVlZs6.js +1 -0
  156. package/src/wechat-preview/assets/browser-dist/assets/r-B6wPVr8A.js +1 -0
  157. package/src/wechat-preview/assets/browser-dist/assets/rpm-CTu-6PCP.js +1 -0
  158. package/src/wechat-preview/assets/browser-dist/assets/ruby-BK5aLJev.js +1 -0
  159. package/src/wechat-preview/assets/browser-dist/assets/sas-B4kiWyti.js +1 -0
  160. package/src/wechat-preview/assets/browser-dist/assets/scheme-C41bIUwD.js +1 -0
  161. package/src/wechat-preview/assets/browser-dist/assets/shell-CjFT_Tl9.js +1 -0
  162. package/src/wechat-preview/assets/browser-dist/assets/sieve-C3Gn_uJK.js +1 -0
  163. package/src/wechat-preview/assets/browser-dist/assets/simple-mode-GW_nhZxv.js +1 -0
  164. package/src/wechat-preview/assets/browser-dist/assets/smalltalk-CnHTOXQT.js +1 -0
  165. package/src/wechat-preview/assets/browser-dist/assets/solr-DehyRSwq.js +1 -0
  166. package/src/wechat-preview/assets/browser-dist/assets/sparql-DkYu6x3z.js +1 -0
  167. package/src/wechat-preview/assets/browser-dist/assets/spreadsheet-BCZA_wO0.js +1 -0
  168. package/src/wechat-preview/assets/browser-dist/assets/sql-D0XecflT.js +1 -0
  169. package/src/wechat-preview/assets/browser-dist/assets/stex-C3f8Ysf7.js +1 -0
  170. package/src/wechat-preview/assets/browser-dist/assets/style-Cif_gYUW.css +1 -0
  171. package/src/wechat-preview/assets/browser-dist/assets/stylus-B533Al4x.js +1 -0
  172. package/src/wechat-preview/assets/browser-dist/assets/swift-BzpIVaGY.js +1 -0
  173. package/src/wechat-preview/assets/browser-dist/assets/tcl-DVfN8rqt.js +1 -0
  174. package/src/wechat-preview/assets/browser-dist/assets/textile-CnDTJFAw.js +1 -0
  175. package/src/wechat-preview/assets/browser-dist/assets/tiddlywiki-DO-Gjzrf.js +1 -0
  176. package/src/wechat-preview/assets/browser-dist/assets/tiki-DGYXhP31.js +1 -0
  177. package/src/wechat-preview/assets/browser-dist/assets/toml-Bm5Em-hy.js +1 -0
  178. package/src/wechat-preview/assets/browser-dist/assets/troff-wAsdV37c.js +1 -0
  179. package/src/wechat-preview/assets/browser-dist/assets/ttcn-CfJYG6tj.js +1 -0
  180. package/src/wechat-preview/assets/browser-dist/assets/ttcn-cfg-B9xdYoR4.js +1 -0
  181. package/src/wechat-preview/assets/browser-dist/assets/turtle-B1tBg_DP.js +1 -0
  182. package/src/wechat-preview/assets/browser-dist/assets/vb-CmGdzxic.js +1 -0
  183. package/src/wechat-preview/assets/browser-dist/assets/vbscript-BuJXcnF6.js +1 -0
  184. package/src/wechat-preview/assets/browser-dist/assets/velocity-D8B20fx6.js +1 -0
  185. package/src/wechat-preview/assets/browser-dist/assets/verilog-C6RDOZhf.js +1 -0
  186. package/src/wechat-preview/assets/browser-dist/assets/vhdl-lSbBsy5d.js +1 -0
  187. package/src/wechat-preview/assets/browser-dist/assets/webidl-ZXfAyPTL.js +1 -0
  188. package/src/wechat-preview/assets/browser-dist/assets/{wechat-renderer-GgNrlSLi.js → wechat-renderer-CcHuq7M-.js} +83 -61
  189. package/src/wechat-preview/assets/browser-dist/assets/xquery-DzFWVndE.js +1 -0
  190. package/src/wechat-preview/assets/browser-dist/assets/yacas-BJ4BC0dw.js +1 -0
  191. package/src/wechat-preview/assets/browser-dist/assets/z80-Hz9HOZM7.js +1 -0
  192. package/src/wechat-preview/assets/browser-dist/editor-export.js +1 -1
  193. package/src/wechat-preview/assets/browser-dist/src/wechat-preview/browser/studio/studio.html +215 -165
  194. package/src/wechat-preview/assets/browser-dist/studio.js +1148 -237
  195. package/src/wechat-preview/browser/studio/color-palettes.ts +28 -0
  196. package/src/wechat-preview/browser/studio/config-manager.ts +49 -0
  197. package/src/wechat-preview/browser/studio/milkdown-article-menu.ts +251 -0
  198. package/src/wechat-preview/browser/studio/myno-editor.ts +122 -0
  199. package/src/wechat-preview/browser/studio/studio.css +493 -250
  200. package/src/wechat-preview/browser/studio/studio.html +213 -163
  201. package/src/wechat-preview/browser/studio/studio.ts +684 -211
  202. package/src/wechat-preview/browser/studio/style-packs.ts +201 -0
  203. package/src/wechat-preview/browser/studio/syntax-presets.test.ts +10 -32
  204. package/src/wechat-preview/browser/studio/syntax-presets.ts +19 -357
  205. package/src/wechat-preview/fixtures/all-nodes.md +2 -11
  206. package/src/wechat-preview/index.ts +29 -13
  207. package/src/wechat-preview/server/http.ts +8 -7
  208. package/src/wechat-preview/server/studio.test.ts +25 -0
  209. package/src/wechat-preview/wechat-export.integration.test.ts +49 -8
  210. package/src/wechat-preview/wechat-renderer.ts +134 -11
  211. package/src/workflow.test.ts +2 -0
  212. package/src/wechat-preview/assets/browser-dist/assets/style-C9-YtTIm.css +0 -1
package/ARTICLE-THEMES.md CHANGED
@@ -24,6 +24,8 @@ zzp publish --state ./workflow-state.json --article-theme ./my-template
24
24
 
25
25
  账号默认使用 `wx.accounts.<account>.articleTheme`,相对路径以配置文件所在目录为基准。显式 `--article-theme` 优先,路径相对当前目录;handoff 支持同义的可选 `article_theme` 字段。没有选择正文模板时保持既有配置。封面仍使用 `--cover-theme`。
26
26
 
27
+ WeChat Visual Studio 的「导出配置」下载独立 `wechat-style.json`,同样通过 `--article-theme` 选择。文件含内嵌 `css`、`editorVars`、`exportTheme`、`syntaxPresets` 和 `structure`;页首图片以内嵌 Data URL 保存。不含账号凭据,不需要附带目录包文件。独立 JSON 使用自身样式,不叠加账号 `theme/customCss`,显式 `wechat-export --custom-css` 仍可覆盖。可用 `article-theme --path` 校验或安装;默认配置引用后由现有 `typeset-assets-sync` 收集部署,详见 [Studio 配置指南](docs/visual-studio-and-config-sync.md)。
28
+
27
29
  模板样式叠加在现有基础样式上,既有账号 `theme` 覆盖和 `customCss` 最后生效。新版正文模板默认不附带内置账号署名,用户自己配置的 footerText 仍保留。旧 Markdown 插件接收可选 `articleThemePath`,可以继续忽略该字段;要支持付费模板预览,应使用内置渲染器或实现该可选参数。桌面端预览同样调用当前已配置的渲染插件。
28
30
 
29
31
  发布前冻结模板版本、CSS 和资源到工作区 `.zzhub-media/article-themes`;渲染结果记录 `article_theme_hash`。同一篇文章更改模板、版本或声明素材后会重新导出。旧状态不含该字段时仍可使用。
package/README.md CHANGED
@@ -56,7 +56,7 @@ Pipeline 需要 [Bun](https://bun.sh/) 运行。npm 可以安装包,但命令
56
56
  npm install -g @akairos/pipeline
57
57
 
58
58
  # 或从源码运行
59
- git clone https://github.com/aatrooox/zzhub-pipeline.git
59
+ git clone https://github.com/k7airos/zzhub-pipeline.git
60
60
  cd zzhub-pipeline
61
61
  bun install
62
62
  bun run src/cli.ts --help
@@ -212,6 +212,8 @@ zzp typeset-assets-sync --output ./pipeline-runtime --account-map '{"default":"W
212
212
 
213
213
  配置包只包含插件入口、Studio 容器路径和账号主题/CSS/文章模板路径,不包含微信凭据、COS PAT 或 Worker token。账号的 `customCss`、`articleTheme` 为 null 时会清除服务器旧引用。服务器用 `nezus-infra` 的 `sync pipeline-runtime` 命令校验文件清单、合并排版白名单并备份切换;镜像与 npm 依赖继续固定版本部署。
214
214
 
215
+ WeChat Visual Studio 可通过「导出配置」下载不绑定账号的独立排版 JSON。CLI 用 `--article-theme ./wechat-style.json` 选择;在默认配置的账号 `articleTheme` 中引用后,也会由上述运行时包收集部署。文件内嵌 CSS 与页首图片,无需附带模板目录。详见 [Studio 独立配置与部署](docs/visual-studio-and-config-sync.md)。
216
+
215
217
  ### 推进一个发布任务
216
218
 
217
219
  Pipeline 每次只推进一个动作。创建任务后,反复执行 `status`,按照返回的 `next_action` 继续;不要直接修改 `workflow-state.json`。
@@ -245,7 +247,7 @@ zzp publish --state <state_path>
245
247
 
246
248
  实际顺序以 `status --view agent` 为准。需要发布贴图时,把 `--content-form` 改为 `newspic`;多页图片可以在渲染前附加 `newspic` 规格。
247
249
 
248
- 如果正文由 Agent 生成或审核,可以直接使用仓库里的 [`zzhub-publish` Skill](skills/zzhub-publish/SKILL.md)。Skill 只负责编排 Agent,文章正文仍由调用方提供。
250
+ 如果正文由 Agent 生成或审核,可以使用配套的 [kairos-skills](https://github.com/k7airos/kairos-skills) 仓库中的 [`zzhub-publish` Skill](https://github.com/k7airos/kairos-skills/tree/main/skills/zzhub-publish/SKILL.md)。Skill 负责编排 Agent 状态机,文章正文仍由调用方提供。
249
251
 
250
252
  ## 云端 Worker
251
253
 
@@ -375,7 +377,7 @@ zzp monitor stop
375
377
  - [云端 Worker API、部署与更新](services/cloud-worker/README.md)
376
378
  - [封面主题和图片排版](docs/render-themes.md)
377
379
  - [离线正文模板](ARTICLE-THEMES.md)
378
- - [Agent 发布 Skill](skills/zzhub-publish/SKILL.md)
380
+ - [Kairos Agent Skills 仓库](https://github.com/k7airos/kairos-skills):配套的 Agent 技能集合(包含 `zzhub-publish` 状态机编排、`milkdown-writing` 写作排版规范、`auto-ai-daily` 自动化发文)
379
381
  - [第三方声明](THIRD-PARTY-NOTICES.md)
380
382
 
381
383
  ## 开发与验证
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@akairos/pipeline",
3
- "version": "0.18.1",
3
+ "version": "0.18.5",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "bin": {
@@ -27,8 +27,8 @@
27
27
  "release:major": "changelogen --release --major --push"
28
28
  },
29
29
  "dependencies": {
30
- "@akairos/milkdown-article-plugins": "^0.1.3",
31
- "@akairos/milkdown-article-style": "^0.1.1",
30
+ "@akairos/milkdown-article-plugins": "^0.1.6",
31
+ "@akairos/milkdown-article-style": "^0.1.2",
32
32
  "@akairos/typeset-studio": "0.2.5",
33
33
  "@chenglou/pretext": "0.0.8",
34
34
  "image-size": "^2.0.2",
@@ -40,7 +40,8 @@
40
40
  "cos-nodejs-sdk-v5": "^2.15.4"
41
41
  },
42
42
  "devDependencies": {
43
- "@milkdown/kit": "^7.18.0",
43
+ "@milkdown/crepe": "^7.21.2",
44
+ "@milkdown/kit": "^7.21.2",
44
45
  "@types/bun": "latest",
45
46
  "@types/pngjs": "^6.0.5",
46
47
  "changelogen": "^0.6.2",
@@ -4,6 +4,9 @@ import { tmpdir } from "node:os";
4
4
  import { join } from "node:path";
5
5
  import { readArticleTheme, snapshotArticleTheme } from "./article-theme";
6
6
  import { filterIdempotent } from "./providers/publish-core";
7
+ import { resolveWechatArticleTheme } from "./wechat-preview";
8
+ import { prepareMarkdownRuntime, RUNTIME_ROOT } from "./runtime-package";
9
+ import { PipelineConfigSchema } from "./schema/config";
7
10
 
8
11
  const roots: string[] = [];
9
12
  afterEach(async () => { for (const root of roots.splice(0)) await rm(root, { recursive: true, force: true }); });
@@ -53,6 +56,58 @@ test("越界、符号链接、网络样式与不兼容版本不能导入", async
53
56
  }
54
57
  });
55
58
 
59
+ test("Studio 单文件配置可跨账号复用、冻结及沿用运行时配置包部署", async () => {
60
+ const root = await mkdtemp(join(tmpdir(), "zzp-studio-config-"));
61
+ roots.push(root);
62
+ const path = join(root, "my-style.json");
63
+ const profile = {
64
+ schemaVersion: 1, engineVersion: 1, id: "wechat-style", name: "独立排版", version: "1.0.0",
65
+ editorVars: { "--brand": "#123456" },
66
+ exportTheme: { bodyFontSize: "18px", footerText: "", primaryColor: "#123456" },
67
+ syntaxPresets: { h2: "contrast-green" },
68
+ structure: { numberedHeadings: true, headingLabel: "章节", calloutPresets: { tip: { title: "建议" } }, headerImageUrl: "data:image/png;base64,aW1hZ2U=" },
69
+ css: "p { color: #123456; }",
70
+ };
71
+ await writeFile(path, JSON.stringify(profile));
72
+ const theme = await readArticleTheme(path);
73
+ expect(theme.files.size).toBe(1);
74
+ expect(theme.css).toBe(profile.css);
75
+ const accountOverrides = { editorVars: { "--brand": "#ff0000" }, exportTheme: { bodyFontSize: "14px" }, syntaxPresets: { h2: "pillar" } };
76
+ const first = resolveWechatArticleTheme("default", accountOverrides, theme);
77
+ const other = resolveWechatArticleTheme("ancientone", accountOverrides, theme);
78
+ expect(first).toEqual(other);
79
+ expect(first.theme.exportTheme.bodyFontSize).toBe("18px");
80
+ expect(first.syntaxPresets).toEqual(profile.syntaxPresets);
81
+ expect(first.structure?.headerImageUrl).toBe(profile.structure.headerImageUrl);
82
+ expect(first.structure?.calloutPresets).toEqual(profile.structure.calloutPresets);
83
+ const frozen = await snapshotArticleTheme(theme, join(root, "frozen"));
84
+ expect((await readArticleTheme(frozen.path)).hash).toBe(theme.hash);
85
+
86
+ const config = PipelineConfigSchema.parse({ wx: { accounts: { default: { articleTheme: path, customCss: join(root, "missing.css"), pat: "secret" } } } });
87
+ const deployed = await prepareMarkdownRuntime(config);
88
+ const manifest = "markdown/article-themes/default/manifest.json";
89
+ expect(deployed.accounts.default).toMatchObject({ articleTheme: `${RUNTIME_ROOT}/${manifest}`, customCss: null });
90
+ expect(JSON.stringify(deployed.accounts)).not.toContain("secret");
91
+ expect(JSON.parse(new TextDecoder().decode(deployed.files.get(manifest))).css).toBe(profile.css);
92
+ await writeFile(path, JSON.stringify({ ...profile, css: "p { color: blue; }" }));
93
+ expect((await readArticleTheme(path)).hash).not.toBe(theme.hash);
94
+ });
95
+
96
+ test("独立配置拒绝凭据、外部素材与不安全 CSS", async () => {
97
+ const root = await mkdtemp(join(tmpdir(), "zzp-studio-invalid-"));
98
+ roots.push(root);
99
+ const path = join(root, "style.json");
100
+ const profile = { schemaVersion: 1, engineVersion: 1, id: "style", name: "Style", version: "1.0.0", css: "" };
101
+ for (const patch of [
102
+ { account: "default" }, { pat: "secret" }, { assets: ["asset.png"] },
103
+ { css: "p { background: url(file:///secret); }" },
104
+ { structure: { headerImageUrl: "file:///secret" } },
105
+ ]) {
106
+ await writeFile(path, JSON.stringify({ ...profile, ...patch }));
107
+ await expect(readArticleTheme(path)).rejects.toThrow();
108
+ }
109
+ });
110
+
56
111
  test("结果未知阻止普通重发,明确重置才建立新发布尝试", async () => {
57
112
  const { root } = await fixture();
58
113
  const { defaultState, readState, writeState } = await import("./state");
@@ -2,6 +2,7 @@ import { createHash } from "node:crypto";
2
2
  import { lstat, mkdir, mkdtemp, readFile, realpath, rename, rm, writeFile } from "node:fs/promises";
3
3
  import { basename, dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
4
4
  import { z } from "zod";
5
+ import { WechatStructureOverridesSchema } from "./schema/config";
5
6
 
6
7
  /** 模板只包含声明、CSS 与素材,不执行客户包中的脚本。 */
7
8
  export const ArticleThemeSchema = z.object({
@@ -18,11 +19,16 @@ export const ArticleThemeSchema = z.object({
18
19
  assets: z.array(z.string()).max(100).default([]),
19
20
  editorVars: z.record(z.string(), z.string()).default({}),
20
21
  exportTheme: z.record(z.string(), z.string()).default({}),
22
+ /** Studio 独立配置内嵌 CSS,无需附带模板目录。 */
23
+ css: z.string().max(256_000).optional(),
24
+ syntaxPresets: z.record(z.string(), z.string()).optional(),
21
25
  structure: z.object({
22
26
  numberedHeadings: z.boolean().default(false),
23
27
  headingLabel: z.string().max(30).default(""),
24
28
  quoteLabel: z.string().max(30).default(""),
25
29
  headerImage: z.string().nullable().default(null),
30
+ headerImageUrl: z.string().regex(/^data:image\/(?:png|jpeg|gif|webp);base64,[A-Za-z0-9+/]+={0,2}$/).nullable().optional(),
31
+ calloutPresets: WechatStructureOverridesSchema.shape.calloutPresets,
26
32
  }).default({ numberedHeadings: false, headingLabel: "", quoteLabel: "", headerImage: null }),
27
33
  }).strict();
28
34
 
@@ -64,10 +70,12 @@ export async function readArticleTheme(inputPath: string): Promise<ArticleThemeP
64
70
  }
65
71
  const manifestName = basename(manifestPath);
66
72
  const manifest = ArticleThemeSchema.parse(JSON.parse(new TextDecoder().decode(await read(manifestName))));
67
- const paths = [manifest.stylesheet, manifest.sample, manifest.preview, manifest.license, ...manifest.assets];
73
+ const standalone = manifest.css !== undefined;
74
+ if (standalone && (manifest.assets.length || manifest.structure.headerImage)) throw new Error("独立排版配置必须内嵌素材,不能引用模板目录文件");
75
+ const paths = standalone ? [] : [manifest.stylesheet, manifest.sample, manifest.preview, manifest.license, ...manifest.assets];
68
76
  if (manifest.structure.headerImage) paths.push(manifest.structure.headerImage);
69
77
  for (const name of new Set(paths)) await read(name);
70
- const css = new TextDecoder().decode(files.get(manifest.stylesheet));
78
+ const css = manifest.css ?? new TextDecoder().decode(files.get(manifest.stylesheet));
71
79
  // 模板无需 CSS 转义;拒绝用转义或注释隐藏的网络/文件资源。
72
80
  const unsafeCss = (value: string) => /\\|@import\b|url\s*\(|expression\s*\(/i.test(value.replace(/\/\*[\s\S]*?\*\//g, ""));
73
81
  if (Object.keys(manifest.editorVars).some(key => !/^--[a-zA-Z0-9_-]+$/.test(key))) throw new Error("模板变量名无效");
@@ -6,7 +6,7 @@ import { printResult } from "../output";
6
6
  export async function articleTheme(args: string[]): Promise<void> {
7
7
  const parsed = parseArgs(args);
8
8
  if (parsed.help) {
9
- console.log("Usage: zzp article-theme --path <模板目录或 manifest.json> [--install <本地模板库>]\n只校验或复制模板,不联网、不发布。");
9
+ console.log("Usage: zzp article-theme --path <Studio 独立 JSON、模板目录或 manifest.json> [--install <本地模板库>]\n只校验或复制模板,不联网、不发布。");
10
10
  return;
11
11
  }
12
12
  let theme = await readArticleTheme(requireArg(parsed, "path", "template path"));
@@ -64,6 +64,7 @@ Options:
64
64
  --newspic-render-spec-file JSON file for newspic pagination / page-image intent (optional)
65
65
  --style-hint e.g. fact_report (optional)
66
66
  --cover-theme Cover theme ID (optional)
67
+ --article-theme Standalone Studio JSON or local article theme package (optional)
67
68
  --requires-research Flag
68
69
  --requires-style Flag
69
70
  --requires-render Flag
@@ -140,6 +141,7 @@ Options:
140
141
  explicit_constraints: [],
141
142
  style_hint: styleHint,
142
143
  cover_theme: coverTheme,
144
+ article_theme: optionalArg(parsed, "article-theme") ? resolve(optionalArg(parsed, "article-theme")!) : null,
143
145
  newspic_render: newspicRender,
144
146
  ...(newspicFile ? { newspic_file: resolve(newspicFile) } : {}),
145
147
  requires: {
@@ -47,7 +47,7 @@ Usage: zzhub-pipeline publish [options]
47
47
  Options:
48
48
  --state Path to state JSON (required)
49
49
  --route Only publish this route (optional; default: all targets)
50
- --article-theme Local article theme package (optional)
50
+ --article-theme Standalone Studio JSON or local article theme package (optional)
51
51
  --dry-run Print commands without executing (optional)
52
52
  `.trim());
53
53
  return;
@@ -5,6 +5,7 @@ import { join } from "node:path";
5
5
  import { PNG } from "pngjs";
6
6
  import { createTypesetAssetsSyncCommand } from "./typeset-assets-sync";
7
7
  import type { uploadFileToCos } from "../providers/cos";
8
+ import { readArticleTheme } from "../article-theme";
8
9
 
9
10
  let root: string;
10
11
  let previousConfig: string | undefined;
@@ -60,6 +61,12 @@ test("dry-run reads only referenced images and never uploads, verifies URLs, or
60
61
 
61
62
  test("deduplicates shared images, rewrites only sources, and exports styles without credentials", async () => {
62
63
  await writeFile(join(root, "templates/shared.json"), JSON.stringify({ ...template, id: "shared" }));
64
+ const style = { schemaVersion: 1, engineVersion: 1, id: "style", name: "Style", version: "1.0.0", css: "p { color: #123456; }", exportTheme: { bodyFontSize: "18px" } };
65
+ await writeFile(join(root, "style.json"), JSON.stringify(style));
66
+ const configPath = join(root, "config.json");
67
+ const config = await result(configPath);
68
+ config.wx.accounts.default.articleTheme = "style.json";
69
+ await writeFile(configPath, JSON.stringify(config));
63
70
  let uploads = 0;
64
71
  const command = createTypesetAssetsSyncCommand({ upload: uploader(async () => { uploads++; }), verifyUrl });
65
72
  const destination = join(root, "runtime");
@@ -67,7 +74,8 @@ test("deduplicates shared images, rewrites only sources, and exports styles with
67
74
  expect(uploads).toBe(1);
68
75
  expect((await result(join(root, "templates/jinx.json"))).images[0]).toEqual({ ...template.images[0], src: "https://cdn.example/jinx.png" });
69
76
  const patch = await result(join(destination, "pipeline.patch.json"));
70
- expect(patch.wx.accounts.default).toMatchObject({ customCss: "/data/pipeline-runtime/markdown/custom-css-default.css", articleTheme: null });
77
+ expect(patch.wx.accounts.default).toMatchObject({ customCss: null, articleTheme: "/data/pipeline-runtime/markdown/article-themes/default/manifest.json" });
78
+ expect((await readArticleTheme(join(destination, "markdown/article-themes/default/manifest.json"))).css).toBe(style.css);
71
79
  for (const secret of ["secret-cos-token", "private-secret", "private-app-id", "private-pat"]) expect(JSON.stringify(patch)).not.toContain(secret);
72
80
  expect((await result(join(destination, "manifest.json"))).typesetTemplates).toBe(2);
73
81
  expect((await readFile(join(root, "uploads/jinx.png"))).equals(image)).toBe(true);
@@ -8,6 +8,7 @@ import { loadConfig, resolveConfigRelativePath } from "../config";
8
8
  import { resolveMarkdownRenderer } from "../adapter-loader";
9
9
  import { WechatExportError } from "../wechat-preview";
10
10
  import { registerPreviewEntry } from "../wechat-preview/server";
11
+ import { readArticleTheme } from "../article-theme";
11
12
 
12
13
  const CSS_DEMO = `
13
14
  Custom CSS is cascaded after the built-in theme and converted to conservative
@@ -69,7 +70,7 @@ Options:
69
70
  --account Account/theme key (optional; default: default)
70
71
  --title Page title for the render shell (optional)
71
72
  --preview-shell-out Path to exact final-HTML preview (optional)
72
- --article-theme Local article theme package (optional)
73
+ --article-theme Standalone Studio JSON or local article theme package (optional)
73
74
  --summary-only Omit HTML from stdout; still write the complete output file
74
75
  --custom-css CSS override path; replaces account customCss (optional)
75
76
  --timeout-ms Real browser wait limit in ms (default: 15000)
@@ -108,9 +109,13 @@ ${CSS_DEMO}
108
109
 
109
110
  const config = loadConfig();
110
111
  const wxAccount = config.wx.accounts[account] ?? config.wx.accounts[config.wx.defaultAccount];
112
+ const articleThemeArg = optionalArg(parsed, "article-theme");
113
+ const articleThemePath = articleThemeArg ? resolve(articleThemeArg) : resolveConfigRelativePath(wxAccount?.articleTheme);
114
+ // 独立配置替代账号样式;显式 CSS 参数仍可覆盖本次导出。
115
+ const standalone = articleThemePath ? (await readArticleTheme(articleThemePath)).manifest.css !== undefined : false;
111
116
  const customCss = resolveWechatExportCustomCss(
112
117
  cliCustomCss,
113
- wxAccount?.customCss,
118
+ standalone ? null : wxAccount?.customCss,
114
119
  );
115
120
  const markdownRenderer = await resolveMarkdownRenderer(config);
116
121
 
@@ -125,8 +130,8 @@ ${CSS_DEMO}
125
130
  title,
126
131
  previewShellOutPath,
127
132
  customCss,
128
- articleThemePath: optionalArg(parsed, "article-theme") ? resolve(optionalArg(parsed, "article-theme")!) : resolveConfigRelativePath(wxAccount?.articleTheme),
129
- themeOverrides: wxAccount?.theme,
133
+ articleThemePath,
134
+ themeOverrides: standalone ? undefined : wxAccount?.theme,
130
135
  timeoutMs: timeoutMs !== undefined && Number.isFinite(timeoutMs) ? timeoutMs : undefined,
131
136
  debugDir: debugDir ? resolve(process.cwd(), debugDir) : undefined,
132
137
  });
@@ -84,15 +84,17 @@ async function publishWechatArticleRoute({
84
84
  try {
85
85
  const markdownRenderer = await resolveMarkdownRenderer(config);
86
86
  const wxAccount = config.wx.accounts[account] ?? config.wx.accounts[config.wx.defaultAccount];
87
+ // 独立正文配置与发布账号的凭据、默认 CSS 分离。
88
+ const standalone = articleTheme?.manifest.css !== undefined;
87
89
  const rendered = await markdownRenderer.render({
88
90
  onProgress: reportProgress,
89
91
  markdownPath: exportPostPath,
90
92
  outPath: workspacePaths.zotepadExportHtml,
91
93
  account,
92
94
  title: state.metadata.title,
93
- customCss: resolveConfigRelativePath(wxAccount?.customCss),
95
+ customCss: standalone ? null : resolveConfigRelativePath(wxAccount?.customCss),
94
96
  articleThemePath: articleTheme?.path,
95
- themeOverrides: wxAccount?.theme,
97
+ themeOverrides: standalone ? undefined : wxAccount?.theme,
96
98
  });
97
99
  const { html } = rendered;
98
100
 
@@ -69,13 +69,14 @@ export async function prepareMarkdownRuntime(config: PipelineConfig, accountMap:
69
69
  if (!/^[a-zA-Z0-9_.-]{1,80}$/.test(account) || [".", "..", "__proto__", "constructor", "prototype"].includes(account)) throw new Error(`无效的样式账号标识:${account}`);
70
70
  if (Object.hasOwn(accounts, account)) throw new Error(`账号映射重复:${account}`);
71
71
  const next: Record<string, unknown> = { theme: value.theme, customCss: null, articleTheme: null };
72
- if (value.customCss) {
72
+ const theme = value.articleTheme ? await readArticleTheme(resolveConfigRelativePath(value.articleTheme)!) : null;
73
+ // 独立配置已内嵌 CSS,部署时不依赖被替代的账号样式文件。
74
+ if (value.customCss && theme?.manifest.css === undefined) {
73
75
  const name = `markdown/custom-css-${account}.css`;
74
76
  files.set(name, await readRuntimeSource(resolveConfigRelativePath(value.customCss)!));
75
77
  next.customCss = `${RUNTIME_ROOT}/${name}`;
76
78
  }
77
- if (value.articleTheme) {
78
- const theme = await readArticleTheme(resolveConfigRelativePath(value.articleTheme)!);
79
+ if (theme) {
79
80
  const prefix = `markdown/article-themes/${account}`;
80
81
  for (const [name, bytes] of theme.files) files.set(`${prefix}/${name}`, bytes);
81
82
  files.set(`${prefix}/manifest.json`, Buffer.from(JSON.stringify(theme.manifest, null, 2)));