@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.
- package/CHANGELOG.md +1 -3
- package/CHANGELOG.zh.md +1 -2
- package/README.md +88 -56
- package/README.zh.md +82 -62
- package/dist/cli/bootstrap.js +4 -115
- package/dist/cli/commands/check/index.js +11 -10
- package/dist/cli/commands/config/action.js +5 -9
- package/dist/cli/commands/content/lint/action.js +38 -44
- package/dist/cli/commands/content/search/action.js +44 -34
- package/dist/cli/commands/content/search/i18n.js +6 -0
- package/dist/cli/commands/content/search/index.js +19 -1
- package/dist/cli/commands/content/validate/action.js +28 -27
- package/dist/cli/commands/index.js +1 -3
- package/dist/cli/commands/pack/index.js +2 -1
- package/dist/cli/commands/publish/build/action.js +39 -11
- package/dist/cli/commands/repo/new/action.js +23 -4
- package/dist/cli/commands/repo/new/i18n.js +2 -2
- package/dist/cli/commands/repo/sync/action.js +24 -4
- package/dist/cli/commands/repo/templates.js +2 -1
- package/dist/cli/utils/material.js +49 -0
- package/dist/core/encrypt.js +24 -1
- package/dist/core/index.js +1 -0
- package/dist/core/parser/frontmatter.js +39 -34
- package/dist/core/parser/parseMaterial.js +174 -24
- package/dist/core/romanization/index.js +152 -0
- package/dist/core/schemas/both.js +52 -0
- package/dist/core/schemas/index.js +3 -0
- package/dist/core/schemas/repo.js +55 -0
- package/dist/core/schemas/user.js +19 -0
- package/dist/core/typing/engine/TypingInput.js +243 -0
- package/dist/core/typing/engine/chars.js +30 -0
- package/dist/core/typing/engine/feedback.js +15 -0
- package/dist/core/typing/engine/index.js +5 -0
- package/dist/core/typing/engine/settings.js +8 -0
- package/dist/core/typing/engine/stats.js +45 -0
- package/dist/core/typing/index.js +9 -1
- package/dist/view/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
- package/dist/view/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
- package/dist/view/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
- package/dist/view/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
- package/dist/view/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
- package/dist/view/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
- package/dist/view/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
- package/dist/view/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
- package/dist/view/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
- package/dist/view/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
- package/dist/view/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
- package/dist/view/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
- package/dist/view/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
- package/dist/view/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
- package/dist/view/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
- package/dist/view/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
- package/dist/view/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
- package/dist/view/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
- package/dist/view/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
- package/dist/view/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
- package/dist/view/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
- package/dist/view/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
- package/dist/view/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
- package/dist/view/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
- package/dist/view/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
- package/dist/view/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
- package/dist/view/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
- package/dist/view/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
- package/dist/view/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
- package/dist/view/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
- package/dist/view/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
- package/dist/view/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
- package/dist/view/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
- package/dist/view/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
- package/dist/view/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
- package/dist/view/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
- package/dist/view/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
- package/dist/view/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
- package/dist/view/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
- package/dist/view/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
- package/dist/view/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
- package/dist/view/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
- package/dist/view/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
- package/dist/view/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
- package/dist/view/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
- package/dist/view/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
- package/dist/view/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
- package/dist/view/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
- package/dist/view/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
- package/dist/view/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
- package/dist/view/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
- package/dist/view/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
- package/dist/view/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
- package/dist/view/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
- package/dist/view/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
- package/dist/view/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
- package/dist/view/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
- package/dist/view/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
- package/dist/view/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
- package/dist/view/assets/abap-BdImnpbu.js +1 -0
- package/dist/view/assets/actionscript-3-B3316cI-.js +1 -0
- package/dist/view/assets/ada-bCR0ucgS.js +1 -0
- package/dist/view/assets/ahk-CsyLZFj1.js +1 -0
- package/dist/view/assets/ahk2-8Zs4aa1G.js +1 -0
- package/dist/view/assets/andromeeda-C4gqWexZ.js +1 -0
- package/dist/view/assets/angular-html-DA-rfuFy.js +1 -0
- package/dist/view/assets/angular-ts-BrjP3tb8.js +1 -0
- package/dist/view/assets/apache-Pmp26Uib.js +1 -0
- package/dist/view/assets/apex-DhZFqWV2.js +1 -0
- package/dist/view/assets/apl-CORt7UWP.js +1 -0
- package/dist/view/assets/applescript-Co6uUVPk.js +1 -0
- package/dist/view/assets/ara-BRHolxvo.js +1 -0
- package/dist/view/assets/asciidoc-CSVQ5wI8.js +1 -0
- package/dist/view/assets/asm-D_Q5rh1f.js +1 -0
- package/dist/view/assets/astro-HNnZUWAn.js +1 -0
- package/dist/view/assets/aurora-x-D-2ljcwZ.js +1 -0
- package/dist/view/assets/awk-DMzUqQB5.js +1 -0
- package/dist/view/assets/ayu-dark-DYE7WIF3.js +1 -0
- package/dist/view/assets/ayu-light-BA47KaF1.js +1 -0
- package/dist/view/assets/ayu-mirage-32ctXXKs.js +1 -0
- package/dist/view/assets/ballerina-BFfxhgS-.js +1 -0
- package/dist/view/assets/bat-CickPsom.js +1 -0
- package/dist/view/assets/beancount-k_qm7-4y.js +1 -0
- package/dist/view/assets/berry-uYugtg8r.js +1 -0
- package/dist/view/assets/bibtex-CHM0blh-.js +1 -0
- package/dist/view/assets/bicep-Bmn6On1c.js +1 -0
- package/dist/view/assets/bird2-Bx8U0n9b.js +1 -0
- package/dist/view/assets/blade-2xfisSek.js +1 -0
- package/dist/view/assets/bsl-DlhNcFeZ.js +1 -0
- package/dist/view/assets/c-BIGW1oBm.js +1 -0
- package/dist/view/assets/c3-Dp5svz6Z.js +1 -0
- package/dist/view/assets/cadence-Bv_4Rxtq.js +1 -0
- package/dist/view/assets/cairo-KRGpt6FW.js +1 -0
- package/dist/view/assets/catppuccin-frappe-CZL1YF0i.js +1 -0
- package/dist/view/assets/catppuccin-latte-DH-8KZSZ.js +1 -0
- package/dist/view/assets/catppuccin-macchiato-B7yYVSCf.js +1 -0
- package/dist/view/assets/catppuccin-mocha-Ct7hS0mc.js +1 -0
- package/dist/view/assets/chapel-DTp_pixX.js +1 -0
- package/dist/view/assets/clarity-Dn5IMItf.js +1 -0
- package/dist/view/assets/clojure-P80f7IUj.js +1 -0
- package/dist/view/assets/cmake-D1j8_8rp.js +1 -0
- package/dist/view/assets/cobol-nBiQ_Alo.js +1 -0
- package/dist/view/assets/codeowners-Bp6g37R7.js +1 -0
- package/dist/view/assets/codeql-DsOJ9woJ.js +1 -0
- package/dist/view/assets/coffee-Ch7k5sss.js +1 -0
- package/dist/view/assets/common-lisp-Cg-RD9OK.js +1 -0
- package/dist/view/assets/coq-C7JzOVbR.js +1 -0
- package/dist/view/assets/cpp-BMRokrvK.js +1 -0
- package/dist/view/assets/crystal-DGywbUpC.js +1 -0
- package/dist/view/assets/csharp-DSvCPggb.js +1 -0
- package/dist/view/assets/css-CLj8gQPS.js +1 -0
- package/dist/view/assets/csv-fuZLfV_i.js +1 -0
- package/dist/view/assets/cue-D82EKSYY.js +1 -0
- package/dist/view/assets/cypher-COkxafJQ.js +1 -0
- package/dist/view/assets/d-85-TOEBH.js +1 -0
- package/dist/view/assets/dark-plus-C3mMm8J8.js +1 -0
- package/dist/view/assets/dart-bE4Kk8sk.js +1 -0
- package/dist/view/assets/dax-CEL-wOlO.js +1 -0
- package/dist/view/assets/desktop-BmXAJ9_W.js +1 -0
- package/dist/view/assets/diff-D97Zzqfu.js +1 -0
- package/dist/view/assets/docker-BcOcwvcX.js +1 -0
- package/dist/view/assets/dotenv-Da5cRb03.js +1 -0
- package/dist/view/assets/dracula-BzJJZx-M.js +1 -0
- package/dist/view/assets/dracula-soft-BXkSAIEj.js +1 -0
- package/dist/view/assets/dream-maker-BtqSS_iP.js +1 -0
- package/dist/view/assets/edge-FbVlp4U3.js +1 -0
- package/dist/view/assets/elixir-CkH2-t6x.js +1 -0
- package/dist/view/assets/elm-DbKCFpqz.js +1 -0
- package/dist/view/assets/emacs-lisp-C_m_b--Z.js +1 -0
- package/dist/view/assets/erb-DXfck5VN.js +1 -0
- package/dist/view/assets/erlang-DsQrWhSR.js +1 -0
- package/dist/view/assets/everforest-dark-BgDCqdQA.js +1 -0
- package/dist/view/assets/everforest-light-C8M2exoo.js +1 -0
- package/dist/view/assets/fennel-BYunw83y.js +1 -0
- package/dist/view/assets/fish-BvzEVeQv.js +1 -0
- package/dist/view/assets/fluent-C4IJs8-o.js +1 -0
- package/dist/view/assets/fortran-fixed-form-CkoXwp7k.js +1 -0
- package/dist/view/assets/fortran-free-form-BxgE0vQu.js +1 -0
- package/dist/view/assets/fsharp-CXgrBDvD.js +1 -0
- package/dist/view/assets/gdresource-TyuKm33G.js +1 -0
- package/dist/view/assets/gdscript-DqcFQ5yU.js +1 -0
- package/dist/view/assets/gdshader-DkwncUOv.js +1 -0
- package/dist/view/assets/genie-D0YGMca9.js +1 -0
- package/dist/view/assets/gherkin-DyxjwDmM.js +1 -0
- package/dist/view/assets/git-commit-F4YmCXRG.js +1 -0
- package/dist/view/assets/git-rebase-r7XF79zn.js +1 -0
- package/dist/view/assets/github-dark-DHJKELXO.js +1 -0
- package/dist/view/assets/github-dark-default-Cuk6v7N8.js +1 -0
- package/dist/view/assets/github-dark-dimmed-DH5Ifo-i.js +1 -0
- package/dist/view/assets/github-dark-high-contrast-E3gJ1_iC.js +1 -0
- package/dist/view/assets/github-light-DAi9KRSo.js +1 -0
- package/dist/view/assets/github-light-default-D7oLnXFd.js +1 -0
- package/dist/view/assets/github-light-high-contrast-BfjtVDDH.js +1 -0
- package/dist/view/assets/gleam-BspZqrRM.js +1 -0
- package/dist/view/assets/glimmer-js-ByusRIyA.js +1 -0
- package/dist/view/assets/glimmer-ts-BfAWNZQY.js +1 -0
- package/dist/view/assets/glsl-DplSGwfg.js +1 -0
- package/dist/view/assets/gn-n2N0HUVH.js +1 -0
- package/dist/view/assets/gnuplot-DdkO51Og.js +1 -0
- package/dist/view/assets/go-C27-OAKa.js +1 -0
- package/dist/view/assets/graphql-ChdNCCLP.js +1 -0
- package/dist/view/assets/groovy-gcz8RCvz.js +1 -0
- package/dist/view/assets/gruvbox-dark-hard-CFHQjOhq.js +1 -0
- package/dist/view/assets/gruvbox-dark-medium-GsRaNv29.js +1 -0
- package/dist/view/assets/gruvbox-dark-soft-CVdnzihN.js +1 -0
- package/dist/view/assets/gruvbox-light-hard-CH1njM8p.js +1 -0
- package/dist/view/assets/gruvbox-light-medium-DRw_LuNl.js +1 -0
- package/dist/view/assets/gruvbox-light-soft-hJgmCMqR.js +1 -0
- package/dist/view/assets/hack-BWmVpMyf.js +1 -0
- package/dist/view/assets/haml-D5jkg6IW.js +1 -0
- package/dist/view/assets/handlebars-BpdQsYii.js +1 -0
- package/dist/view/assets/haskell-Df6bDoY_.js +1 -0
- package/dist/view/assets/haxe-CfZj7gIn.js +1 -0
- package/dist/view/assets/hcl-BWvSN4gD.js +1 -0
- package/dist/view/assets/hjson-D5-asLiD.js +1 -0
- package/dist/view/assets/hlsl-D3lLCCz7.js +1 -0
- package/dist/view/assets/horizon-BUw7H-hv.js +1 -0
- package/dist/view/assets/horizon-bright-CUuTKBJd.js +1 -0
- package/dist/view/assets/houston-DnULxvSX.js +1 -0
- package/dist/view/assets/html-derivative-DlHx6ybY.js +1 -0
- package/dist/view/assets/html-pp8916En.js +1 -0
- package/dist/view/assets/http-jrhK8wxY.js +1 -0
- package/dist/view/assets/hurl-irOxFIW8.js +1 -0
- package/dist/view/assets/hxml-2-FPmUDs.js +1 -0
- package/dist/view/assets/hy-DFXneXwc.js +1 -0
- package/dist/view/assets/imba-DGztddWO.js +1 -0
- package/dist/view/assets/index-BLryk3W4.css +1 -0
- package/dist/view/assets/index-ByMJp0a5.js +3 -0
- package/dist/view/assets/index-CRh4USfC.js +189 -0
- package/dist/view/assets/index-JNx7Ohoj.js +153 -0
- package/dist/view/assets/ini-BEwlwnbL.js +1 -0
- package/dist/view/assets/java-CylS5w8V.js +1 -0
- package/dist/view/assets/javascript-wDzz0qaB.js +1 -0
- package/dist/view/assets/jinja-f2NsQr07.js +1 -0
- package/dist/view/assets/jison-wvAkD_A8.js +1 -0
- package/dist/view/assets/json-Cp-IABpG.js +1 -0
- package/dist/view/assets/json5-C9tS-k6U.js +1 -0
- package/dist/view/assets/jsonc-Des-eS-w.js +1 -0
- package/dist/view/assets/jsonl-DcaNXYhu.js +1 -0
- package/dist/view/assets/jsonnet-DFQXde-d.js +1 -0
- package/dist/view/assets/jssm-C2t-YnRu.js +1 -0
- package/dist/view/assets/jsx-g9-lgVsj.js +1 -0
- package/dist/view/assets/julia-5Bft2YPA.js +1 -0
- package/dist/view/assets/just-Cwhn7H3k.js +1 -0
- package/dist/view/assets/kanagawa-dragon-BuwD2xS4.js +1 -0
- package/dist/view/assets/kanagawa-lotus-C3DzagqV.js +1 -0
- package/dist/view/assets/kanagawa-wave-DFGoQZhC.js +1 -0
- package/dist/view/assets/katex-BYZTj3zW.css +1 -0
- package/dist/view/assets/katex-C5jXJg4s.js +257 -0
- package/dist/view/assets/kdl-DV7GczEv.js +1 -0
- package/dist/view/assets/kotlin-BdnUsdx6.js +1 -0
- package/dist/view/assets/kusto-wEQ09or8.js +1 -0
- package/dist/view/assets/laserwave-DUszq2jm.js +1 -0
- package/dist/view/assets/latex-D5pSuvFb.js +1 -0
- package/dist/view/assets/lean-BZvkOJ9d.js +1 -0
- package/dist/view/assets/less-B1dDrJ26.js +1 -0
- package/dist/view/assets/light-plus-B7mTdjB0.js +1 -0
- package/dist/view/assets/liquid-C0sCDyMI.js +1 -0
- package/dist/view/assets/llvm-BZoOZj88.js +1 -0
- package/dist/view/assets/log-2UxHyX5q.js +1 -0
- package/dist/view/assets/logo-BtOb2qkB.js +1 -0
- package/dist/view/assets/lua-BaeVxFsk.js +1 -0
- package/dist/view/assets/luau-BnpPk5vE.js +1 -0
- package/dist/view/assets/make-CHLpvVh8.js +1 -0
- package/dist/view/assets/markdown-Cvjx9yec.js +1 -0
- package/dist/view/assets/marko-DjSrsDqO.js +1 -0
- package/dist/view/assets/material-theme-D5KoaKCx.js +1 -0
- package/dist/view/assets/material-theme-darker-BfHTSMKl.js +1 -0
- package/dist/view/assets/material-theme-lighter-B0m2ddpp.js +1 -0
- package/dist/view/assets/material-theme-ocean-CyktbL80.js +1 -0
- package/dist/view/assets/material-theme-palenight-Csfq5Kiy.js +1 -0
- package/dist/view/assets/matlab-D7o27uSR.js +1 -0
- package/dist/view/assets/mdc-D1_yUvq7.js +1 -0
- package/dist/view/assets/mdx-Cmh6b_Ma.js +1 -0
- package/dist/view/assets/mermaid-CQcHuHx7.js +1 -0
- package/dist/view/assets/min-dark-CafNBF8u.js +1 -0
- package/dist/view/assets/min-light-CTRr51gU.js +1 -0
- package/dist/view/assets/mipsasm-CKIfxQSi.js +1 -0
- package/dist/view/assets/mojo-DJz3ZmWd.js +1 -0
- package/dist/view/assets/monokai-BRVnQi9A.js +1 -0
- package/dist/view/assets/moonbit-CHtswR0a.js +1 -0
- package/dist/view/assets/move-el3G9tDJ.js +1 -0
- package/dist/view/assets/narrat-DRg8JJMk.js +1 -0
- package/dist/view/assets/nextflow-C-mBbutL.js +1 -0
- package/dist/view/assets/nextflow-groovy-vE_lwT2v.js +1 -0
- package/dist/view/assets/nginx-BpAMiNFr.js +1 -0
- package/dist/view/assets/night-owl-C39BiMTA.js +1 -0
- package/dist/view/assets/night-owl-light-CMTm3GFP.js +1 -0
- package/dist/view/assets/nim-BIad80T-.js +1 -0
- package/dist/view/assets/nix-CwoSXNpI.js +1 -0
- package/dist/view/assets/nord-Ddv68eIx.js +1 -0
- package/dist/view/assets/nsis-BlV79W_Q.js +1 -0
- package/dist/view/assets/nushell-D3jzshHO.js +1 -0
- package/dist/view/assets/objective-c-DXmwc3jG.js +1 -0
- package/dist/view/assets/objective-cpp-CLxacb5B.js +1 -0
- package/dist/view/assets/ocaml-C0hk2d4L.js +1 -0
- package/dist/view/assets/odin-BBf5iR-q.js +1 -0
- package/dist/view/assets/one-dark-pro-DVMEJ2y_.js +1 -0
- package/dist/view/assets/one-light-C3Wv6jpd.js +1 -0
- package/dist/view/assets/openscad-C4EeE6gA.js +1 -0
- package/dist/view/assets/org-DM6o9KBp.js +1 -0
- package/dist/view/assets/pascal-D93ZcfNL.js +1 -0
- package/dist/view/assets/perl-B9cMNwum.js +1 -0
- package/dist/view/assets/php-Csjmro_R.js +1 -0
- package/dist/view/assets/pkl-u5AG7uiY.js +1 -0
- package/dist/view/assets/plastic-3e1v2bzS.js +1 -0
- package/dist/view/assets/plsql-ChMvpjG-.js +1 -0
- package/dist/view/assets/po-BTJTHyun.js +1 -0
- package/dist/view/assets/poimandres-CS3Unz2-.js +1 -0
- package/dist/view/assets/polar-C0HS_06l.js +1 -0
- package/dist/view/assets/postcss-CXtECtnM.js +1 -0
- package/dist/view/assets/powerquery-CEu0bR-o.js +1 -0
- package/dist/view/assets/powershell-BmBUJMz7.js +1 -0
- package/dist/view/assets/prisma-Vru482bI.js +1 -0
- package/dist/view/assets/prolog-CbFg5uaA.js +1 -0
- package/dist/view/assets/proto-C7zT0LnQ.js +1 -0
- package/dist/view/assets/pug-DKIMFp6K.js +1 -0
- package/dist/view/assets/puppet-BMWR74SV.js +1 -0
- package/dist/view/assets/purescript-CklMAg4u.js +1 -0
- package/dist/view/assets/python-B6aJPvgy.js +1 -0
- package/dist/view/assets/qml-3beO22l8.js +1 -0
- package/dist/view/assets/qmldir-C8lEn-DE.js +1 -0
- package/dist/view/assets/qss-IeuSbFQv.js +1 -0
- package/dist/view/assets/r-Cf5RLm7j.js +1 -0
- package/dist/view/assets/racket-BqYA7rlc.js +1 -0
- package/dist/view/assets/raku-DXvB9xmW.js +1 -0
- package/dist/view/assets/razor-BjBPvh-w.js +1 -0
- package/dist/view/assets/rbs-CpoqiR4B.js +1 -0
- package/dist/view/assets/red-hvxz__6c.js +1 -0
- package/dist/view/assets/reg-C-SQnVFl.js +1 -0
- package/dist/view/assets/regexp-CDVJQ6XC.js +1 -0
- package/dist/view/assets/rel-C3B-1QV4.js +1 -0
- package/dist/view/assets/riscv-BM1_JUlF.js +1 -0
- package/dist/view/assets/ron-D8l8udqQ.js +1 -0
- package/dist/view/assets/rose-pine-5qJOZa0Y.js +1 -0
- package/dist/view/assets/rose-pine-dawn-zx0QlTCp.js +1 -0
- package/dist/view/assets/rose-pine-moon-C9pEdX9L.js +1 -0
- package/dist/view/assets/rosmsg-BJDFO7_C.js +1 -0
- package/dist/view/assets/rst-bs7f0vWN.js +1 -0
- package/dist/view/assets/ruby-C0TQ7zu5.js +1 -0
- package/dist/view/assets/rust-B1yitclQ.js +1 -0
- package/dist/view/assets/sas-DEy46yEz.js +1 -0
- package/dist/view/assets/sass-Cj5Yp3dK.js +1 -0
- package/dist/view/assets/scala-CqE71os6.js +1 -0
- package/dist/view/assets/scheme-C98Dy4si.js +1 -0
- package/dist/view/assets/scss-D5BDwBP9.js +1 -0
- package/dist/view/assets/sdbl-DVxCFoDh.js +1 -0
- package/dist/view/assets/shaderlab-Dg9Lc6iA.js +1 -0
- package/dist/view/assets/shellscript-Yzrsuije.js +1 -0
- package/dist/view/assets/shellsession-BADoaaVG.js +1 -0
- package/dist/view/assets/slack-dark-BthQWCQV.js +1 -0
- package/dist/view/assets/slack-ochin-DqwNpetd.js +1 -0
- package/dist/view/assets/smalltalk-BOQMe2GC.js +1 -0
- package/dist/view/assets/smithy-cds9vsN8.js +1 -0
- package/dist/view/assets/snazzy-light-Bw305WKR.js +1 -0
- package/dist/view/assets/solarized-dark-CpvCGNkr.js +1 -0
- package/dist/view/assets/solarized-light-Dlz6yCKv.js +1 -0
- package/dist/view/assets/solidity-DijEV5ha.js +1 -0
- package/dist/view/assets/soy-8wufbnw4.js +1 -0
- package/dist/view/assets/sparql-rVzFXLq3.js +1 -0
- package/dist/view/assets/splunk-BtCnVYZw.js +1 -0
- package/dist/view/assets/sql-CRqJ_cUM.js +1 -0
- package/dist/view/assets/ssh-config-_ykCGR6B.js +1 -0
- package/dist/view/assets/stata-DI20mbqo.js +1 -0
- package/dist/view/assets/stylus-BEDo0Tqx.js +1 -0
- package/dist/view/assets/surrealql-Cjom0U5J.js +1 -0
- package/dist/view/assets/svelte-Cy7k_4gC.js +1 -0
- package/dist/view/assets/swift-C2oV4EkX.js +1 -0
- package/dist/view/assets/synthwave-84-CbfX1IO0.js +1 -0
- package/dist/view/assets/system-verilog-0hqHdDBg.js +1 -0
- package/dist/view/assets/systemd-4A_iFExJ.js +1 -0
- package/dist/view/assets/talonscript-CkByrt1z.js +1 -0
- package/dist/view/assets/tasl-QIJgUcNo.js +1 -0
- package/dist/view/assets/tcl-dwOrl1Do.js +1 -0
- package/dist/view/assets/templ-DhtptRzy.js +1 -0
- package/dist/view/assets/terraform-BETggiCN.js +1 -0
- package/dist/view/assets/tex-D96PA37w.js +1 -0
- package/dist/view/assets/tokyo-night-hegEt444.js +1 -0
- package/dist/view/assets/toml-vGWfd6FD.js +1 -0
- package/dist/view/assets/ts-tags-D351s5mN.js +1 -0
- package/dist/view/assets/tsv-B_m7g4N7.js +1 -0
- package/dist/view/assets/tsx-COt5Ahok.js +1 -0
- package/dist/view/assets/turtle-BsS91CYL.js +1 -0
- package/dist/view/assets/twig-27uCiNez.js +1 -0
- package/dist/view/assets/typescript-BPQ3VLAy.js +1 -0
- package/dist/view/assets/typespec-CAFt9gP4.js +1 -0
- package/dist/view/assets/typst-BUadGCkm.js +1 -0
- package/dist/view/assets/v-BGw2Nkan.js +1 -0
- package/dist/view/assets/vala-CsfeWuGM.js +1 -0
- package/dist/view/assets/vb-Cu-pLBUe.js +1 -0
- package/dist/view/assets/verilog-nZwndyjY.js +1 -0
- package/dist/view/assets/vesper-DRje8inN.js +1 -0
- package/dist/view/assets/vhdl-CeAyd5Ju.js +1 -0
- package/dist/view/assets/viml-CJc9bBzg.js +1 -0
- package/dist/view/assets/vitesse-black-Bkuqu6BP.js +1 -0
- package/dist/view/assets/vitesse-dark-D0r3Knsf.js +1 -0
- package/dist/view/assets/vitesse-light-CVO1_9PV.js +1 -0
- package/dist/view/assets/vue-BqiEGhQt.js +1 -0
- package/dist/view/assets/vue-html-AaS7Mt5G.js +1 -0
- package/dist/view/assets/vue-vine-BoDAl6tE.js +1 -0
- package/dist/view/assets/vyper-CDx5xZoG.js +1 -0
- package/dist/view/assets/wasm-CG6Dc4jp.js +1 -0
- package/dist/view/assets/wasm-MzD3tlZU.js +1 -0
- package/dist/view/assets/wenyan-BV7otONQ.js +1 -0
- package/dist/view/assets/wgsl-Dx-B1_4e.js +1 -0
- package/dist/view/assets/wikitext-BhOHFoWU.js +1 -0
- package/dist/view/assets/wit-5i3qLPDT.js +1 -0
- package/dist/view/assets/wolfram-lXgVvXCa.js +1 -0
- package/dist/view/assets/xml-sdJ4AIDG.js +1 -0
- package/dist/view/assets/xsl-CtQFsRM5.js +1 -0
- package/dist/view/assets/yaml-Buea-lGh.js +1 -0
- package/dist/view/assets/zenscript-DVFEvuxE.js +1 -0
- package/dist/view/assets/zig-VOosw3JB.js +1 -0
- package/dist/view/index.html +10 -2
- package/docs/README.md +21 -15
- package/docs/README.zh.md +15 -9
- package/docs/en/authoring.md +85 -80
- package/docs/en/cli-reference.md +110 -72
- package/docs/en/deployment.md +183 -0
- package/docs/en/getting-started.md +112 -0
- package/docs/en/material-types.md +241 -0
- package/docs/en/settings.md +133 -0
- package/docs/en/shortcuts.md +89 -0
- package/docs/en/typing-rules.md +208 -0
- package/docs/zh/authoring.md +74 -69
- package/docs/zh/cli-reference.md +92 -58
- package/docs/zh/deployment.md +179 -0
- package/docs/zh/getting-started.md +104 -0
- package/docs/zh/material-types.md +769 -0
- package/docs/zh/settings.md +120 -0
- package/docs/zh/shortcuts.md +83 -0
- package/docs/zh/typing-rules.md +191 -0
- package/package.json +13 -11
- package/templates/en/QTYPE.md +155 -495
- package/templates/en/README.md +11 -11
- package/templates/en/TODO.md +1 -1
- package/templates/en/material/article.md +20 -0
- package/templates/en/material/assets/article/sunrise.svg +12 -0
- package/templates/en/material/assets/code/tree.svg +19 -0
- package/templates/en/material/assets/qa/login-flow.svg +17 -0
- package/templates/en/material/assets/sentence/pangram.svg +6 -0
- package/templates/en/material/assets/snippet/moon.svg +8 -0
- package/templates/en/material/assets/word/apple.svg +5 -0
- package/templates/en/material/code.md +55 -0
- package/templates/en/material/qa.md +33 -0
- package/templates/en/material/sentence.md +18 -0
- package/templates/en/material/snippet.md +17 -0
- package/templates/en/material/word.md +20 -0
- package/templates/zh/QTYPE.md +191 -473
- package/templates/zh/README.md +6 -6
- package/templates/zh/index.md +1 -1
- package/templates/zh/material/article.md +18 -0
- package/templates/zh/material/assets/article/sunrise.svg +12 -0
- package/templates/zh/material/assets/code/tree.svg +19 -0
- package/templates/zh/material/assets/qa/login-flow.svg +17 -0
- package/templates/zh/material/assets/sentence/pangram.svg +6 -0
- package/templates/zh/material/assets/snippet/moon.svg +8 -0
- package/templates/zh/material/assets/word/apple.svg +5 -0
- package/templates/zh/material/code.md +55 -0
- package/templates/zh/material/qa.md +33 -0
- package/templates/zh/material/sentence.md +19 -0
- package/templates/zh/material/snippet.md +20 -0
- package/templates/zh/material/word.md +20 -0
- package/dist/cli/commands/check/action.js +0 -56
- package/dist/cli/commands/check/i18n.js +0 -26
- package/dist/cli/commands/plugin/i18n.js +0 -28
- package/dist/cli/commands/plugin/index.js +0 -41
- package/dist/core/typing/engine.js +0 -112
- package/dist/view/assets/index-DBABH3dG.js +0 -111
- package/dist/view/assets/index-RTLZ-zOC.css +0 -1
- package/templates/en/material/example.md +0 -47
- 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
|
+
#### 
|
|
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)
|