feat: build theme-aware pictures (equations) (#1772)
Some checks failed
tinymist::ci / Duplicate Actions Detection (push) Has been cancelled
tinymist::ci / Check Clippy, Formatting, Completion, Documentation, and Tests (Linux) (push) Has been cancelled
tinymist::ci / Check Minimum Rust version and Tests (Windows) (push) Has been cancelled
tinymist::ci / prepare-build (push) Has been cancelled
tinymist::gh_pages / build-gh-pages (push) Has been cancelled
tinymist::ci / E2E Tests (darwin-arm64 on macos-latest) (push) Has been cancelled
tinymist::ci / E2E Tests (linux-x64 on ubuntu-22.04) (push) Has been cancelled
tinymist::ci / E2E Tests (linux-x64 on ubuntu-latest) (push) Has been cancelled
tinymist::ci / E2E Tests (win32-x64 on windows-2019) (push) Has been cancelled
tinymist::ci / E2E Tests (win32-x64 on windows-latest) (push) Has been cancelled
tinymist::ci / build-binary (push) Has been cancelled
tinymist::ci / build-vsc-assets (push) Has been cancelled
tinymist::ci / build-vscode (push) Has been cancelled
tinymist::ci / build-vscode-others (push) Has been cancelled
tinymist::ci / publish-vscode (push) Has been cancelled

* revert: "test: bad changes"

* feat: m1source
This commit is contained in:
Myriad-Dreamin 2025-06-05 11:10:04 +08:00 committed by GitHub
parent 646dd81a35
commit 51db97ffcc
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 347 additions and 155 deletions

View file

@ -76,7 +76,7 @@ Extra features:
Tinymist's versions follow the [Semantic Versioning](https://semver.org/) scheme, in format of `MAJOR.MINOR.PATCH`. Besides, tinymist follows special rules for the version number:
- If a version is suffixed with `-rcN` (<img alt="typst-block" src="./assets/images/introduction.typ-inlined0.svg" />), e.g. `0.11.0-rc1` and `0.12.1-rc1`, it means this version is a release candidate. It is used to test publish script and E2E functionalities. These versions will not be published to the marketplace.
- If a version is suffixed with `-rcN` (<picture><source media="(prefers-color-scheme: dark)" srcset="./assets/images/introduction.typ-inlined0.svg" /><img alt="typst-block" src="./assets/images/introduction.typ-inlined1.svg" /></picture>), e.g. `0.11.0-rc1` and `0.12.1-rc1`, it means this version is a release candidate. It is used to test publish script and E2E functionalities. These versions will not be published to the marketplace.
- If the `PATCH` number is odd, e.g. `0.11.1` and `0.12.3`, it means this version is a nightly release. The nightly release will use both [tinymist](https://github.com/Myriad-Dreamin/tinymist/tree/main) and [typst](https://github.com/typst/typst/tree/main) at **main branch**. They will be published as prerelease version to the marketplace. Note that in nightly releases, we change `#sys.version` to the next minor release to help develop documents with nightly features. For example, in tinymist nightly v0.12.1 or v0.12.3, the `#sys.version` is changed to `version(0, 13, 0)`.
- Otherwise, if the `PATCH` number is even, e.g. `0.11.0` and `0.12.2`, it means this version is a regular release. The regular release will always use the recent stable version of tinymist and typst.

View file

@ -1,30 +1,30 @@
<svg class="typst-doc" viewBox="0 0 30.168111111111113 17.413" width="30.168111111111113pt" height="17.413pt" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:h5="http://www.w3.org/1999/xhtml">
<svg class="typst-doc" viewBox="0 0 28.796833333333332 7.171500000000001" width="28.796833333333332pt" height="7.171500000000001pt" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:h5="http://www.w3.org/1999/xhtml">
<g>
<g transform="translate(0 12.463)">
<g transform="translate(0 7.171500000000001)">
<g class="typst-text" transform="scale(1, -1)">
<use xlink:href="#g9C136C76572213DE6707324506E34D78" x="0" fill="#c0caf5" fill-rule="nonzero"/>
<use xlink:href="#g7936AD3000646C81EC3F86CF33FB2586" x="0" fill="#f0f6fc" fill-rule="nonzero"/>
</g>
</g>
<g transform="translate(13.054555555555556 12.463)">
<g transform="translate(12.461166666666667 7.171500000000001)">
<g class="typst-text" transform="scale(1, -1)">
<use xlink:href="#gDD96380C275DE9AF15656F8D405976A0" x="0" fill="#c0caf5" fill-rule="nonzero"/>
<use xlink:href="#gEF371FBA9DF8545F57E1B97AFE6E9F72" x="0" fill="#f0f6fc" fill-rule="nonzero"/>
</g>
</g>
<g transform="translate(24.668111111111113 12.463)">
<g transform="translate(23.546833333333332 7.171500000000001)">
<g class="typst-text" transform="scale(1, -1)">
<use xlink:href="#gB37B7CB6A35FD21388CA262EF751BF3B" x="0" fill="#c0caf5" fill-rule="nonzero"/>
<use xlink:href="#g5C5EEB92102F3768E1DB77DB85972F14" x="0" fill="#f0f6fc" fill-rule="nonzero"/>
</g>
</g>
</g>
<defs id="glyph">
<symbol id="g9C136C76572213DE6707324506E34D78" overflow="visible">
<path d="M 9.504 7.513 C 9.295 7.513 8.613 7.48 8.404 7.48 C 8.195 7.48 7.502 7.513 7.2929997 7.513 C 7.128 7.513 7.051 7.425 7.051 7.249 C 7.051 7.15 7.128 7.095 7.2929997 7.084 C 7.755 7.084 7.986 6.941 7.986 6.6549997 C 7.986 6.5889997 7.975 6.512 7.9639997 6.435 L 6.776 1.727 L 4.411 7.282 C 4.323 7.491 4.301 7.513 4.026 7.513 L 2.563 7.513 C 2.299 7.513 2.2 7.491 2.2 7.249 C 2.2 7.139 2.321 7.084 2.552 7.084 C 3.014 7.084 3.245 7.073 3.256 7.04 L 1.793 1.21 C 1.694 0.781 1.441 0.539 1.045 0.462 C 0.759 0.429 0.429 0.473 0.429 0.16499999 C 0.429 0.055 0.495 0 0.616 0 C 0.814 0 1.496 0.033 1.705 0.033 C 1.914 0.033 2.618 0 2.827 0 C 2.992 0 3.069 0.088 3.069 0.264 C 3.069 0.363 2.981 0.41799998 2.805 0.429 C 2.354 0.44 2.134 0.583 2.134 0.858 C 2.134 0.913 2.145 0.99 2.167 1.1 L 3.586 6.721 L 6.336 0.231 C 6.402 0.077 6.49 0 6.5889997 0 C 6.6879997 0 6.754 0.088 6.798 0.264 L 8.327 6.314 C 8.47 6.875 8.778 7.073 9.46 7.084 C 9.614 7.095 9.691 7.183 9.691 7.3589997 C 9.658 7.458 9.647 7.513 9.504 7.513 Z "/>
<symbol id="g7936AD3000646C81EC3F86CF33FB2586" overflow="visible">
<path d="M 9.072 7.1714997 C 8.872499 7.1714997 8.221499 7.14 8.022 7.14 C 7.8224998 7.14 7.161 7.1714997 6.9614997 7.1714997 C 6.804 7.1714997 6.7304997 7.0875 6.7304997 6.9195 C 6.7304997 6.825 6.804 6.7725 6.9614997 6.762 C 7.4024997 6.762 7.6229997 6.6254997 7.6229997 6.3525 C 7.6229997 6.2894998 7.6124997 6.216 7.6019998 6.1425 L 6.468 1.6485 L 4.2105 6.9509997 C 4.1265 7.1505 4.1054997 7.1714997 3.843 7.1714997 L 2.4465 7.1714997 C 2.1945 7.1714997 2.1 7.1505 2.1 6.9195 C 2.1 6.8145 2.2154999 6.762 2.4359999 6.762 C 2.8769999 6.762 3.0974998 6.7515 3.108 6.72 L 1.7114999 1.155 C 1.617 0.74549997 1.3755 0.5145 0.9975 0.44099998 C 0.7245 0.4095 0.4095 0.4515 0.4095 0.1575 C 0.4095 0.0525 0.4725 0 0.588 0 C 0.777 0 1.428 0.0315 1.6274999 0.0315 C 1.827 0.0315 2.499 0 2.6985 0 C 2.856 0 2.9294999 0.084 2.9294999 0.252 C 2.9294999 0.3465 2.8455 0.399 2.6775 0.4095 C 2.247 0.42 2.037 0.5565 2.037 0.819 C 2.037 0.8715 2.0475 0.945 2.0685 1.05 L 3.4229999 6.4154997 L 6.048 0.22049999 C 6.111 0.0735 6.1949997 0 6.2894998 0 C 6.384 0 6.447 0.084 6.489 0.252 L 7.9484997 6.027 C 8.085 6.5625 8.379 6.7515 9.03 6.762 C 9.177 6.7725 9.2505 6.8564997 9.2505 7.0245 C 9.219 7.119 9.2085 7.1714997 9.072 7.1714997 Z "/>
</symbol>
<symbol id="gDD96380C275DE9AF15656F8D405976A0" overflow="visible">
<path d="M 7.546 2.497 C 7.656 2.552 7.711 2.629 7.711 2.75 C 7.711 2.871 7.656 2.948 7.546 3.003 L 1.232 5.995 C 1.199 6.006 1.155 6.017 1.111 6.017 C 0.935 6.017 0.847 5.929 0.847 5.742 C 0.847 5.643 0.902 5.566 1.001 5.522 L 6.875 2.75 L 1.001 -0.022 C 0.902 -0.066 0.847 -0.143 0.847 -0.242 C 0.847 -0.429 0.935 -0.517 1.111 -0.517 C 1.155 -0.517 1.199 -0.506 1.232 -0.495 Z "/>
<symbol id="gEF371FBA9DF8545F57E1B97AFE6E9F72" overflow="visible">
<path d="M 7.203 2.3834999 C 7.308 2.4359999 7.3605 2.5095 7.3605 2.625 C 7.3605 2.7405 7.308 2.814 7.203 2.8665 L 1.176 5.7225 C 1.1445 5.733 1.1025 5.7434998 1.0605 5.7434998 C 0.8925 5.7434998 0.8085 5.6595 0.8085 5.481 C 0.8085 5.3865 0.861 5.3129997 0.9555 5.271 L 6.5625 2.625 L 0.9555 -0.021 C 0.861 -0.063 0.8085 -0.1365 0.8085 -0.23099999 C 0.8085 -0.4095 0.8925 -0.4935 1.0605 -0.4935 C 1.1025 -0.4935 1.1445 -0.48299998 1.176 -0.4725 Z "/>
</symbol>
<symbol id="gB37B7CB6A35FD21388CA262EF751BF3B" overflow="visible">
<path d="M 2.739 -0.242 C 4.29 -0.242 5.06 1.012 5.06 3.52 C 5.06 5.203 4.708 6.325 4.015 6.875 C 3.6299999 7.172 3.201 7.3259997 2.75 7.3259997 C 1.199 7.3259997 0.429 6.061 0.429 3.52 C 0.429 1.496 0.968 -0.242 2.739 -0.242 Z M 3.971 5.764 C 4.048 5.379 4.081 4.675 4.081 3.652 C 4.081 2.6399999 4.037 1.892 3.96 1.408 C 3.817 0.528 3.41 0.088 2.739 0.088 C 2.486 0.088 2.233 0.187 2.002 0.374 C 1.705 0.627 1.529 1.144 1.452 1.936 C 1.419 2.211 1.408 2.783 1.408 3.652 C 1.408 4.609 1.441 5.2799997 1.496 5.643 C 1.595 6.248 1.793 6.633 2.101 6.798 C 2.343 6.93 2.552 6.996 2.739 6.996 C 3.454 6.996 3.85 6.413 3.971 5.764 Z "/>
<symbol id="g5C5EEB92102F3768E1DB77DB85972F14" overflow="visible">
<path d="M 2.6145 -0.23099999 C 4.095 -0.23099999 4.83 0.96599996 4.83 3.36 C 4.83 4.9665 4.494 6.0375 3.8325 6.5625 C 3.465 6.8459997 3.0555 6.993 2.625 6.993 C 1.1445 6.993 0.4095 5.7855 0.4095 3.36 C 0.4095 1.428 0.92399997 -0.23099999 2.6145 -0.23099999 Z M 3.7905 5.502 C 3.8639998 5.1345 3.8955 4.4625 3.8955 3.486 C 3.8955 2.52 3.8535 1.806 3.78 1.344 C 3.6434999 0.504 3.2549999 0.084 2.6145 0.084 C 2.373 0.084 2.1315 0.1785 1.911 0.357 C 1.6274999 0.5985 1.4595 1.092 1.386 1.8479999 C 1.3544999 2.1104999 1.344 2.6564999 1.344 3.486 C 1.344 4.3995 1.3755 5.04 1.428 5.3865 C 1.5225 5.9639997 1.7114999 6.3315 2.0055 6.489 C 2.2365 6.615 2.4359999 6.678 2.6145 6.678 C 3.297 6.678 3.675 6.1215 3.7905 5.502 Z "/>
</symbol>
</defs>
</svg>

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

Before After
Before After

View file

@ -1,30 +1,30 @@
<svg class="typst-doc" viewBox="0 0 30.168111111111113 17.413" width="30.168111111111113pt" height="17.413pt" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:h5="http://www.w3.org/1999/xhtml">
<svg class="typst-doc" viewBox="0 0 28.796833333333332 7.171500000000001" width="28.796833333333332pt" height="7.171500000000001pt" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:h5="http://www.w3.org/1999/xhtml">
<g>
<g transform="translate(0 12.463)">
<g transform="translate(0 7.171500000000001)">
<g class="typst-text" transform="scale(1, -1)">
<use xlink:href="#g9C136C76572213DE6707324506E34D78" x="0" fill="#000000" fill-rule="nonzero"/>
<use xlink:href="#g7936AD3000646C81EC3F86CF33FB2586" x="0" fill="#000000" fill-rule="nonzero"/>
</g>
</g>
<g transform="translate(13.054555555555556 12.463)">
<g transform="translate(12.461166666666667 7.171500000000001)">
<g class="typst-text" transform="scale(1, -1)">
<use xlink:href="#gDD96380C275DE9AF15656F8D405976A0" x="0" fill="#000000" fill-rule="nonzero"/>
<use xlink:href="#gEF371FBA9DF8545F57E1B97AFE6E9F72" x="0" fill="#000000" fill-rule="nonzero"/>
</g>
</g>
<g transform="translate(24.668111111111113 12.463)">
<g transform="translate(23.546833333333332 7.171500000000001)">
<g class="typst-text" transform="scale(1, -1)">
<use xlink:href="#gB37B7CB6A35FD21388CA262EF751BF3B" x="0" fill="#000000" fill-rule="nonzero"/>
<use xlink:href="#g5C5EEB92102F3768E1DB77DB85972F14" x="0" fill="#000000" fill-rule="nonzero"/>
</g>
</g>
</g>
<defs id="glyph">
<symbol id="g9C136C76572213DE6707324506E34D78" overflow="visible">
<path d="M 9.504 7.513 C 9.295 7.513 8.613 7.48 8.404 7.48 C 8.195 7.48 7.502 7.513 7.2929997 7.513 C 7.128 7.513 7.051 7.425 7.051 7.249 C 7.051 7.15 7.128 7.095 7.2929997 7.084 C 7.755 7.084 7.986 6.941 7.986 6.6549997 C 7.986 6.5889997 7.975 6.512 7.9639997 6.435 L 6.776 1.727 L 4.411 7.282 C 4.323 7.491 4.301 7.513 4.026 7.513 L 2.563 7.513 C 2.299 7.513 2.2 7.491 2.2 7.249 C 2.2 7.139 2.321 7.084 2.552 7.084 C 3.014 7.084 3.245 7.073 3.256 7.04 L 1.793 1.21 C 1.694 0.781 1.441 0.539 1.045 0.462 C 0.759 0.429 0.429 0.473 0.429 0.16499999 C 0.429 0.055 0.495 0 0.616 0 C 0.814 0 1.496 0.033 1.705 0.033 C 1.914 0.033 2.618 0 2.827 0 C 2.992 0 3.069 0.088 3.069 0.264 C 3.069 0.363 2.981 0.41799998 2.805 0.429 C 2.354 0.44 2.134 0.583 2.134 0.858 C 2.134 0.913 2.145 0.99 2.167 1.1 L 3.586 6.721 L 6.336 0.231 C 6.402 0.077 6.49 0 6.5889997 0 C 6.6879997 0 6.754 0.088 6.798 0.264 L 8.327 6.314 C 8.47 6.875 8.778 7.073 9.46 7.084 C 9.614 7.095 9.691 7.183 9.691 7.3589997 C 9.658 7.458 9.647 7.513 9.504 7.513 Z "/>
<symbol id="g7936AD3000646C81EC3F86CF33FB2586" overflow="visible">
<path d="M 9.072 7.1714997 C 8.872499 7.1714997 8.221499 7.14 8.022 7.14 C 7.8224998 7.14 7.161 7.1714997 6.9614997 7.1714997 C 6.804 7.1714997 6.7304997 7.0875 6.7304997 6.9195 C 6.7304997 6.825 6.804 6.7725 6.9614997 6.762 C 7.4024997 6.762 7.6229997 6.6254997 7.6229997 6.3525 C 7.6229997 6.2894998 7.6124997 6.216 7.6019998 6.1425 L 6.468 1.6485 L 4.2105 6.9509997 C 4.1265 7.1505 4.1054997 7.1714997 3.843 7.1714997 L 2.4465 7.1714997 C 2.1945 7.1714997 2.1 7.1505 2.1 6.9195 C 2.1 6.8145 2.2154999 6.762 2.4359999 6.762 C 2.8769999 6.762 3.0974998 6.7515 3.108 6.72 L 1.7114999 1.155 C 1.617 0.74549997 1.3755 0.5145 0.9975 0.44099998 C 0.7245 0.4095 0.4095 0.4515 0.4095 0.1575 C 0.4095 0.0525 0.4725 0 0.588 0 C 0.777 0 1.428 0.0315 1.6274999 0.0315 C 1.827 0.0315 2.499 0 2.6985 0 C 2.856 0 2.9294999 0.084 2.9294999 0.252 C 2.9294999 0.3465 2.8455 0.399 2.6775 0.4095 C 2.247 0.42 2.037 0.5565 2.037 0.819 C 2.037 0.8715 2.0475 0.945 2.0685 1.05 L 3.4229999 6.4154997 L 6.048 0.22049999 C 6.111 0.0735 6.1949997 0 6.2894998 0 C 6.384 0 6.447 0.084 6.489 0.252 L 7.9484997 6.027 C 8.085 6.5625 8.379 6.7515 9.03 6.762 C 9.177 6.7725 9.2505 6.8564997 9.2505 7.0245 C 9.219 7.119 9.2085 7.1714997 9.072 7.1714997 Z "/>
</symbol>
<symbol id="gDD96380C275DE9AF15656F8D405976A0" overflow="visible">
<path d="M 7.546 2.497 C 7.656 2.552 7.711 2.629 7.711 2.75 C 7.711 2.871 7.656 2.948 7.546 3.003 L 1.232 5.995 C 1.199 6.006 1.155 6.017 1.111 6.017 C 0.935 6.017 0.847 5.929 0.847 5.742 C 0.847 5.643 0.902 5.566 1.001 5.522 L 6.875 2.75 L 1.001 -0.022 C 0.902 -0.066 0.847 -0.143 0.847 -0.242 C 0.847 -0.429 0.935 -0.517 1.111 -0.517 C 1.155 -0.517 1.199 -0.506 1.232 -0.495 Z "/>
<symbol id="gEF371FBA9DF8545F57E1B97AFE6E9F72" overflow="visible">
<path d="M 7.203 2.3834999 C 7.308 2.4359999 7.3605 2.5095 7.3605 2.625 C 7.3605 2.7405 7.308 2.814 7.203 2.8665 L 1.176 5.7225 C 1.1445 5.733 1.1025 5.7434998 1.0605 5.7434998 C 0.8925 5.7434998 0.8085 5.6595 0.8085 5.481 C 0.8085 5.3865 0.861 5.3129997 0.9555 5.271 L 6.5625 2.625 L 0.9555 -0.021 C 0.861 -0.063 0.8085 -0.1365 0.8085 -0.23099999 C 0.8085 -0.4095 0.8925 -0.4935 1.0605 -0.4935 C 1.1025 -0.4935 1.1445 -0.48299998 1.176 -0.4725 Z "/>
</symbol>
<symbol id="gB37B7CB6A35FD21388CA262EF751BF3B" overflow="visible">
<path d="M 2.739 -0.242 C 4.29 -0.242 5.06 1.012 5.06 3.52 C 5.06 5.203 4.708 6.325 4.015 6.875 C 3.6299999 7.172 3.201 7.3259997 2.75 7.3259997 C 1.199 7.3259997 0.429 6.061 0.429 3.52 C 0.429 1.496 0.968 -0.242 2.739 -0.242 Z M 3.971 5.764 C 4.048 5.379 4.081 4.675 4.081 3.652 C 4.081 2.6399999 4.037 1.892 3.96 1.408 C 3.817 0.528 3.41 0.088 2.739 0.088 C 2.486 0.088 2.233 0.187 2.002 0.374 C 1.705 0.627 1.529 1.144 1.452 1.936 C 1.419 2.211 1.408 2.783 1.408 3.652 C 1.408 4.609 1.441 5.2799997 1.496 5.643 C 1.595 6.248 1.793 6.633 2.101 6.798 C 2.343 6.93 2.552 6.996 2.739 6.996 C 3.454 6.996 3.85 6.413 3.971 5.764 Z "/>
<symbol id="g5C5EEB92102F3768E1DB77DB85972F14" overflow="visible">
<path d="M 2.6145 -0.23099999 C 4.095 -0.23099999 4.83 0.96599996 4.83 3.36 C 4.83 4.9665 4.494 6.0375 3.8325 6.5625 C 3.465 6.8459997 3.0555 6.993 2.625 6.993 C 1.1445 6.993 0.4095 5.7855 0.4095 3.36 C 0.4095 1.428 0.92399997 -0.23099999 2.6145 -0.23099999 Z M 3.7905 5.502 C 3.8639998 5.1345 3.8955 4.4625 3.8955 3.486 C 3.8955 2.52 3.8535 1.806 3.78 1.344 C 3.6434999 0.504 3.2549999 0.084 2.6145 0.084 C 2.373 0.084 2.1315 0.1785 1.911 0.357 C 1.6274999 0.5985 1.4595 1.092 1.386 1.8479999 C 1.3544999 2.1104999 1.344 2.6564999 1.344 3.486 C 1.344 4.3995 1.3755 5.04 1.428 5.3865 C 1.5225 5.9639997 1.7114999 6.3315 2.0055 6.489 C 2.2365 6.615 2.4359999 6.678 2.6145 6.678 C 3.297 6.678 3.675 6.1215 3.7905 5.502 Z "/>
</symbol>
</defs>
</svg>

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

Before After
Before After

View file

@ -20,6 +20,7 @@ pub mod md_attr {
}
attrs! {
media -> media
src -> src
alt -> alt
level -> level

View file

@ -78,7 +78,7 @@ pub struct ExternalFrameNode {
/// Alternative text for the frame
pub alt_text: String,
/// Original SVG data (needed for DOCX that still embeds images)
pub svg_data: String,
pub svg: String,
}
impl ExternalFrameNode {

View file

@ -10,11 +10,11 @@ use crate::tags::md_tag;
use crate::Result;
use crate::TypliteFeat;
use super::{inline::InlineParser, list::ListParser, table::TableParser};
use super::{list::ListParser, table::TableParser};
/// HTML to AST parser implementation
pub struct HtmlToAstParser {
pub frame_counter: usize,
pub asset_counter: usize,
pub feat: TypliteFeat,
pub list_state: Option<ListState>,
pub list_level: usize,
@ -26,7 +26,7 @@ impl HtmlToAstParser {
pub fn new(feat: TypliteFeat) -> Self {
Self {
feat,
frame_counter: 0,
asset_counter: 0,
list_level: 0,
list_state: None,
blocks: Vec::new(),
@ -43,18 +43,16 @@ impl HtmlToAstParser {
Ok(())
}
md_tag::parbreak => {
self.flush_inline_buffer();
tag::p | tag::span | tag::div => {
self.convert_children(element)?;
Ok(())
}
md_tag::heading => {
self.flush_inline_buffer();
let attrs = HeadingAttr::parse(&element.attrs)?;
self.convert_children(element)?;
self.flush_inline_buffer_as_block(|content| {
Node::heading(attrs.level as u8 + 1, content)
});
tag::strong | md_tag::strong => self.convert_strong(element),
tag::em | md_tag::emph => self.convert_emphasis(element),
tag::br => {
self.inline_buffer.push(Node::HardBreak);
Ok(())
}
@ -75,6 +73,21 @@ impl HtmlToAstParser {
Ok(())
}
md_tag::parbreak => {
self.flush_inline_buffer();
Ok(())
}
md_tag::heading => {
self.flush_inline_buffer();
let attrs = HeadingAttr::parse(&element.attrs)?;
self.convert_children(element)?;
self.flush_inline_buffer_as_block(|content| {
Node::heading(attrs.level as u8 + 1, content)
});
Ok(())
}
md_tag::raw => {
let attrs = RawAttr::parse(&element.attrs)?;
if attrs.block {
@ -100,35 +113,23 @@ impl HtmlToAstParser {
Ok(())
}
md_tag::figure => InlineParser::convert_figure(self, element),
tag::br => {
self.inline_buffer.push(Node::HardBreak);
Ok(())
}
tag::p | tag::span | tag::div => {
self.convert_children(element)?;
Ok(())
}
tag::strong | md_tag::strong => InlineParser::convert_strong(self, element),
tag::em | md_tag::emph => InlineParser::convert_emphasis(self, element),
md_tag::highlight => InlineParser::convert_highlight(self, element),
md_tag::strike => InlineParser::convert_strikethrough(self, element),
md_tag::link => InlineParser::convert_link(self, element),
md_tag::image => InlineParser::convert_image(self, element),
md_tag::figure => self.convert_figure(element),
md_tag::highlight => self.convert_highlight(element),
md_tag::strike => self.convert_strikethrough(element),
md_tag::link => self.convert_link(element),
md_tag::image => self.convert_image(element),
md_tag::linebreak => {
self.inline_buffer.push(Node::HardBreak);
Ok(())
}
md_tag::source => {
let src = self.convert_source(element);
self.inline_buffer.push(src);
Ok(())
}
md_tag::table | md_tag::grid => {
self.flush_inline_buffer();
if let Some(table) = TableParser::convert_table(self, element)? {

View file

@ -9,53 +9,46 @@ use crate::Result;
use super::core::HtmlToAstParser;
/// Inline style element parser
pub struct InlineParser;
impl InlineParser {
impl HtmlToAstParser {
/// Convert strong emphasis element
pub fn convert_strong(parser: &mut HtmlToAstParser, element: &HtmlElement) -> Result<()> {
pub fn convert_strong(&mut self, element: &HtmlElement) -> Result<()> {
let mut content = Vec::new();
parser.convert_children_into(&mut content, element)?;
parser.inline_buffer.push(Node::Strong(content));
self.convert_children_into(&mut content, element)?;
self.inline_buffer.push(Node::Strong(content));
Ok(())
}
/// Convert emphasis element
pub fn convert_emphasis(parser: &mut HtmlToAstParser, element: &HtmlElement) -> Result<()> {
pub fn convert_emphasis(&mut self, element: &HtmlElement) -> Result<()> {
let mut content = Vec::new();
parser.convert_children_into(&mut content, element)?;
parser.inline_buffer.push(Node::Emphasis(content));
self.convert_children_into(&mut content, element)?;
self.inline_buffer.push(Node::Emphasis(content));
Ok(())
}
/// Convert highlight element
pub fn convert_highlight(parser: &mut HtmlToAstParser, element: &HtmlElement) -> Result<()> {
pub fn convert_highlight(&mut self, element: &HtmlElement) -> Result<()> {
let mut content = Vec::new();
parser.convert_children_into(&mut content, element)?;
parser
.inline_buffer
self.convert_children_into(&mut content, element)?;
self.inline_buffer
.push(Node::Custom(Box::new(HighlightNode { content })));
Ok(())
}
/// Convert strikethrough element
pub fn convert_strikethrough(
parser: &mut HtmlToAstParser,
element: &HtmlElement,
) -> Result<()> {
pub fn convert_strikethrough(&mut self, element: &HtmlElement) -> Result<()> {
let mut content = Vec::new();
parser.convert_children_into(&mut content, element)?;
parser.inline_buffer.push(Node::Strikethrough(content));
self.convert_children_into(&mut content, element)?;
self.inline_buffer.push(Node::Strikethrough(content));
Ok(())
}
/// Convert link element
pub fn convert_link(parser: &mut HtmlToAstParser, element: &HtmlElement) -> Result<()> {
pub fn convert_link(&mut self, element: &HtmlElement) -> Result<()> {
let attrs = LinkAttr::parse(&element.attrs)?;
let mut content = Vec::new();
parser.convert_children_into(&mut content, element)?;
parser.inline_buffer.push(Node::Link {
self.convert_children_into(&mut content, element)?;
self.inline_buffer.push(Node::Link {
url: attrs.dest.into(),
title: None,
content,
@ -64,10 +57,10 @@ impl InlineParser {
}
/// Convert image element
pub fn convert_image(parser: &mut HtmlToAstParser, element: &HtmlElement) -> Result<()> {
pub fn convert_image(&mut self, element: &HtmlElement) -> Result<()> {
let attrs = ImageAttr::parse(&element.attrs)?;
let src = attrs.src.as_str();
parser.inline_buffer.push(Node::Image {
self.inline_buffer.push(Node::Image {
url: src.to_string(),
title: None,
alt: vec![Node::Text(attrs.alt.into())],
@ -76,8 +69,8 @@ impl InlineParser {
}
/// Convert figure element
pub fn convert_figure(parser: &mut HtmlToAstParser, element: &HtmlElement) -> Result<()> {
parser.flush_inline_buffer();
pub fn convert_figure(&mut self, element: &HtmlElement) -> Result<()> {
self.flush_inline_buffer();
// Parse figure attributes to extract caption
let attrs = FigureAttr::parse(&element.attrs)?;
@ -85,7 +78,7 @@ impl InlineParser {
// Find image and body content
let mut body_content = Vec::new();
parser.convert_children_into(&mut body_content, element)?;
self.convert_children_into(&mut body_content, element)?;
let body = Box::new(Node::Paragraph(body_content));
// Create figure node with centering
@ -93,7 +86,7 @@ impl InlineParser {
let centered_node = CenterNode::new(vec![Node::Custom(figure_node)]);
// Add the centered figure to blocks
parser.blocks.push(Node::Custom(Box::new(centered_node)));
self.blocks.push(Node::Custom(Box::new(centered_node)));
Ok(())
}

View file

@ -1,14 +1,116 @@
//! Media processing module, handles images, SVG and Frame media elements
use core::fmt;
use std::path::PathBuf;
use base64::Engine;
use cmark_writer::ast::{HtmlAttribute, HtmlElement as CmarkHtmlElement, Node};
use typst::layout::Frame;
use typst::{
html::{HtmlElement, HtmlNode},
layout::Frame,
};
use crate::common::ExternalFrameNode;
use crate::{attributes::md_attr, common::ExternalFrameNode};
use super::core::HtmlToAstParser;
enum AssetUrl {
/// Embedded Base64 SVG data
Embedded(String),
/// External file path
External(PathBuf),
}
impl fmt::Display for AssetUrl {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
AssetUrl::Embedded(data) => write!(f, "data:image/svg+xml;base64,{data}"),
// todo: correct relative path?
AssetUrl::External(path) => write!(f, "{}", path.display()),
}
}
}
impl HtmlToAstParser {
/// Convert Typst source to CommonMark node
pub fn convert_source(&mut self, element: &HtmlElement) -> Node {
if element.children.len() != 1 {
// Construct error node
return Node::HtmlElement(CmarkHtmlElement {
tag: "div".to_string(),
attributes: vec![HtmlAttribute {
name: "class".to_string(),
value: "error".to_string(),
}],
children: vec![Node::Text(format!(
"source contains not only one child: {}, whose attrs: {:?}",
element.children.len(),
element.attrs
))],
self_closing: false,
});
}
let Some(HtmlNode::Frame(frame)) = element.children.first() else {
// todo: utils to remove duplicated error construction
return Node::HtmlElement(CmarkHtmlElement {
tag: "div".to_string(),
attributes: vec![HtmlAttribute {
name: "class".to_string(),
value: "error".to_string(),
}],
children: vec![Node::Text(format!(
"source contains not a frame, but: {:?}",
element.children
))],
self_closing: false,
});
};
let svg = typst_svg::svg_frame(frame);
let frame_url = match self.create_asset_url(&svg) {
Ok(url) => url,
Err(e) => {
// Construct error node
return Node::HtmlElement(CmarkHtmlElement {
tag: "div".to_string(),
attributes: vec![HtmlAttribute {
name: "class".to_string(),
value: "error".to_string(),
}],
children: vec![Node::Text(format!("Error creating source URL: {e}"))],
self_closing: false,
});
}
};
let media = element.attrs.0.iter().find_map(|(name, data)| {
if *name == md_attr::media {
Some(data.clone())
} else {
None
}
});
Node::HtmlElement(CmarkHtmlElement {
tag: "source".to_string(),
attributes: vec![
HtmlAttribute {
name: "media".to_string(),
value: media
.map(|m| m.to_string())
.unwrap_or_else(|| "all".to_string()),
},
HtmlAttribute {
name: "srcset".to_string(),
value: frame_url.to_string(),
},
],
children: vec![],
self_closing: true,
})
}
/// Convert Typst frame to CommonMark node
pub fn convert_frame(&mut self, frame: &Frame) -> Node {
if self.feat.remove_html {
@ -17,44 +119,37 @@ impl HtmlToAstParser {
}
let svg = typst_svg::svg_frame(frame);
let data = base64::engine::general_purpose::STANDARD.encode(svg.as_bytes());
let frame_url = self.create_asset_url(&svg);
if let Some(assets_path) = &self.feat.assets_path {
let file_id = self.frame_counter;
self.frame_counter += 1;
let file_name = format!("frame_{file_id}.svg");
let file_path = assets_path.join(&file_name);
if let Err(e) = std::fs::write(&file_path, svg.as_bytes()) {
match frame_url {
Ok(url @ AssetUrl::Embedded(..)) => Self::create_embedded_frame(&url),
Ok(AssetUrl::External(file_path)) => Node::Custom(Box::new(ExternalFrameNode {
file_path,
alt_text: "typst-frame".to_string(),
svg,
})),
Err(e) => {
if self.feat.soft_error {
return Self::create_embedded_frame(&data);
let b64_data = Self::base64_url(&svg);
Self::create_embedded_frame(&b64_data)
} else {
// Construct error node
return Node::HtmlElement(CmarkHtmlElement {
Node::HtmlElement(CmarkHtmlElement {
tag: "div".to_string(),
attributes: vec![HtmlAttribute {
name: "class".to_string(),
value: "error".to_string(),
}],
children: vec![Node::Text(format!("Error writing frame to file: {}", e))],
children: vec![Node::Text(format!("Error creating frame URL: {}", e))],
self_closing: false,
});
})
}
}
return Node::Custom(Box::new(ExternalFrameNode {
file_path,
alt_text: "typst-frame".to_string(),
svg_data: data,
}));
}
// Fall back to embedded mode if no external asset path is specified
Self::create_embedded_frame(&data)
}
/// Create embedded frame node
fn create_embedded_frame(data: &str) -> Node {
fn create_embedded_frame(url: &AssetUrl) -> Node {
Node::HtmlElement(CmarkHtmlElement {
tag: "img".to_string(),
attributes: vec![
@ -64,11 +159,32 @@ impl HtmlToAstParser {
},
HtmlAttribute {
name: "src".to_string(),
value: format!("data:image/svg+xml;base64,{data}"),
value: url.to_string(),
},
],
children: vec![],
self_closing: true,
})
}
/// Convert asset to asset url
fn create_asset_url(&mut self, svg: &str) -> crate::Result<AssetUrl> {
if let Some(assets_path) = &self.feat.assets_path {
let file_id = self.asset_counter;
self.asset_counter += 1;
let file_name = format!("frame_{file_id}.svg");
let file_path = assets_path.join(&file_name);
std::fs::write(&file_path, svg.as_bytes())?;
return Ok(AssetUrl::External(file_path));
}
// Fall back to embedded mode if no external asset path is specified
Ok(Self::base64_url(svg))
}
/// Create embedded frame node
fn base64_url(data: &str) -> AssetUrl {
AssetUrl::Embedded(base64::engine::general_purpose::STANDARD.encode(data.as_bytes()))
}
}

View file

@ -29,6 +29,7 @@ pub mod md_tag {
outline_entry -> m1outentry
quote -> m1quote
table -> m1table
source -> m1source
// table_cell -> m1tablecell
grid -> m1grid
// grid_cell -> m1gridcell

View file

@ -446,7 +446,7 @@ impl DocxWriter {
.downcast_ref::<crate::common::ExternalFrameNode>(
) {
let data = base64::engine::general_purpose::STANDARD
.decode(&external_frame.svg_data)
.decode(&external_frame.svg)
.map_err(|e| format!("Failed to decode SVG data: {}", e))?;
docx = self.image_processor.process_image_data(

View file

@ -1,30 +1,30 @@
<svg class="typst-doc" viewBox="0 0 30.168111111111113 17.413" width="30.168111111111113pt" height="17.413pt" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:h5="http://www.w3.org/1999/xhtml">
<svg class="typst-doc" viewBox="0 0 28.796833333333332 7.171500000000001" width="28.796833333333332pt" height="7.171500000000001pt" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:h5="http://www.w3.org/1999/xhtml">
<g>
<g transform="translate(0 12.463)">
<g transform="translate(0 7.171500000000001)">
<g class="typst-text" transform="scale(1, -1)">
<use xlink:href="#g9C136C76572213DE6707324506E34D78" x="0" fill="#c0caf5" fill-rule="nonzero"/>
<use xlink:href="#g7936AD3000646C81EC3F86CF33FB2586" x="0" fill="#f0f6fc" fill-rule="nonzero"/>
</g>
</g>
<g transform="translate(13.054555555555556 12.463)">
<g transform="translate(12.461166666666667 7.171500000000001)">
<g class="typst-text" transform="scale(1, -1)">
<use xlink:href="#gDD96380C275DE9AF15656F8D405976A0" x="0" fill="#c0caf5" fill-rule="nonzero"/>
<use xlink:href="#gEF371FBA9DF8545F57E1B97AFE6E9F72" x="0" fill="#f0f6fc" fill-rule="nonzero"/>
</g>
</g>
<g transform="translate(24.668111111111113 12.463)">
<g transform="translate(23.546833333333332 7.171500000000001)">
<g class="typst-text" transform="scale(1, -1)">
<use xlink:href="#gB37B7CB6A35FD21388CA262EF751BF3B" x="0" fill="#c0caf5" fill-rule="nonzero"/>
<use xlink:href="#g5C5EEB92102F3768E1DB77DB85972F14" x="0" fill="#f0f6fc" fill-rule="nonzero"/>
</g>
</g>
</g>
<defs id="glyph">
<symbol id="g9C136C76572213DE6707324506E34D78" overflow="visible">
<path d="M 9.504 7.513 C 9.295 7.513 8.613 7.48 8.404 7.48 C 8.195 7.48 7.502 7.513 7.2929997 7.513 C 7.128 7.513 7.051 7.425 7.051 7.249 C 7.051 7.15 7.128 7.095 7.2929997 7.084 C 7.755 7.084 7.986 6.941 7.986 6.6549997 C 7.986 6.5889997 7.975 6.512 7.9639997 6.435 L 6.776 1.727 L 4.411 7.282 C 4.323 7.491 4.301 7.513 4.026 7.513 L 2.563 7.513 C 2.299 7.513 2.2 7.491 2.2 7.249 C 2.2 7.139 2.321 7.084 2.552 7.084 C 3.014 7.084 3.245 7.073 3.256 7.04 L 1.793 1.21 C 1.694 0.781 1.441 0.539 1.045 0.462 C 0.759 0.429 0.429 0.473 0.429 0.16499999 C 0.429 0.055 0.495 0 0.616 0 C 0.814 0 1.496 0.033 1.705 0.033 C 1.914 0.033 2.618 0 2.827 0 C 2.992 0 3.069 0.088 3.069 0.264 C 3.069 0.363 2.981 0.41799998 2.805 0.429 C 2.354 0.44 2.134 0.583 2.134 0.858 C 2.134 0.913 2.145 0.99 2.167 1.1 L 3.586 6.721 L 6.336 0.231 C 6.402 0.077 6.49 0 6.5889997 0 C 6.6879997 0 6.754 0.088 6.798 0.264 L 8.327 6.314 C 8.47 6.875 8.778 7.073 9.46 7.084 C 9.614 7.095 9.691 7.183 9.691 7.3589997 C 9.658 7.458 9.647 7.513 9.504 7.513 Z "/>
<symbol id="g7936AD3000646C81EC3F86CF33FB2586" overflow="visible">
<path d="M 9.072 7.1714997 C 8.872499 7.1714997 8.221499 7.14 8.022 7.14 C 7.8224998 7.14 7.161 7.1714997 6.9614997 7.1714997 C 6.804 7.1714997 6.7304997 7.0875 6.7304997 6.9195 C 6.7304997 6.825 6.804 6.7725 6.9614997 6.762 C 7.4024997 6.762 7.6229997 6.6254997 7.6229997 6.3525 C 7.6229997 6.2894998 7.6124997 6.216 7.6019998 6.1425 L 6.468 1.6485 L 4.2105 6.9509997 C 4.1265 7.1505 4.1054997 7.1714997 3.843 7.1714997 L 2.4465 7.1714997 C 2.1945 7.1714997 2.1 7.1505 2.1 6.9195 C 2.1 6.8145 2.2154999 6.762 2.4359999 6.762 C 2.8769999 6.762 3.0974998 6.7515 3.108 6.72 L 1.7114999 1.155 C 1.617 0.74549997 1.3755 0.5145 0.9975 0.44099998 C 0.7245 0.4095 0.4095 0.4515 0.4095 0.1575 C 0.4095 0.0525 0.4725 0 0.588 0 C 0.777 0 1.428 0.0315 1.6274999 0.0315 C 1.827 0.0315 2.499 0 2.6985 0 C 2.856 0 2.9294999 0.084 2.9294999 0.252 C 2.9294999 0.3465 2.8455 0.399 2.6775 0.4095 C 2.247 0.42 2.037 0.5565 2.037 0.819 C 2.037 0.8715 2.0475 0.945 2.0685 1.05 L 3.4229999 6.4154997 L 6.048 0.22049999 C 6.111 0.0735 6.1949997 0 6.2894998 0 C 6.384 0 6.447 0.084 6.489 0.252 L 7.9484997 6.027 C 8.085 6.5625 8.379 6.7515 9.03 6.762 C 9.177 6.7725 9.2505 6.8564997 9.2505 7.0245 C 9.219 7.119 9.2085 7.1714997 9.072 7.1714997 Z "/>
</symbol>
<symbol id="gDD96380C275DE9AF15656F8D405976A0" overflow="visible">
<path d="M 7.546 2.497 C 7.656 2.552 7.711 2.629 7.711 2.75 C 7.711 2.871 7.656 2.948 7.546 3.003 L 1.232 5.995 C 1.199 6.006 1.155 6.017 1.111 6.017 C 0.935 6.017 0.847 5.929 0.847 5.742 C 0.847 5.643 0.902 5.566 1.001 5.522 L 6.875 2.75 L 1.001 -0.022 C 0.902 -0.066 0.847 -0.143 0.847 -0.242 C 0.847 -0.429 0.935 -0.517 1.111 -0.517 C 1.155 -0.517 1.199 -0.506 1.232 -0.495 Z "/>
<symbol id="gEF371FBA9DF8545F57E1B97AFE6E9F72" overflow="visible">
<path d="M 7.203 2.3834999 C 7.308 2.4359999 7.3605 2.5095 7.3605 2.625 C 7.3605 2.7405 7.308 2.814 7.203 2.8665 L 1.176 5.7225 C 1.1445 5.733 1.1025 5.7434998 1.0605 5.7434998 C 0.8925 5.7434998 0.8085 5.6595 0.8085 5.481 C 0.8085 5.3865 0.861 5.3129997 0.9555 5.271 L 6.5625 2.625 L 0.9555 -0.021 C 0.861 -0.063 0.8085 -0.1365 0.8085 -0.23099999 C 0.8085 -0.4095 0.8925 -0.4935 1.0605 -0.4935 C 1.1025 -0.4935 1.1445 -0.48299998 1.176 -0.4725 Z "/>
</symbol>
<symbol id="gB37B7CB6A35FD21388CA262EF751BF3B" overflow="visible">
<path d="M 2.739 -0.242 C 4.29 -0.242 5.06 1.012 5.06 3.52 C 5.06 5.203 4.708 6.325 4.015 6.875 C 3.6299999 7.172 3.201 7.3259997 2.75 7.3259997 C 1.199 7.3259997 0.429 6.061 0.429 3.52 C 0.429 1.496 0.968 -0.242 2.739 -0.242 Z M 3.971 5.764 C 4.048 5.379 4.081 4.675 4.081 3.652 C 4.081 2.6399999 4.037 1.892 3.96 1.408 C 3.817 0.528 3.41 0.088 2.739 0.088 C 2.486 0.088 2.233 0.187 2.002 0.374 C 1.705 0.627 1.529 1.144 1.452 1.936 C 1.419 2.211 1.408 2.783 1.408 3.652 C 1.408 4.609 1.441 5.2799997 1.496 5.643 C 1.595 6.248 1.793 6.633 2.101 6.798 C 2.343 6.93 2.552 6.996 2.739 6.996 C 3.454 6.996 3.85 6.413 3.971 5.764 Z "/>
<symbol id="g5C5EEB92102F3768E1DB77DB85972F14" overflow="visible">
<path d="M 2.6145 -0.23099999 C 4.095 -0.23099999 4.83 0.96599996 4.83 3.36 C 4.83 4.9665 4.494 6.0375 3.8325 6.5625 C 3.465 6.8459997 3.0555 6.993 2.625 6.993 C 1.1445 6.993 0.4095 5.7855 0.4095 3.36 C 0.4095 1.428 0.92399997 -0.23099999 2.6145 -0.23099999 Z M 3.7905 5.502 C 3.8639998 5.1345 3.8955 4.4625 3.8955 3.486 C 3.8955 2.52 3.8535 1.806 3.78 1.344 C 3.6434999 0.504 3.2549999 0.084 2.6145 0.084 C 2.373 0.084 2.1315 0.1785 1.911 0.357 C 1.6274999 0.5985 1.4595 1.092 1.386 1.8479999 C 1.3544999 2.1104999 1.344 2.6564999 1.344 3.486 C 1.344 4.3995 1.3755 5.04 1.428 5.3865 C 1.5225 5.9639997 1.7114999 6.3315 2.0055 6.489 C 2.2365 6.615 2.4359999 6.678 2.6145 6.678 C 3.297 6.678 3.675 6.1215 3.7905 5.502 Z "/>
</symbol>
</defs>
</svg>

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

Before After
Before After

View file

@ -1,30 +1,30 @@
<svg class="typst-doc" viewBox="0 0 30.168111111111113 17.413" width="30.168111111111113pt" height="17.413pt" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:h5="http://www.w3.org/1999/xhtml">
<svg class="typst-doc" viewBox="0 0 28.796833333333332 7.171500000000001" width="28.796833333333332pt" height="7.171500000000001pt" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:h5="http://www.w3.org/1999/xhtml">
<g>
<g transform="translate(0 12.463)">
<g transform="translate(0 7.171500000000001)">
<g class="typst-text" transform="scale(1, -1)">
<use xlink:href="#g9C136C76572213DE6707324506E34D78" x="0" fill="#000000" fill-rule="nonzero"/>
<use xlink:href="#g7936AD3000646C81EC3F86CF33FB2586" x="0" fill="#000000" fill-rule="nonzero"/>
</g>
</g>
<g transform="translate(13.054555555555556 12.463)">
<g transform="translate(12.461166666666667 7.171500000000001)">
<g class="typst-text" transform="scale(1, -1)">
<use xlink:href="#gDD96380C275DE9AF15656F8D405976A0" x="0" fill="#000000" fill-rule="nonzero"/>
<use xlink:href="#gEF371FBA9DF8545F57E1B97AFE6E9F72" x="0" fill="#000000" fill-rule="nonzero"/>
</g>
</g>
<g transform="translate(24.668111111111113 12.463)">
<g transform="translate(23.546833333333332 7.171500000000001)">
<g class="typst-text" transform="scale(1, -1)">
<use xlink:href="#gB37B7CB6A35FD21388CA262EF751BF3B" x="0" fill="#000000" fill-rule="nonzero"/>
<use xlink:href="#g5C5EEB92102F3768E1DB77DB85972F14" x="0" fill="#000000" fill-rule="nonzero"/>
</g>
</g>
</g>
<defs id="glyph">
<symbol id="g9C136C76572213DE6707324506E34D78" overflow="visible">
<path d="M 9.504 7.513 C 9.295 7.513 8.613 7.48 8.404 7.48 C 8.195 7.48 7.502 7.513 7.2929997 7.513 C 7.128 7.513 7.051 7.425 7.051 7.249 C 7.051 7.15 7.128 7.095 7.2929997 7.084 C 7.755 7.084 7.986 6.941 7.986 6.6549997 C 7.986 6.5889997 7.975 6.512 7.9639997 6.435 L 6.776 1.727 L 4.411 7.282 C 4.323 7.491 4.301 7.513 4.026 7.513 L 2.563 7.513 C 2.299 7.513 2.2 7.491 2.2 7.249 C 2.2 7.139 2.321 7.084 2.552 7.084 C 3.014 7.084 3.245 7.073 3.256 7.04 L 1.793 1.21 C 1.694 0.781 1.441 0.539 1.045 0.462 C 0.759 0.429 0.429 0.473 0.429 0.16499999 C 0.429 0.055 0.495 0 0.616 0 C 0.814 0 1.496 0.033 1.705 0.033 C 1.914 0.033 2.618 0 2.827 0 C 2.992 0 3.069 0.088 3.069 0.264 C 3.069 0.363 2.981 0.41799998 2.805 0.429 C 2.354 0.44 2.134 0.583 2.134 0.858 C 2.134 0.913 2.145 0.99 2.167 1.1 L 3.586 6.721 L 6.336 0.231 C 6.402 0.077 6.49 0 6.5889997 0 C 6.6879997 0 6.754 0.088 6.798 0.264 L 8.327 6.314 C 8.47 6.875 8.778 7.073 9.46 7.084 C 9.614 7.095 9.691 7.183 9.691 7.3589997 C 9.658 7.458 9.647 7.513 9.504 7.513 Z "/>
<symbol id="g7936AD3000646C81EC3F86CF33FB2586" overflow="visible">
<path d="M 9.072 7.1714997 C 8.872499 7.1714997 8.221499 7.14 8.022 7.14 C 7.8224998 7.14 7.161 7.1714997 6.9614997 7.1714997 C 6.804 7.1714997 6.7304997 7.0875 6.7304997 6.9195 C 6.7304997 6.825 6.804 6.7725 6.9614997 6.762 C 7.4024997 6.762 7.6229997 6.6254997 7.6229997 6.3525 C 7.6229997 6.2894998 7.6124997 6.216 7.6019998 6.1425 L 6.468 1.6485 L 4.2105 6.9509997 C 4.1265 7.1505 4.1054997 7.1714997 3.843 7.1714997 L 2.4465 7.1714997 C 2.1945 7.1714997 2.1 7.1505 2.1 6.9195 C 2.1 6.8145 2.2154999 6.762 2.4359999 6.762 C 2.8769999 6.762 3.0974998 6.7515 3.108 6.72 L 1.7114999 1.155 C 1.617 0.74549997 1.3755 0.5145 0.9975 0.44099998 C 0.7245 0.4095 0.4095 0.4515 0.4095 0.1575 C 0.4095 0.0525 0.4725 0 0.588 0 C 0.777 0 1.428 0.0315 1.6274999 0.0315 C 1.827 0.0315 2.499 0 2.6985 0 C 2.856 0 2.9294999 0.084 2.9294999 0.252 C 2.9294999 0.3465 2.8455 0.399 2.6775 0.4095 C 2.247 0.42 2.037 0.5565 2.037 0.819 C 2.037 0.8715 2.0475 0.945 2.0685 1.05 L 3.4229999 6.4154997 L 6.048 0.22049999 C 6.111 0.0735 6.1949997 0 6.2894998 0 C 6.384 0 6.447 0.084 6.489 0.252 L 7.9484997 6.027 C 8.085 6.5625 8.379 6.7515 9.03 6.762 C 9.177 6.7725 9.2505 6.8564997 9.2505 7.0245 C 9.219 7.119 9.2085 7.1714997 9.072 7.1714997 Z "/>
</symbol>
<symbol id="gDD96380C275DE9AF15656F8D405976A0" overflow="visible">
<path d="M 7.546 2.497 C 7.656 2.552 7.711 2.629 7.711 2.75 C 7.711 2.871 7.656 2.948 7.546 3.003 L 1.232 5.995 C 1.199 6.006 1.155 6.017 1.111 6.017 C 0.935 6.017 0.847 5.929 0.847 5.742 C 0.847 5.643 0.902 5.566 1.001 5.522 L 6.875 2.75 L 1.001 -0.022 C 0.902 -0.066 0.847 -0.143 0.847 -0.242 C 0.847 -0.429 0.935 -0.517 1.111 -0.517 C 1.155 -0.517 1.199 -0.506 1.232 -0.495 Z "/>
<symbol id="gEF371FBA9DF8545F57E1B97AFE6E9F72" overflow="visible">
<path d="M 7.203 2.3834999 C 7.308 2.4359999 7.3605 2.5095 7.3605 2.625 C 7.3605 2.7405 7.308 2.814 7.203 2.8665 L 1.176 5.7225 C 1.1445 5.733 1.1025 5.7434998 1.0605 5.7434998 C 0.8925 5.7434998 0.8085 5.6595 0.8085 5.481 C 0.8085 5.3865 0.861 5.3129997 0.9555 5.271 L 6.5625 2.625 L 0.9555 -0.021 C 0.861 -0.063 0.8085 -0.1365 0.8085 -0.23099999 C 0.8085 -0.4095 0.8925 -0.4935 1.0605 -0.4935 C 1.1025 -0.4935 1.1445 -0.48299998 1.176 -0.4725 Z "/>
</symbol>
<symbol id="gB37B7CB6A35FD21388CA262EF751BF3B" overflow="visible">
<path d="M 2.739 -0.242 C 4.29 -0.242 5.06 1.012 5.06 3.52 C 5.06 5.203 4.708 6.325 4.015 6.875 C 3.6299999 7.172 3.201 7.3259997 2.75 7.3259997 C 1.199 7.3259997 0.429 6.061 0.429 3.52 C 0.429 1.496 0.968 -0.242 2.739 -0.242 Z M 3.971 5.764 C 4.048 5.379 4.081 4.675 4.081 3.652 C 4.081 2.6399999 4.037 1.892 3.96 1.408 C 3.817 0.528 3.41 0.088 2.739 0.088 C 2.486 0.088 2.233 0.187 2.002 0.374 C 1.705 0.627 1.529 1.144 1.452 1.936 C 1.419 2.211 1.408 2.783 1.408 3.652 C 1.408 4.609 1.441 5.2799997 1.496 5.643 C 1.595 6.248 1.793 6.633 2.101 6.798 C 2.343 6.93 2.552 6.996 2.739 6.996 C 3.454 6.996 3.85 6.413 3.971 5.764 Z "/>
<symbol id="g5C5EEB92102F3768E1DB77DB85972F14" overflow="visible">
<path d="M 2.6145 -0.23099999 C 4.095 -0.23099999 4.83 0.96599996 4.83 3.36 C 4.83 4.9665 4.494 6.0375 3.8325 6.5625 C 3.465 6.8459997 3.0555 6.993 2.625 6.993 C 1.1445 6.993 0.4095 5.7855 0.4095 3.36 C 0.4095 1.428 0.92399997 -0.23099999 2.6145 -0.23099999 Z M 3.7905 5.502 C 3.8639998 5.1345 3.8955 4.4625 3.8955 3.486 C 3.8955 2.52 3.8535 1.806 3.78 1.344 C 3.6434999 0.504 3.2549999 0.084 2.6145 0.084 C 2.373 0.084 2.1315 0.1785 1.911 0.357 C 1.6274999 0.5985 1.4595 1.092 1.386 1.8479999 C 1.3544999 2.1104999 1.344 2.6564999 1.344 3.486 C 1.344 4.3995 1.3755 5.04 1.428 5.3865 C 1.5225 5.9639997 1.7114999 6.3315 2.0055 6.489 C 2.2365 6.615 2.4359999 6.678 2.6145 6.678 C 3.297 6.678 3.675 6.1215 3.7905 5.502 Z "/>
</symbol>
</defs>
</svg>

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

Before After
Before After

View file

@ -42,7 +42,7 @@ If you are releasing a nightly version, please set the prerelease flag to true.
Tinymist's versions follow the [Semantic Versioning](https://semver.org/) scheme, in format of `MAJOR.MINOR.PATCH`. Besides, tinymist follows special rules for the version number:
- If a version is suffixed with `-rcN` (<img alt="typst-block" src="./assets/images/release-instruction.typ-inlined0.svg" />), e.g. `0.11.0-rc1` and `0.12.1-rc1`, it means this version is a release candidate. It is used to test publish script and E2E functionalities. These versions will not be published to the marketplace.
- If a version is suffixed with `-rcN` (<picture><source media="(prefers-color-scheme: dark)" srcset="./assets/images/release-instruction.typ-inlined0.svg" /><img alt="typst-block" src="./assets/images/release-instruction.typ-inlined1.svg" /></picture>), e.g. `0.11.0-rc1` and `0.12.1-rc1`, it means this version is a release candidate. It is used to test publish script and E2E functionalities. These versions will not be published to the marketplace.
- If the `PATCH` number is odd, e.g. `0.11.1` and `0.12.3`, it means this version is a nightly release. The nightly release will use both [tinymist](https://github.com/Myriad-Dreamin/tinymist/tree/main) and [typst](https://github.com/typst/typst/tree/main) at **main branch**. They will be published as prerelease version to the marketplace. Note that in nightly releases, we change `#sys.version` to the next minor release to help develop documents with nightly features. For example, in tinymist nightly v0.12.1 or v0.12.3, the `#sys.version` is changed to `version(0, 13, 0)`.
- Otherwise, if the `PATCH` number is even, e.g. `0.11.0` and `0.12.2`, it means this version is a regular release. The regular release will always use the recent stable version of tinymist and typst.

View file

@ -13,6 +13,7 @@
#import templates: *
#import "@preview/numbly:0.1.0": numbly
#import "@preview/zebraw:0.4.5": zebraw-init, zebraw-html
#import "theme.typ": theme-box
// Metadata
#let page-width = get-page-width()
@ -36,6 +37,7 @@
dash-color: dash-color,
code-extra-colors: code-extra-colors,
) = book-theme-from(toml("theme-style.toml"), xml: it => xml(it))
#let gh-dark-fg = rgb("#f0f6fc")
// Fonts
#let main-font = (
@ -108,6 +110,36 @@
body
}
#let equation-rules(body) = {
// equation setting
show math.equation: set text(weight: 400)
show math.equation.where(block: true): it => context if shiroa-sys-target() == "html" {
div-frame(attrs: ("style": "display: flex; justify-content: center; overflow-x: auto;"), it)
} else {
it
}
show math.equation.where(block: false): it => context if shiroa-sys-target() == "html" {
span-frame(attrs: ("style": "overflow-x: auto;"), it)
} else {
it
}
body
}
#let md-equation-rules(body) = {
// equation setting
show math.equation: it => theme-box(
tag: if it.block { "p" } else { "span" },
theme => {
set text(fill: if theme.is-dark { gh-dark-fg } else { theme.main-color })
html.frame(it)
},
)
body
}
/// The project function defines how your document looks.
/// It takes your content and some metadata and formats it.
/// Go ahead and customize it to your liking!
@ -196,17 +228,10 @@
// link setting
show link: set text(fill: dash-color)
// math setting
show math.equation: set text(weight: 400)
show math.equation.where(block: true): it => context if shiroa-sys-target() == "html" {
div-frame(attrs: ("style": "display: flex; justify-content: center; overflow-x: auto;"), it)
show: if is-md-target {
md-equation-rules
} else {
it
}
show math.equation.where(block: false): it => context if shiroa-sys-target() == "html" {
span-frame(attrs: ("style": "overflow-x: auto;"), it)
} else {
it
equation-rules
}
show: if is-md-target {

55
typ/templates/theme.typ Normal file
View file

@ -0,0 +1,55 @@
#import "@preview/shiroa:0.2.3": templates, book-sys
#import templates: *
#let is-md-target = book-sys.target == "md"
#let sys-is-html-target = book-sys.sys-is-html-target
// Theme (Colors)
#let dark-theme = book-theme-from(toml("theme-style.toml"), xml: it => xml(it), target: "web-ayu")
#let light-theme = book-theme-from(
toml("theme-style.toml"),
xml: it => xml(it),
target: if sys-is-html-target {
"web-light"
} else {
"pdf"
},
)
#let default-theme = if sys-is-html-target {
dark-theme
} else {
light-theme
}
#let theme-box(render, tag: "div", theme-tag: none) = if is-md-target {
show: html.elem.with(tag)
show: html.elem.with("picture")
html.elem(
"m1source",
attrs: (media: "(prefers-color-scheme: dark)"),
render(dark-theme),
)
render(light-theme)
} else if sys-is-html-target {
if theme-tag == none {
theme-tag = tag
}
html.elem(
tag,
attrs: (class: "code-image themed"),
{
html.elem(
theme-tag,
render(dark-theme),
attrs: (class: "dark"),
)
html.elem(
theme-tag,
render(light-theme),
attrs: (class: "light"),
)
},
)
} else {
render(default-theme)
}