@qnroa/qtype 0.0.1 → 0.0.3

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 (468) hide show
  1. package/CHANGELOG.md +1 -3
  2. package/CHANGELOG.zh.md +1 -2
  3. package/README.md +88 -56
  4. package/README.zh.md +82 -62
  5. package/dist/cli/bootstrap.js +4 -115
  6. package/dist/cli/commands/check/index.js +11 -10
  7. package/dist/cli/commands/config/action.js +5 -9
  8. package/dist/cli/commands/content/lint/action.js +38 -44
  9. package/dist/cli/commands/content/search/action.js +44 -34
  10. package/dist/cli/commands/content/search/i18n.js +6 -0
  11. package/dist/cli/commands/content/search/index.js +19 -1
  12. package/dist/cli/commands/content/validate/action.js +28 -27
  13. package/dist/cli/commands/index.js +1 -3
  14. package/dist/cli/commands/pack/index.js +2 -1
  15. package/dist/cli/commands/publish/build/action.js +39 -11
  16. package/dist/cli/commands/repo/new/action.js +23 -4
  17. package/dist/cli/commands/repo/new/i18n.js +2 -2
  18. package/dist/cli/commands/repo/sync/action.js +24 -4
  19. package/dist/cli/commands/repo/templates.js +2 -1
  20. package/dist/cli/utils/material.js +49 -0
  21. package/dist/core/encrypt.js +24 -1
  22. package/dist/core/index.js +1 -0
  23. package/dist/core/parser/frontmatter.js +39 -34
  24. package/dist/core/parser/parseMaterial.js +174 -24
  25. package/dist/core/romanization/index.js +152 -0
  26. package/dist/core/schemas/both.js +52 -0
  27. package/dist/core/schemas/index.js +3 -0
  28. package/dist/core/schemas/repo.js +55 -0
  29. package/dist/core/schemas/user.js +19 -0
  30. package/dist/core/typing/engine/TypingInput.js +243 -0
  31. package/dist/core/typing/engine/chars.js +30 -0
  32. package/dist/core/typing/engine/feedback.js +15 -0
  33. package/dist/core/typing/engine/index.js +5 -0
  34. package/dist/core/typing/engine/settings.js +8 -0
  35. package/dist/core/typing/engine/stats.js +45 -0
  36. package/dist/core/typing/index.js +9 -1
  37. package/dist/view/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
  38. package/dist/view/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
  39. package/dist/view/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
  40. package/dist/view/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
  41. package/dist/view/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
  42. package/dist/view/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
  43. package/dist/view/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
  44. package/dist/view/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
  45. package/dist/view/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
  46. package/dist/view/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
  47. package/dist/view/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
  48. package/dist/view/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
  49. package/dist/view/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
  50. package/dist/view/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
  51. package/dist/view/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
  52. package/dist/view/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
  53. package/dist/view/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
  54. package/dist/view/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
  55. package/dist/view/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
  56. package/dist/view/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
  57. package/dist/view/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
  58. package/dist/view/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
  59. package/dist/view/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
  60. package/dist/view/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
  61. package/dist/view/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
  62. package/dist/view/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
  63. package/dist/view/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
  64. package/dist/view/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
  65. package/dist/view/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
  66. package/dist/view/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
  67. package/dist/view/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
  68. package/dist/view/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
  69. package/dist/view/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
  70. package/dist/view/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
  71. package/dist/view/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
  72. package/dist/view/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
  73. package/dist/view/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
  74. package/dist/view/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
  75. package/dist/view/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
  76. package/dist/view/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
  77. package/dist/view/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
  78. package/dist/view/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
  79. package/dist/view/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
  80. package/dist/view/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
  81. package/dist/view/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
  82. package/dist/view/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
  83. package/dist/view/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
  84. package/dist/view/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
  85. package/dist/view/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
  86. package/dist/view/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
  87. package/dist/view/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
  88. package/dist/view/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
  89. package/dist/view/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
  90. package/dist/view/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
  91. package/dist/view/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
  92. package/dist/view/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
  93. package/dist/view/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
  94. package/dist/view/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
  95. package/dist/view/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
  96. package/dist/view/assets/abap-BdImnpbu.js +1 -0
  97. package/dist/view/assets/actionscript-3-B3316cI-.js +1 -0
  98. package/dist/view/assets/ada-bCR0ucgS.js +1 -0
  99. package/dist/view/assets/ahk-CsyLZFj1.js +1 -0
  100. package/dist/view/assets/ahk2-8Zs4aa1G.js +1 -0
  101. package/dist/view/assets/andromeeda-C4gqWexZ.js +1 -0
  102. package/dist/view/assets/angular-html-DA-rfuFy.js +1 -0
  103. package/dist/view/assets/angular-ts-BrjP3tb8.js +1 -0
  104. package/dist/view/assets/apache-Pmp26Uib.js +1 -0
  105. package/dist/view/assets/apex-DhZFqWV2.js +1 -0
  106. package/dist/view/assets/apl-CORt7UWP.js +1 -0
  107. package/dist/view/assets/applescript-Co6uUVPk.js +1 -0
  108. package/dist/view/assets/ara-BRHolxvo.js +1 -0
  109. package/dist/view/assets/asciidoc-CSVQ5wI8.js +1 -0
  110. package/dist/view/assets/asm-D_Q5rh1f.js +1 -0
  111. package/dist/view/assets/astro-HNnZUWAn.js +1 -0
  112. package/dist/view/assets/aurora-x-D-2ljcwZ.js +1 -0
  113. package/dist/view/assets/awk-DMzUqQB5.js +1 -0
  114. package/dist/view/assets/ayu-dark-DYE7WIF3.js +1 -0
  115. package/dist/view/assets/ayu-light-BA47KaF1.js +1 -0
  116. package/dist/view/assets/ayu-mirage-32ctXXKs.js +1 -0
  117. package/dist/view/assets/ballerina-BFfxhgS-.js +1 -0
  118. package/dist/view/assets/bat-CickPsom.js +1 -0
  119. package/dist/view/assets/beancount-k_qm7-4y.js +1 -0
  120. package/dist/view/assets/berry-uYugtg8r.js +1 -0
  121. package/dist/view/assets/bibtex-CHM0blh-.js +1 -0
  122. package/dist/view/assets/bicep-Bmn6On1c.js +1 -0
  123. package/dist/view/assets/bird2-Bx8U0n9b.js +1 -0
  124. package/dist/view/assets/blade-2xfisSek.js +1 -0
  125. package/dist/view/assets/bsl-DlhNcFeZ.js +1 -0
  126. package/dist/view/assets/c-BIGW1oBm.js +1 -0
  127. package/dist/view/assets/c3-Dp5svz6Z.js +1 -0
  128. package/dist/view/assets/cadence-Bv_4Rxtq.js +1 -0
  129. package/dist/view/assets/cairo-KRGpt6FW.js +1 -0
  130. package/dist/view/assets/catppuccin-frappe-CZL1YF0i.js +1 -0
  131. package/dist/view/assets/catppuccin-latte-DH-8KZSZ.js +1 -0
  132. package/dist/view/assets/catppuccin-macchiato-B7yYVSCf.js +1 -0
  133. package/dist/view/assets/catppuccin-mocha-Ct7hS0mc.js +1 -0
  134. package/dist/view/assets/chapel-DTp_pixX.js +1 -0
  135. package/dist/view/assets/clarity-Dn5IMItf.js +1 -0
  136. package/dist/view/assets/clojure-P80f7IUj.js +1 -0
  137. package/dist/view/assets/cmake-D1j8_8rp.js +1 -0
  138. package/dist/view/assets/cobol-nBiQ_Alo.js +1 -0
  139. package/dist/view/assets/codeowners-Bp6g37R7.js +1 -0
  140. package/dist/view/assets/codeql-DsOJ9woJ.js +1 -0
  141. package/dist/view/assets/coffee-Ch7k5sss.js +1 -0
  142. package/dist/view/assets/common-lisp-Cg-RD9OK.js +1 -0
  143. package/dist/view/assets/coq-C7JzOVbR.js +1 -0
  144. package/dist/view/assets/cpp-BMRokrvK.js +1 -0
  145. package/dist/view/assets/crystal-DGywbUpC.js +1 -0
  146. package/dist/view/assets/csharp-DSvCPggb.js +1 -0
  147. package/dist/view/assets/css-CLj8gQPS.js +1 -0
  148. package/dist/view/assets/csv-fuZLfV_i.js +1 -0
  149. package/dist/view/assets/cue-D82EKSYY.js +1 -0
  150. package/dist/view/assets/cypher-COkxafJQ.js +1 -0
  151. package/dist/view/assets/d-85-TOEBH.js +1 -0
  152. package/dist/view/assets/dark-plus-C3mMm8J8.js +1 -0
  153. package/dist/view/assets/dart-bE4Kk8sk.js +1 -0
  154. package/dist/view/assets/dax-CEL-wOlO.js +1 -0
  155. package/dist/view/assets/desktop-BmXAJ9_W.js +1 -0
  156. package/dist/view/assets/diff-D97Zzqfu.js +1 -0
  157. package/dist/view/assets/docker-BcOcwvcX.js +1 -0
  158. package/dist/view/assets/dotenv-Da5cRb03.js +1 -0
  159. package/dist/view/assets/dracula-BzJJZx-M.js +1 -0
  160. package/dist/view/assets/dracula-soft-BXkSAIEj.js +1 -0
  161. package/dist/view/assets/dream-maker-BtqSS_iP.js +1 -0
  162. package/dist/view/assets/edge-FbVlp4U3.js +1 -0
  163. package/dist/view/assets/elixir-CkH2-t6x.js +1 -0
  164. package/dist/view/assets/elm-DbKCFpqz.js +1 -0
  165. package/dist/view/assets/emacs-lisp-C_m_b--Z.js +1 -0
  166. package/dist/view/assets/erb-DXfck5VN.js +1 -0
  167. package/dist/view/assets/erlang-DsQrWhSR.js +1 -0
  168. package/dist/view/assets/everforest-dark-BgDCqdQA.js +1 -0
  169. package/dist/view/assets/everforest-light-C8M2exoo.js +1 -0
  170. package/dist/view/assets/fennel-BYunw83y.js +1 -0
  171. package/dist/view/assets/fish-BvzEVeQv.js +1 -0
  172. package/dist/view/assets/fluent-C4IJs8-o.js +1 -0
  173. package/dist/view/assets/fortran-fixed-form-CkoXwp7k.js +1 -0
  174. package/dist/view/assets/fortran-free-form-BxgE0vQu.js +1 -0
  175. package/dist/view/assets/fsharp-CXgrBDvD.js +1 -0
  176. package/dist/view/assets/gdresource-TyuKm33G.js +1 -0
  177. package/dist/view/assets/gdscript-DqcFQ5yU.js +1 -0
  178. package/dist/view/assets/gdshader-DkwncUOv.js +1 -0
  179. package/dist/view/assets/genie-D0YGMca9.js +1 -0
  180. package/dist/view/assets/gherkin-DyxjwDmM.js +1 -0
  181. package/dist/view/assets/git-commit-F4YmCXRG.js +1 -0
  182. package/dist/view/assets/git-rebase-r7XF79zn.js +1 -0
  183. package/dist/view/assets/github-dark-DHJKELXO.js +1 -0
  184. package/dist/view/assets/github-dark-default-Cuk6v7N8.js +1 -0
  185. package/dist/view/assets/github-dark-dimmed-DH5Ifo-i.js +1 -0
  186. package/dist/view/assets/github-dark-high-contrast-E3gJ1_iC.js +1 -0
  187. package/dist/view/assets/github-light-DAi9KRSo.js +1 -0
  188. package/dist/view/assets/github-light-default-D7oLnXFd.js +1 -0
  189. package/dist/view/assets/github-light-high-contrast-BfjtVDDH.js +1 -0
  190. package/dist/view/assets/gleam-BspZqrRM.js +1 -0
  191. package/dist/view/assets/glimmer-js-ByusRIyA.js +1 -0
  192. package/dist/view/assets/glimmer-ts-BfAWNZQY.js +1 -0
  193. package/dist/view/assets/glsl-DplSGwfg.js +1 -0
  194. package/dist/view/assets/gn-n2N0HUVH.js +1 -0
  195. package/dist/view/assets/gnuplot-DdkO51Og.js +1 -0
  196. package/dist/view/assets/go-C27-OAKa.js +1 -0
  197. package/dist/view/assets/graphql-ChdNCCLP.js +1 -0
  198. package/dist/view/assets/groovy-gcz8RCvz.js +1 -0
  199. package/dist/view/assets/gruvbox-dark-hard-CFHQjOhq.js +1 -0
  200. package/dist/view/assets/gruvbox-dark-medium-GsRaNv29.js +1 -0
  201. package/dist/view/assets/gruvbox-dark-soft-CVdnzihN.js +1 -0
  202. package/dist/view/assets/gruvbox-light-hard-CH1njM8p.js +1 -0
  203. package/dist/view/assets/gruvbox-light-medium-DRw_LuNl.js +1 -0
  204. package/dist/view/assets/gruvbox-light-soft-hJgmCMqR.js +1 -0
  205. package/dist/view/assets/hack-BWmVpMyf.js +1 -0
  206. package/dist/view/assets/haml-D5jkg6IW.js +1 -0
  207. package/dist/view/assets/handlebars-BpdQsYii.js +1 -0
  208. package/dist/view/assets/haskell-Df6bDoY_.js +1 -0
  209. package/dist/view/assets/haxe-CfZj7gIn.js +1 -0
  210. package/dist/view/assets/hcl-BWvSN4gD.js +1 -0
  211. package/dist/view/assets/hjson-D5-asLiD.js +1 -0
  212. package/dist/view/assets/hlsl-D3lLCCz7.js +1 -0
  213. package/dist/view/assets/horizon-BUw7H-hv.js +1 -0
  214. package/dist/view/assets/horizon-bright-CUuTKBJd.js +1 -0
  215. package/dist/view/assets/houston-DnULxvSX.js +1 -0
  216. package/dist/view/assets/html-derivative-DlHx6ybY.js +1 -0
  217. package/dist/view/assets/html-pp8916En.js +1 -0
  218. package/dist/view/assets/http-jrhK8wxY.js +1 -0
  219. package/dist/view/assets/hurl-irOxFIW8.js +1 -0
  220. package/dist/view/assets/hxml-2-FPmUDs.js +1 -0
  221. package/dist/view/assets/hy-DFXneXwc.js +1 -0
  222. package/dist/view/assets/imba-DGztddWO.js +1 -0
  223. package/dist/view/assets/index-BLryk3W4.css +1 -0
  224. package/dist/view/assets/index-ByMJp0a5.js +3 -0
  225. package/dist/view/assets/index-CRh4USfC.js +189 -0
  226. package/dist/view/assets/index-JNx7Ohoj.js +153 -0
  227. package/dist/view/assets/ini-BEwlwnbL.js +1 -0
  228. package/dist/view/assets/java-CylS5w8V.js +1 -0
  229. package/dist/view/assets/javascript-wDzz0qaB.js +1 -0
  230. package/dist/view/assets/jinja-f2NsQr07.js +1 -0
  231. package/dist/view/assets/jison-wvAkD_A8.js +1 -0
  232. package/dist/view/assets/json-Cp-IABpG.js +1 -0
  233. package/dist/view/assets/json5-C9tS-k6U.js +1 -0
  234. package/dist/view/assets/jsonc-Des-eS-w.js +1 -0
  235. package/dist/view/assets/jsonl-DcaNXYhu.js +1 -0
  236. package/dist/view/assets/jsonnet-DFQXde-d.js +1 -0
  237. package/dist/view/assets/jssm-C2t-YnRu.js +1 -0
  238. package/dist/view/assets/jsx-g9-lgVsj.js +1 -0
  239. package/dist/view/assets/julia-5Bft2YPA.js +1 -0
  240. package/dist/view/assets/just-Cwhn7H3k.js +1 -0
  241. package/dist/view/assets/kanagawa-dragon-BuwD2xS4.js +1 -0
  242. package/dist/view/assets/kanagawa-lotus-C3DzagqV.js +1 -0
  243. package/dist/view/assets/kanagawa-wave-DFGoQZhC.js +1 -0
  244. package/dist/view/assets/katex-BYZTj3zW.css +1 -0
  245. package/dist/view/assets/katex-C5jXJg4s.js +257 -0
  246. package/dist/view/assets/kdl-DV7GczEv.js +1 -0
  247. package/dist/view/assets/kotlin-BdnUsdx6.js +1 -0
  248. package/dist/view/assets/kusto-wEQ09or8.js +1 -0
  249. package/dist/view/assets/laserwave-DUszq2jm.js +1 -0
  250. package/dist/view/assets/latex-D5pSuvFb.js +1 -0
  251. package/dist/view/assets/lean-BZvkOJ9d.js +1 -0
  252. package/dist/view/assets/less-B1dDrJ26.js +1 -0
  253. package/dist/view/assets/light-plus-B7mTdjB0.js +1 -0
  254. package/dist/view/assets/liquid-C0sCDyMI.js +1 -0
  255. package/dist/view/assets/llvm-BZoOZj88.js +1 -0
  256. package/dist/view/assets/log-2UxHyX5q.js +1 -0
  257. package/dist/view/assets/logo-BtOb2qkB.js +1 -0
  258. package/dist/view/assets/lua-BaeVxFsk.js +1 -0
  259. package/dist/view/assets/luau-BnpPk5vE.js +1 -0
  260. package/dist/view/assets/make-CHLpvVh8.js +1 -0
  261. package/dist/view/assets/markdown-Cvjx9yec.js +1 -0
  262. package/dist/view/assets/marko-DjSrsDqO.js +1 -0
  263. package/dist/view/assets/material-theme-D5KoaKCx.js +1 -0
  264. package/dist/view/assets/material-theme-darker-BfHTSMKl.js +1 -0
  265. package/dist/view/assets/material-theme-lighter-B0m2ddpp.js +1 -0
  266. package/dist/view/assets/material-theme-ocean-CyktbL80.js +1 -0
  267. package/dist/view/assets/material-theme-palenight-Csfq5Kiy.js +1 -0
  268. package/dist/view/assets/matlab-D7o27uSR.js +1 -0
  269. package/dist/view/assets/mdc-D1_yUvq7.js +1 -0
  270. package/dist/view/assets/mdx-Cmh6b_Ma.js +1 -0
  271. package/dist/view/assets/mermaid-CQcHuHx7.js +1 -0
  272. package/dist/view/assets/min-dark-CafNBF8u.js +1 -0
  273. package/dist/view/assets/min-light-CTRr51gU.js +1 -0
  274. package/dist/view/assets/mipsasm-CKIfxQSi.js +1 -0
  275. package/dist/view/assets/mojo-DJz3ZmWd.js +1 -0
  276. package/dist/view/assets/monokai-BRVnQi9A.js +1 -0
  277. package/dist/view/assets/moonbit-CHtswR0a.js +1 -0
  278. package/dist/view/assets/move-el3G9tDJ.js +1 -0
  279. package/dist/view/assets/narrat-DRg8JJMk.js +1 -0
  280. package/dist/view/assets/nextflow-C-mBbutL.js +1 -0
  281. package/dist/view/assets/nextflow-groovy-vE_lwT2v.js +1 -0
  282. package/dist/view/assets/nginx-BpAMiNFr.js +1 -0
  283. package/dist/view/assets/night-owl-C39BiMTA.js +1 -0
  284. package/dist/view/assets/night-owl-light-CMTm3GFP.js +1 -0
  285. package/dist/view/assets/nim-BIad80T-.js +1 -0
  286. package/dist/view/assets/nix-CwoSXNpI.js +1 -0
  287. package/dist/view/assets/nord-Ddv68eIx.js +1 -0
  288. package/dist/view/assets/nsis-BlV79W_Q.js +1 -0
  289. package/dist/view/assets/nushell-D3jzshHO.js +1 -0
  290. package/dist/view/assets/objective-c-DXmwc3jG.js +1 -0
  291. package/dist/view/assets/objective-cpp-CLxacb5B.js +1 -0
  292. package/dist/view/assets/ocaml-C0hk2d4L.js +1 -0
  293. package/dist/view/assets/odin-BBf5iR-q.js +1 -0
  294. package/dist/view/assets/one-dark-pro-DVMEJ2y_.js +1 -0
  295. package/dist/view/assets/one-light-C3Wv6jpd.js +1 -0
  296. package/dist/view/assets/openscad-C4EeE6gA.js +1 -0
  297. package/dist/view/assets/org-DM6o9KBp.js +1 -0
  298. package/dist/view/assets/pascal-D93ZcfNL.js +1 -0
  299. package/dist/view/assets/perl-B9cMNwum.js +1 -0
  300. package/dist/view/assets/php-Csjmro_R.js +1 -0
  301. package/dist/view/assets/pkl-u5AG7uiY.js +1 -0
  302. package/dist/view/assets/plastic-3e1v2bzS.js +1 -0
  303. package/dist/view/assets/plsql-ChMvpjG-.js +1 -0
  304. package/dist/view/assets/po-BTJTHyun.js +1 -0
  305. package/dist/view/assets/poimandres-CS3Unz2-.js +1 -0
  306. package/dist/view/assets/polar-C0HS_06l.js +1 -0
  307. package/dist/view/assets/postcss-CXtECtnM.js +1 -0
  308. package/dist/view/assets/powerquery-CEu0bR-o.js +1 -0
  309. package/dist/view/assets/powershell-BmBUJMz7.js +1 -0
  310. package/dist/view/assets/prisma-Vru482bI.js +1 -0
  311. package/dist/view/assets/prolog-CbFg5uaA.js +1 -0
  312. package/dist/view/assets/proto-C7zT0LnQ.js +1 -0
  313. package/dist/view/assets/pug-DKIMFp6K.js +1 -0
  314. package/dist/view/assets/puppet-BMWR74SV.js +1 -0
  315. package/dist/view/assets/purescript-CklMAg4u.js +1 -0
  316. package/dist/view/assets/python-B6aJPvgy.js +1 -0
  317. package/dist/view/assets/qml-3beO22l8.js +1 -0
  318. package/dist/view/assets/qmldir-C8lEn-DE.js +1 -0
  319. package/dist/view/assets/qss-IeuSbFQv.js +1 -0
  320. package/dist/view/assets/r-Cf5RLm7j.js +1 -0
  321. package/dist/view/assets/racket-BqYA7rlc.js +1 -0
  322. package/dist/view/assets/raku-DXvB9xmW.js +1 -0
  323. package/dist/view/assets/razor-BjBPvh-w.js +1 -0
  324. package/dist/view/assets/rbs-CpoqiR4B.js +1 -0
  325. package/dist/view/assets/red-hvxz__6c.js +1 -0
  326. package/dist/view/assets/reg-C-SQnVFl.js +1 -0
  327. package/dist/view/assets/regexp-CDVJQ6XC.js +1 -0
  328. package/dist/view/assets/rel-C3B-1QV4.js +1 -0
  329. package/dist/view/assets/riscv-BM1_JUlF.js +1 -0
  330. package/dist/view/assets/ron-D8l8udqQ.js +1 -0
  331. package/dist/view/assets/rose-pine-5qJOZa0Y.js +1 -0
  332. package/dist/view/assets/rose-pine-dawn-zx0QlTCp.js +1 -0
  333. package/dist/view/assets/rose-pine-moon-C9pEdX9L.js +1 -0
  334. package/dist/view/assets/rosmsg-BJDFO7_C.js +1 -0
  335. package/dist/view/assets/rst-bs7f0vWN.js +1 -0
  336. package/dist/view/assets/ruby-C0TQ7zu5.js +1 -0
  337. package/dist/view/assets/rust-B1yitclQ.js +1 -0
  338. package/dist/view/assets/sas-DEy46yEz.js +1 -0
  339. package/dist/view/assets/sass-Cj5Yp3dK.js +1 -0
  340. package/dist/view/assets/scala-CqE71os6.js +1 -0
  341. package/dist/view/assets/scheme-C98Dy4si.js +1 -0
  342. package/dist/view/assets/scss-D5BDwBP9.js +1 -0
  343. package/dist/view/assets/sdbl-DVxCFoDh.js +1 -0
  344. package/dist/view/assets/shaderlab-Dg9Lc6iA.js +1 -0
  345. package/dist/view/assets/shellscript-Yzrsuije.js +1 -0
  346. package/dist/view/assets/shellsession-BADoaaVG.js +1 -0
  347. package/dist/view/assets/slack-dark-BthQWCQV.js +1 -0
  348. package/dist/view/assets/slack-ochin-DqwNpetd.js +1 -0
  349. package/dist/view/assets/smalltalk-BOQMe2GC.js +1 -0
  350. package/dist/view/assets/smithy-cds9vsN8.js +1 -0
  351. package/dist/view/assets/snazzy-light-Bw305WKR.js +1 -0
  352. package/dist/view/assets/solarized-dark-CpvCGNkr.js +1 -0
  353. package/dist/view/assets/solarized-light-Dlz6yCKv.js +1 -0
  354. package/dist/view/assets/solidity-DijEV5ha.js +1 -0
  355. package/dist/view/assets/soy-8wufbnw4.js +1 -0
  356. package/dist/view/assets/sparql-rVzFXLq3.js +1 -0
  357. package/dist/view/assets/splunk-BtCnVYZw.js +1 -0
  358. package/dist/view/assets/sql-CRqJ_cUM.js +1 -0
  359. package/dist/view/assets/ssh-config-_ykCGR6B.js +1 -0
  360. package/dist/view/assets/stata-DI20mbqo.js +1 -0
  361. package/dist/view/assets/stylus-BEDo0Tqx.js +1 -0
  362. package/dist/view/assets/surrealql-Cjom0U5J.js +1 -0
  363. package/dist/view/assets/svelte-Cy7k_4gC.js +1 -0
  364. package/dist/view/assets/swift-C2oV4EkX.js +1 -0
  365. package/dist/view/assets/synthwave-84-CbfX1IO0.js +1 -0
  366. package/dist/view/assets/system-verilog-0hqHdDBg.js +1 -0
  367. package/dist/view/assets/systemd-4A_iFExJ.js +1 -0
  368. package/dist/view/assets/talonscript-CkByrt1z.js +1 -0
  369. package/dist/view/assets/tasl-QIJgUcNo.js +1 -0
  370. package/dist/view/assets/tcl-dwOrl1Do.js +1 -0
  371. package/dist/view/assets/templ-DhtptRzy.js +1 -0
  372. package/dist/view/assets/terraform-BETggiCN.js +1 -0
  373. package/dist/view/assets/tex-D96PA37w.js +1 -0
  374. package/dist/view/assets/tokyo-night-hegEt444.js +1 -0
  375. package/dist/view/assets/toml-vGWfd6FD.js +1 -0
  376. package/dist/view/assets/ts-tags-D351s5mN.js +1 -0
  377. package/dist/view/assets/tsv-B_m7g4N7.js +1 -0
  378. package/dist/view/assets/tsx-COt5Ahok.js +1 -0
  379. package/dist/view/assets/turtle-BsS91CYL.js +1 -0
  380. package/dist/view/assets/twig-27uCiNez.js +1 -0
  381. package/dist/view/assets/typescript-BPQ3VLAy.js +1 -0
  382. package/dist/view/assets/typespec-CAFt9gP4.js +1 -0
  383. package/dist/view/assets/typst-BUadGCkm.js +1 -0
  384. package/dist/view/assets/v-BGw2Nkan.js +1 -0
  385. package/dist/view/assets/vala-CsfeWuGM.js +1 -0
  386. package/dist/view/assets/vb-Cu-pLBUe.js +1 -0
  387. package/dist/view/assets/verilog-nZwndyjY.js +1 -0
  388. package/dist/view/assets/vesper-DRje8inN.js +1 -0
  389. package/dist/view/assets/vhdl-CeAyd5Ju.js +1 -0
  390. package/dist/view/assets/viml-CJc9bBzg.js +1 -0
  391. package/dist/view/assets/vitesse-black-Bkuqu6BP.js +1 -0
  392. package/dist/view/assets/vitesse-dark-D0r3Knsf.js +1 -0
  393. package/dist/view/assets/vitesse-light-CVO1_9PV.js +1 -0
  394. package/dist/view/assets/vue-BqiEGhQt.js +1 -0
  395. package/dist/view/assets/vue-html-AaS7Mt5G.js +1 -0
  396. package/dist/view/assets/vue-vine-BoDAl6tE.js +1 -0
  397. package/dist/view/assets/vyper-CDx5xZoG.js +1 -0
  398. package/dist/view/assets/wasm-CG6Dc4jp.js +1 -0
  399. package/dist/view/assets/wasm-MzD3tlZU.js +1 -0
  400. package/dist/view/assets/wenyan-BV7otONQ.js +1 -0
  401. package/dist/view/assets/wgsl-Dx-B1_4e.js +1 -0
  402. package/dist/view/assets/wikitext-BhOHFoWU.js +1 -0
  403. package/dist/view/assets/wit-5i3qLPDT.js +1 -0
  404. package/dist/view/assets/wolfram-lXgVvXCa.js +1 -0
  405. package/dist/view/assets/xml-sdJ4AIDG.js +1 -0
  406. package/dist/view/assets/xsl-CtQFsRM5.js +1 -0
  407. package/dist/view/assets/yaml-Buea-lGh.js +1 -0
  408. package/dist/view/assets/zenscript-DVFEvuxE.js +1 -0
  409. package/dist/view/assets/zig-VOosw3JB.js +1 -0
  410. package/dist/view/index.html +10 -2
  411. package/docs/README.md +21 -15
  412. package/docs/README.zh.md +15 -9
  413. package/docs/en/authoring.md +85 -80
  414. package/docs/en/cli-reference.md +110 -72
  415. package/docs/en/deployment.md +183 -0
  416. package/docs/en/getting-started.md +112 -0
  417. package/docs/en/material-types.md +241 -0
  418. package/docs/en/settings.md +133 -0
  419. package/docs/en/shortcuts.md +89 -0
  420. package/docs/en/typing-rules.md +208 -0
  421. package/docs/zh/authoring.md +74 -69
  422. package/docs/zh/cli-reference.md +92 -58
  423. package/docs/zh/deployment.md +179 -0
  424. package/docs/zh/getting-started.md +104 -0
  425. package/docs/zh/material-types.md +769 -0
  426. package/docs/zh/settings.md +120 -0
  427. package/docs/zh/shortcuts.md +83 -0
  428. package/docs/zh/typing-rules.md +191 -0
  429. package/package.json +13 -11
  430. package/templates/en/QTYPE.md +155 -495
  431. package/templates/en/README.md +11 -11
  432. package/templates/en/TODO.md +1 -1
  433. package/templates/en/material/article.md +20 -0
  434. package/templates/en/material/assets/article/sunrise.svg +12 -0
  435. package/templates/en/material/assets/code/tree.svg +19 -0
  436. package/templates/en/material/assets/qa/login-flow.svg +17 -0
  437. package/templates/en/material/assets/sentence/pangram.svg +6 -0
  438. package/templates/en/material/assets/snippet/moon.svg +8 -0
  439. package/templates/en/material/assets/word/apple.svg +5 -0
  440. package/templates/en/material/code.md +55 -0
  441. package/templates/en/material/qa.md +33 -0
  442. package/templates/en/material/sentence.md +18 -0
  443. package/templates/en/material/snippet.md +17 -0
  444. package/templates/en/material/word.md +20 -0
  445. package/templates/zh/QTYPE.md +191 -473
  446. package/templates/zh/README.md +6 -6
  447. package/templates/zh/index.md +1 -1
  448. package/templates/zh/material/article.md +18 -0
  449. package/templates/zh/material/assets/article/sunrise.svg +12 -0
  450. package/templates/zh/material/assets/code/tree.svg +19 -0
  451. package/templates/zh/material/assets/qa/login-flow.svg +17 -0
  452. package/templates/zh/material/assets/sentence/pangram.svg +6 -0
  453. package/templates/zh/material/assets/snippet/moon.svg +8 -0
  454. package/templates/zh/material/assets/word/apple.svg +5 -0
  455. package/templates/zh/material/code.md +55 -0
  456. package/templates/zh/material/qa.md +33 -0
  457. package/templates/zh/material/sentence.md +19 -0
  458. package/templates/zh/material/snippet.md +20 -0
  459. package/templates/zh/material/word.md +20 -0
  460. package/dist/cli/commands/check/action.js +0 -56
  461. package/dist/cli/commands/check/i18n.js +0 -26
  462. package/dist/cli/commands/plugin/i18n.js +0 -28
  463. package/dist/cli/commands/plugin/index.js +0 -41
  464. package/dist/core/typing/engine.js +0 -112
  465. package/dist/view/assets/index-DBABH3dG.js +0 -111
  466. package/dist/view/assets/index-RTLZ-zOC.css +0 -1
  467. package/templates/en/material/example.md +0 -47
  468. package/templates/zh/material/example.md +0 -47
@@ -0,0 +1,241 @@
1
+ # Material Types
2
+
3
+ qtype supports six material types — `word`, `sentence`, `article`,
4
+ `snippet`, `qa`, and `code`. Each has its own Markdown structure,
5
+ parser rule, renderer, and interaction. This doc covers all four
6
+ layers: **file format → parser behaviour → UI layout → interaction**.
7
+ See `docs/zh/material-types.md` for the full Chinese reference; this
8
+ English version summarizes the same rules.
9
+
10
+ ---
11
+
12
+ ## Common conventions
13
+
14
+ ### Frontmatter
15
+
16
+ Every `.md` file starts with YAML frontmatter declaring the type for
17
+ the entire file:
18
+
19
+ ```yaml
20
+ ---
21
+ type: word # one of the six types; controls how cards parse
22
+ title: My deck # display name, optional
23
+ tags: [english, cet4]
24
+ created: 2026-01-15
25
+ updated: 2026-08-20
26
+ ---
27
+ ```
28
+
29
+ - `type` decides the parse rule for every card in the file — a file
30
+ holds exactly one type
31
+ - Missing `type` falls back to `article` (backward-compat with early
32
+ files)
33
+ - Unknown `type` values fall back to `article` parsing and use the
34
+ `CardBase` renderer
35
+
36
+ ### Card boundary
37
+
38
+ After frontmatter, the body is split into cards by **H1** (`#`):
39
+
40
+ - Each H1 starts a new card
41
+ - Prose above the first H1 is dropped
42
+ - A chunk includes its own H1 line plus everything up to the next
43
+ H1 or EOF
44
+
45
+ ### Typing text normalisation
46
+
47
+ Every "typing target" runs through `validateTypingText`:
48
+
49
+ - Smart quotes → straight (`“” → ""`, `‘’ → ''`)
50
+ - Em-dash / en-dash → hyphen
51
+ - Emoji + zero-width chars stripped
52
+ - Untypable codepoints collected in `card.unknownChars` → UI flags
53
+ the card as unplayable
54
+
55
+ ### Runtime `Card` shape
56
+
57
+ ```ts
58
+ {
59
+ id: string // "path/to/file.md#3"
60
+ title: string // display heading
61
+ answer: string // typing target (normalized)
62
+ charPlans: CharPlan[]
63
+ unknownChars: string[]
64
+ phonetic?, gloss?, image? // word/sentence only
65
+ question? // article/snippet/qa/code
66
+ romanization?, glyphMap?, romanizationAccepted? // CJK cards
67
+ }
68
+ ```
69
+
70
+ For CJK cards the parser attaches pinyin (`romanization`) plus a
71
+ `glyphMap` (roman-index → Han-index) and a per-position `accepted`
72
+ set that handles heteronyms and rare-character wildcards. Used by
73
+ the pinyin channel (`features/typing/pinyin`) to score the user's
74
+ keystrokes against Hanzi answers without requiring an IME.
75
+
76
+ ### Rich rendering (display side only, not typed)
77
+
78
+ Non-typed display slots (`## Q` prompts, article/snippet bodies,
79
+ word/sentence gloss) run through a light Markdown renderer that
80
+ supports:
81
+
82
+ | Feature | Syntax | Notes |
83
+ |---|---|---|
84
+ | **Bold / italic / inline code** | `**text**` / `*text*` / `` `code` `` | Standard Markdown |
85
+ | **Code blocks** | ` ```lang ` fence | The `code` type's answer side uses a separate Shiki path (see the code section); other positions render monospaced only |
86
+ | **Mermaid diagrams** | ` ```mermaid ` fence | `publish build` **pre-renders to SVG** (dark + light pair); the browser just looks up and swaps — zero runtime cost |
87
+ | **Math (LaTeX)** | inline `$...$`, block `$$...$$` | Rendered via **KaTeX**, lazy-loaded (~280KB) only when a page contains math. Can be toggled off in settings |
88
+
89
+ **Everything above renders only on the display side and never
90
+ participates in typing.** The user sees pretty formulas or diagrams
91
+ and still types plain keyboard characters. Example:
92
+
93
+ ```md
94
+ ---
95
+ type: qa
96
+ ---
97
+
98
+ # Gaussian integral
99
+
100
+ ## Q
101
+ Evaluate the following integral:
102
+
103
+ $$\int_{-\infty}^{\infty} e^{-x^2}\,dx = ?$$
104
+
105
+ ## A
106
+ sqrt(pi)
107
+ ```
108
+
109
+ The prompt renders the equation via KaTeX; `sqrt(pi)` in `## A` is
110
+ plain ASCII the user actually types.
111
+
112
+ ### Universal interaction
113
+
114
+ All cards render into `<TypingArena>` inside a `<CardShell>`. Shared
115
+ behaviours:
116
+
117
+ - Correct keystroke → green + advance; wrong → red (`ignorePunctuation`
118
+ and `ignoreCase` are opt-in relaxations)
119
+ - Backspace pops the top char, no cross-line restriction (stack model)
120
+ - Enter dispatches a `\n` to the engine like any other char; whether
121
+ it triggers a real line break comes from `target`, not user input
122
+ - Pause is explicit: HUD ⏸ / Alt+Space / AFK / tab hidden / window blur
123
+ - On CJK cards the pinyin channel highlights the keyboard for the
124
+ expected pinyin letter and colours wrong letters red in the preedit
125
+ bubble
126
+
127
+ ---
128
+
129
+ ## Six types at a glance
130
+
131
+ | type | Body target | Extras | Auto-speak | Rendered |
132
+ |---|---|---|---|---|
133
+ | **word** | H1 word itself | H2 phonetic, H3 gloss, H4 image | yes | centered, big glyph |
134
+ | **sentence** | H1 sentence | H2 phonetic, H3 translation, H4 image | yes | centered |
135
+ | **article** | H1 body prose | inline images | no | flow (top-aligned) |
136
+ | **snippet** | H1 body (short) | inline images | no | centered "poster" |
137
+ | **qa** | `## A` block | `## Q` block | no | flow |
138
+ | **code** | `## A` fenced code | `## Q` block | no | flow, Shiki (opt-in) |
139
+
140
+ ### word / sentence
141
+
142
+ ```md
143
+ # apple
144
+ ## /ˈæp.əl/
145
+ ### the fruit
146
+ #### ![](https://…/apple.jpg)
147
+ ```
148
+
149
+ Layout: target word/sentence big and centered; a floating speak button
150
+ sits absolute to its right so the target stays optically centered.
151
+ Auto-speak fires once per card when unpaused (deduped by `card.id`).
152
+
153
+ ### article
154
+
155
+ ```md
156
+ # Autumn Morning
157
+
158
+ The mist hung low over the valley…
159
+ ```
160
+
161
+ Long-form prose. Images in the body are extracted and rendered above
162
+ the arena (source-mode) but stripped from the typing text (the arena
163
+ itself types only characters). Title is centered; body left-aligned
164
+ (standard document typography).
165
+
166
+ ### snippet
167
+
168
+ Same shape as `article` but rendered **vertically centered with
169
+ centered text** — for poems, aphorisms, slogans, or any short
170
+ composition where visual balance beats reading flow.
171
+
172
+ ### qa
173
+
174
+ ```md
175
+ # What is a closure?
176
+
177
+ ## Q
178
+ Explain JavaScript closures with an example.
179
+
180
+ ## A
181
+ A closure is a function bundled with its lexical scope…
182
+ ```
183
+
184
+ `## Q` renders through `<MdRenderer>` (full markdown — lists, code
185
+ blocks, images all display). `## A` is the typing target as **raw
186
+ markdown text**: users type the `-`, `**`, backticks, etc. verbatim.
187
+
188
+ ### code
189
+
190
+ Same shape as `qa` but the `## A` block is expected to hold a fenced
191
+ code fence. The parser strips the ``` markers, keeping the code body
192
+ as the typing target. Language is detected from the fence tag or the
193
+ filename, and Shiki syntax highlighting is applied when
194
+ `qtype.codeSyntaxHighlight` is on (off by default — pending/hit/miss
195
+ colours suffice for muscle-memory training and disabling avoids the
196
+ ~1MB Shiki bundle).
197
+
198
+ ---
199
+
200
+ ## Dispatch
201
+
202
+ `CardView` switches on `material.meta.type`:
203
+
204
+ ```tsx
205
+ switch (type) {
206
+ case 'word': return <WordCard {...props} />
207
+ case 'sentence': return <SentenceCard {...props} />
208
+ case 'article': return <ArticleCard {...props} />
209
+ case 'snippet': return <SnippetCard {...props} />
210
+ case 'qa': return <QaCard {...props} />
211
+ case 'code':
212
+ return (
213
+ <Suspense fallback={<QaCard {...props} />}>
214
+ <CodeCard {...props} />
215
+ </Suspense>
216
+ )
217
+ default: return <CardBase {...props} />
218
+ }
219
+ ```
220
+
221
+ `CodeCard` is lazy-loaded via `React.lazy` because Shiki is heavy.
222
+ Unknown types fall back to `CardBase` (bare `<TypingArena>`).
223
+
224
+ ---
225
+
226
+ ## FAQ
227
+
228
+ **Can I mix types in one file?** No — `type` is material-level.
229
+
230
+ **Can `word` H2 span multiple lines?** No — regex only matches one
231
+ line; extra lines are ignored.
232
+
233
+ **In `article`, why can't I type images?** Image markdown is stripped
234
+ from the typing target. If you need users to type image references,
235
+ use `qa` and put them in `## A`.
236
+
237
+ **In `qa`, do users type the `- ` and `**` too?** Yes — the answer
238
+ is preserved as raw markdown so users practise those symbols.
239
+
240
+ **What if `code` has an unknown fence language?** Shiki silently
241
+ falls back to plain text; typing still works normally.
@@ -0,0 +1,133 @@
1
+ # Settings reference
2
+
3
+ Chinese: [settings.md](https://www.npmjs.com/package/@qnroa/qtype?activeTab=code&filepath=docs/zh/settings.md)
4
+
5
+ qtype has **two independent settings stores**:
6
+
7
+ 1. **Repo/CLI config** — via `qtype config`, stored at
8
+ `~/.config/qtype/config.json` (user) + `<repo>/.qtype/config.json`
9
+ (repo). See [cli-reference.md](https://www.npmjs.com/package/@qnroa/qtype?activeTab=code&filepath=docs/en/cli-reference.md#qtype-config-get--set--unset--list).
10
+ 2. **Reader UI settings** — everything the user opens the gear icon
11
+ to change, stored in the browser's kv store (`qtype.config.user`
12
+ blob). This document covers those.
13
+
14
+ Reader settings **live in the browser only** — they don't hit
15
+ `qtype config`, don't enter git, and don't affect the CLI. To sync to
16
+ another machine, use browser sync or the manual import/export below.
17
+
18
+ ---
19
+
20
+ ## Appearance
21
+
22
+ | Key | Type | Default | Notes |
23
+ |---|---|---|---|
24
+ | `qtype.themeMode` | `auto` / `mocha` / `latte` | `auto` | Theme (dark / light / follow system) |
25
+ | `qtype.uiLang` | `auto` / `zh-CN` / `en-US` | `auto` | UI language |
26
+ | `qtype.typingFontSize` | `s` / `m` / `l` | `m` | Arena font size |
27
+ | `qtype.letterSpacing` | `tight` / `normal` / `wide` | `normal` | Letter spacing |
28
+ | `qtype.spaceGlyph` | `dot` / `dash` / `blank` | `dash` | How the target's spaces are drawn |
29
+ | `qtype.breakWord` | boolean | true | Break long words to fit the arena width |
30
+
31
+ ---
32
+
33
+ ## Typing rules
34
+
35
+ Deeper semantics in [typing-rules.md](https://www.npmjs.com/package/@qnroa/qtype?activeTab=code&filepath=docs/en/typing-rules.md).
36
+
37
+ | Key | Type | Default | Notes |
38
+ |---|---|---|---|
39
+ | `qtype.hint` | `off` / `ghost` | `off` | Show ghost hint under the target |
40
+ | `qtype.ignoreCase` | boolean | false | Case-insensitive comparison |
41
+ | `qtype.ignorePunctuation` | boolean | false | Ignore punctuation variants (smart quotes / full-width) |
42
+ | `qtype.allowBackspace` | boolean | true | Allow Backspace to undo |
43
+ | `qtype.tabBehavior` | `reset` / `input` | `reset` | Tab: reset the card / expand to spaces |
44
+ | `qtype.tabWidth` | `2` / `4` | `4` | Spaces per Tab when `tabBehavior=input` |
45
+ | `qtype.completionMode` | `through` / `perfect` / `lenient` | `through` | Bar to count a card as done (see typing-rules) |
46
+ | `qtype.retryOnFail` | `off` / `auto` / `immediate` | `off` | Auto-retry policy on failure |
47
+ | `qtype.maxRetries` | 0-20 | 5 | Auto-retry cap; 0 = unlimited |
48
+ | `qtype.maxWrongRate` | 0-100 | 0 | Error-rate threshold (%); above it locks; 0 = off |
49
+ | `qtype.targetWpm` | 0-500 | 0 | Target WPM (shadow-cursor pacer); 0 = off |
50
+
51
+ ---
52
+
53
+ ## Audio
54
+
55
+ | Key | Type | Default | Notes |
56
+ |---|---|---|---|
57
+ | `qtype.keySoundEnabled` | boolean | false | Key click sound |
58
+ | `qtype.keySoundVolume` | 0-100 | 40 | Key sound volume |
59
+ | `qtype.errorSoundEnabled` | boolean | false | Error sound |
60
+ | `qtype.errorSoundVolume` | 0-100 | 60 | Error sound volume |
61
+ | `qtype.completeSoundEnabled` | boolean | true | Sound when a material finishes |
62
+ | `qtype.autoSpeak` | boolean | true | Auto-speak on word / sentence card switch |
63
+ | `qtype.autoSpeakRepeat` | 1-5 | 1 | Auto-speak repeat count |
64
+ | `qtype.ttsProvider` | `browser` / `youdao` / `google` | `browser` | TTS backend |
65
+ | `qtype.ttsVolume` | 0-100 | 100 | Speech volume |
66
+ | `qtype.ttsRate` | 50-200 | 100 | Speech rate (%) |
67
+
68
+ ---
69
+
70
+ ## Interface
71
+
72
+ | Key | Type | Default | Notes |
73
+ |---|---|---|---|
74
+ | `qtype.showKeyboard` | boolean | true | Show on-screen keyboard |
75
+ | `qtype.showHands` | boolean | true | Overlay finger-position hints on the keyboard |
76
+ | `qtype.keyboardSize` | `s` / `m` / `l` | `m` | On-screen keyboard size |
77
+ | `qtype.autoHideCursor` | boolean | true | Auto-hide cursor after 3s of no movement |
78
+ | `qtype.showNeighborPreview` | boolean | true | Show prev / next card previews on the sides |
79
+ | `qtype.showPhonetic` | boolean | true | Show phonetic line on word / sentence |
80
+ | `qtype.showGloss` | boolean | true | Show gloss on word / sentence |
81
+ | `qtype.showResultPopup` | boolean | true | Result popup on completion (WPM / accuracy) |
82
+ | `qtype.speedUnit` | `wpm` / `cpm` | `wpm` | Speed unit — words vs characters per minute |
83
+ | `qtype.afkSeconds` | 5-300 | 60 | Idle seconds → auto-pause (see [typing-rules](https://www.npmjs.com/package/@qnroa/qtype?activeTab=code&filepath=docs/en/typing-rules.md#afk-auto-pause)) |
84
+ | `qtype.minAccuracy` | 0-100 | 0 | Warn below this accuracy; 0 = off |
85
+ | `qtype.codeSyntaxHighlight` | boolean | false | Shiki highlighting on `code` cards (off by default, ~1MB bundle) |
86
+ | `qtype.mathRenderer` | boolean | true | Render `$...$` / `$$...$$` via KaTeX (lazy-loaded ~280KB) |
87
+
88
+ ---
89
+
90
+ ## Side stores
91
+
92
+ A few large / structured pieces of state live alongside the main
93
+ blob, still in the same kv layer:
94
+
95
+ | Key | Content | Notes |
96
+ |---|---|---|
97
+ | `qtype.doneState` | `Record<file, Record<idx, CardStats[]>>` | Per-card WPM / accuracy history — powers the home sparkline |
98
+ | `qtype.handOffsets` | Keyboard calibration | Offsets from the default layout |
99
+ | `qtype.keybindings` | Shortcut rebindings | See [shortcuts.md](https://www.npmjs.com/package/@qnroa/qtype?activeTab=code&filepath=docs/en/shortcuts.md) |
100
+
101
+ The v2 kv migration folded these into the unified blob so they travel
102
+ with import / export alongside theme / hint / etc.
103
+
104
+ ---
105
+
106
+ ## Import / export
107
+
108
+ The **Data** tab in the Settings dialog has buttons to export /
109
+ import:
110
+
111
+ - Export → `qtype-settings.json` — every key above plus all three
112
+ side stores
113
+ - Import → overwrites the current values; each key is schema-validated
114
+ before being written
115
+
116
+ **Import is a full overwrite, not a merge.** To change just one or
117
+ two values, use the UI or call `kvSet('key', value)` directly.
118
+
119
+ ---
120
+
121
+ ## Can the CLI read reader settings?
122
+
123
+ **No.** The keys above **only exist in the browser** and the CLI has
124
+ no access. The split is intentional:
125
+
126
+ - Who writes cards / who publishes → CLI-layer config (`qtype config`,
127
+ lives in git)
128
+ - Who types in the browser → reader-layer settings (browser kv,
129
+ per-device)
130
+
131
+ If you want e.g. team-wide default font size, that's **not possible
132
+ today**. Reader settings are "each reader's private preference"; CLI
133
+ settings are "part of the artifact".
@@ -0,0 +1,89 @@
1
+ # Keyboard shortcuts
2
+
3
+ Chinese: [shortcuts.md](https://www.npmjs.com/package/@qnroa/qtype?activeTab=code&filepath=docs/zh/shortcuts.md)
4
+
5
+ Every shortcut in the reader. This is the **factory default**;
6
+ everything can be rebound in Settings → Shortcuts. Rebindings live in
7
+ browser kv (not in git, per-device).
8
+
9
+ ## Global (any page)
10
+
11
+ | Action | mac | Windows / Linux | Notes |
12
+ |---|---|---|---|
13
+ | Open command palette | `Cmd+K` | `Ctrl+K` | ⌘K-style launcher — search any action / material |
14
+ | Palette (commands only) | `Cmd+Shift+P` | `Ctrl+Shift+P` | Actions only, no materials |
15
+
16
+ ## Typing route
17
+
18
+ ### HUD (top status bar)
19
+
20
+ | Action | mac | Windows / Linux | Notes |
21
+ |---|---|---|---|
22
+ | Pause / resume | `Alt+Space` | `Alt+Space` | Also the ⏸ button on the HUD |
23
+ | Toggle ghost hint | `Alt+H` | `Alt+Shift+H` | Show a faded target under the arena |
24
+ | Toggle on-screen keyboard | `Alt+K` | `Alt+K` | Keyboard visibility |
25
+ | Toggle finger overlay | `Alt+J` | `Alt+J` | Hand positions on the keyboard |
26
+ | Back to home | `Alt+R` | `Alt+R` | Leave the current material |
27
+
28
+ ### Card navigation
29
+
30
+ | Action | mac | Windows / Linux | Notes |
31
+ |---|---|---|---|
32
+ | Previous card | `Alt+Shift+←` | `Alt+Shift+←` | Within the current deck |
33
+ | Next card | `Alt+Shift+→` | `Alt+Shift+→` | Within the current deck |
34
+
35
+ ### Palette-only (no default binding)
36
+
37
+ These have **no shipped shortcut** — access via the command palette:
38
+
39
+ - **Jump to card N** — `card.jump`
40
+ - **Pick theme** — `pick.theme`
41
+ - **Toggle hint mode** — `hint.toggle`
42
+ - **Open settings** — `settings.open`
43
+ - **Search materials** — `search.materials`
44
+ - **Grid / list view** — `view.grid` / `view.list` (home only)
45
+ - **Reload current material** — `material.reload`
46
+ - **Jump to a random material** — `material.random`
47
+ - **Clear all done state** — `done.clearAll`
48
+ - **Reset filters** — `filter.reset`
49
+
50
+ Bind any of them in Settings → Shortcuts by clicking the row and
51
+ pressing a key combo.
52
+
53
+ ## Typing keys (engine behaviour, not remappable)
54
+
55
+ The arena's own key handling — not counted as "actions", not
56
+ rebindable:
57
+
58
+ | Key | Behaviour |
59
+ |---|---|
60
+ | Letters / digits / punctuation / space | Correct → cursor advances, char goes green; wrong → red, cursor holds |
61
+ | `Backspace` | Undo one char (unless `allowBackspace: false`, see [typing-rules.md](https://www.npmjs.com/package/@qnroa/qtype?activeTab=code&filepath=docs/en/typing-rules.md)) |
62
+ | `Enter` | Types the newline target char (not "submit") |
63
+ | `Tab` | Per `tabBehavior`: reset the card, or expand to 2 or 4 spaces |
64
+ | `Escape` | Blur the arena (does not pause) |
65
+ | `←` `→` `↑` `↓` `Home` `End` | **Ignored** — a typing tool doesn't need caret movement |
66
+
67
+ ## Rebinding
68
+
69
+ **Settings → Shortcuts**:
70
+ - Every action shows its label + current binding
71
+ - Click a row → press a new combo (recording mode)
72
+ - Escape cancels the recording, Delete clears the binding
73
+ - Conflict detection: two actions on the same combo → warning
74
+ - "Reset defaults" button restores factory bindings
75
+
76
+ **Where the rebindings live**: `qtype.keybindings` in browser kv,
77
+ folded into the main config blob by v2 migration; they travel with
78
+ import / export (see [settings.md](https://www.npmjs.com/package/@qnroa/qtype?activeTab=code&filepath=docs/en/settings.md)).
79
+
80
+ ## Platform differences
81
+
82
+ **Mac** and **Windows / Linux** have separate default tables. Most
83
+ actions use plain `Alt` combos that don't clash on either OS; a few
84
+ use `Cmd` (mac) vs `Ctrl` (Windows / Linux) to match native muscle
85
+ memory.
86
+
87
+ Platform detection is **runtime** (`navigator.platform` /
88
+ `userAgent`), not build-time — one dist works for every visitor
89
+ regardless of OS.
@@ -0,0 +1,208 @@
1
+ # Typing rules
2
+
3
+ Chinese: [typing-rules.md](https://www.npmjs.com/package/@qnroa/qtype?activeTab=code&filepath=docs/zh/typing-rules.md)
4
+
5
+ A bunch of knobs govern "what counts as a correct keystroke / when a
6
+ card is done / when to auto-retry". Everything's toggleable in
7
+ Settings; the full switch list is in [settings.md](https://www.npmjs.com/package/@qnroa/qtype?activeTab=code&filepath=docs/en/settings.md).
8
+
9
+ This doc explains the **semantics** and gives some **preset combos**.
10
+
11
+ ---
12
+
13
+ ## Input matching
14
+
15
+ ### `ignoreCase` (default off)
16
+
17
+ **On**: typing `a` matches target `A` — miss-shifts don't count as
18
+ wrong.
19
+
20
+ **Off**: case must match exactly.
21
+
22
+ **Turn on** when learning positions and don't want to fight Shift.
23
+ **Off** for prose typing where you want the rigour.
24
+
25
+ ### `ignorePunctuation` (default off)
26
+
27
+ **On**: the engine **skips over punctuation slots** — the target's
28
+ `.` `,` `!` `?` `。` `,` etc. auto-advance without a user keystroke.
29
+
30
+ **Off**: punctuation must be typed too.
31
+
32
+ **Turn on** when practising English prose and just care about the
33
+ words. **Off** for exact transcription (legal text / poems / code).
34
+
35
+ ### `allowBackspace` (default on)
36
+
37
+ **On**: Backspace undoes one char — mistakes are recoverable.
38
+
39
+ **Off**: Backspace is inert; you carry the mistake forward and rely
40
+ on `retryOnFail` / `maxWrongRate` to bail out.
41
+
42
+ **Turn off** to simulate a strict-mode exam.
43
+
44
+ ---
45
+
46
+ ## Input limits
47
+
48
+ ### `maxWrongRate` (default 0 = off, range 0-100)
49
+
50
+ Wrong-rate ceiling in percent. **Above** the limit, the engine:
51
+ - auto-undoes the last wrong char
52
+ - fires an error toast ("wrong rate exceeded X%")
53
+
54
+ E.g. `maxWrongRate: 5` → accumulated wrong rate > 5% forces auto-undo
55
+ on the next mistake, throttling you back.
56
+
57
+ **Turn on** to train accuracy over speed. **Leave 0** to allow errors
58
+ as long as you finish the pass.
59
+
60
+ ### `retryOnFail` (default `off`)
61
+
62
+ Auto-retry policy when a pass finishes without meeting `completionMode`:
63
+
64
+ - **`off`** — no auto-retry; user has to `Alt+R` manually
65
+ - **`auto`** — pass finished + gate rejected → shake the arena + reset
66
+ - **`immediate`** — stricter: **any single wrong char** triggers reset
67
+ (doesn't wait for the pass to finish)
68
+
69
+ **maxRetries** (0-20, default 5): cap on auto-retries. Beyond that,
70
+ `onSkip` fires (route usually advances to the next card). 0 =
71
+ unlimited.
72
+
73
+ **Sample combos**:
74
+ - `retryOnFail: auto` + `completionMode: perfect` → every card must
75
+ be zero-error to pass, else reset from scratch
76
+ - `retryOnFail: immediate` + `maxRetries: 3` → 3 instant resets, then
77
+ skip
78
+
79
+ ---
80
+
81
+ ## Completion
82
+
83
+ ### `completionMode` (default `through`)
84
+
85
+ "When the last char is typed, does the card count as done?"
86
+
87
+ - **`through`** — yes, as soon as you reach the end (default, most
88
+ lenient)
89
+ - **`lenient`** — yes if wrong rate ≤ 5%
90
+ - **`perfect`** — yes only when zero errors
91
+
92
+ **"Not done" outcome** depends on `retryOnFail`:
93
+ - `off` → card shows as "finished but not passed"; user can continue
94
+ - `auto` → reset from scratch
95
+ - `immediate` → strict mode; you rarely reach the end in this branch
96
+ (a wrong char already reset you)
97
+
98
+ **Independence**: completionMode and retryOnFail are two separate
99
+ knobs:
100
+ - completionMode decides "what counts as done"
101
+ - retryOnFail decides "what to do when not done"
102
+
103
+ ---
104
+
105
+ ## Tab key
106
+
107
+ ### `tabBehavior` (default `reset`)
108
+
109
+ - **`reset`** — Tab resets the current card (typical typing-tool
110
+ convention)
111
+ - **`input`** — Tab is real input, expands to `tabWidth` spaces (for
112
+ code)
113
+
114
+ ### `tabWidth` (2 or 4, default 4)
115
+
116
+ When `tabBehavior: input`, one Tab = N spaces.
117
+
118
+ **Python usually 4, Go / shell 2**. The target code in a `code` card
119
+ should use one indent style consistently — qtype only shapes user
120
+ input, it doesn't rewrite the target.
121
+
122
+ ---
123
+
124
+ ## Target-speed pacer
125
+
126
+ ### `targetWpm` (default 0 = off, range 0-500)
127
+
128
+ Turn on to render a **shadow cursor** that advances at the target
129
+ speed. Your actual cursor being ahead / behind tells you at a glance.
130
+
131
+ E.g. `targetWpm: 40` → the shadow marches at 40 WPM; matching it
132
+ means you're hitting 40.
133
+
134
+ 0 turns it off. Doesn't affect correctness judging — pure metronome.
135
+
136
+ ---
137
+
138
+ ## AFK auto-pause
139
+
140
+ ### `afkSeconds` (default 60, range 5-300)
141
+
142
+ Seconds of no "activity" before auto-pausing.
143
+
144
+ **Activity = keydown / mousemove / wheel / touchstart / touchmove.**
145
+ Mouse hovering without moving **counts as AFK**. Switching tabs or
146
+ losing window focus **pauses immediately** without waiting for the
147
+ timeout.
148
+
149
+ Once paused the arena greys out and refuses input; `Alt+Space` or
150
+ the HUD ▶ resumes.
151
+
152
+ **Why default 60**: gives room to think. Drop to 15 or 30 for strict
153
+ timing.
154
+
155
+ ---
156
+
157
+ ## Preset combos
158
+
159
+ ### "Beginner — chill mode"
160
+ ```
161
+ ignoreCase: on
162
+ ignorePunctuation: on
163
+ allowBackspace: on
164
+ completionMode: through
165
+ retryOnFail: off
166
+ maxWrongRate: 0
167
+ ```
168
+ Anything goes; finishing counts. Build speed over time.
169
+
170
+ ### "Daily practice" (recommended default)
171
+ ```
172
+ ignoreCase: off
173
+ ignorePunctuation: off
174
+ allowBackspace: on
175
+ completionMode: through
176
+ retryOnFail: auto
177
+ maxRetries: 3
178
+ maxWrongRate: 0
179
+ ```
180
+ Mistakes recoverable; on too many, retry up to 3 then skip.
181
+
182
+ ### "Exam-strict"
183
+ ```
184
+ ignoreCase: off
185
+ ignorePunctuation: off
186
+ allowBackspace: off
187
+ completionMode: perfect
188
+ retryOnFail: immediate
189
+ maxRetries: 0
190
+ ```
191
+ Errors instantly reset; no backspace; zero-error required.
192
+
193
+ ### "Sweep-through, don't grind"
194
+ ```
195
+ ignoreCase: on
196
+ ignorePunctuation: on
197
+ completionMode: through
198
+ retryOnFail: off
199
+ ```
200
+ Speed-run the deck once, record WPM, don't perfectionist your way
201
+ in.
202
+
203
+ ---
204
+
205
+ ## Related
206
+
207
+ - Where each knob lives in the UI: [settings.md](https://www.npmjs.com/package/@qnroa/qtype?activeTab=code&filepath=docs/en/settings.md)
208
+ - Shortcuts (pause / prev / next): [shortcuts.md](https://www.npmjs.com/package/@qnroa/qtype?activeTab=code&filepath=docs/en/shortcuts.md)