Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/release-smoke.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ jobs:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Event-supplied values go through env, never interpolated into the
# shell body (workflow-injection safety).
INPUT_TAG: ${{ github.event.inputs.tag }}
INPUT_TAG: ${{ github.event.inputs.tag }} # input-empty-ok: empty on the release event; the step falls back to the release tag, then the latest release, and rejects anything not v*
RELEASE_TAG: ${{ github.event.release.tag_name }}
run: |
TAG="${INPUT_TAG:-$RELEASE_TAG}"
Expand Down Expand Up @@ -236,7 +236,7 @@ jobs:
GH_REPO: ${{ github.repository }}
# Event-supplied values go through env, never interpolated into the
# shell body (workflow-injection safety).
INPUT_TAG: ${{ github.event.inputs.tag }}
INPUT_TAG: ${{ github.event.inputs.tag }} # input-empty-ok: empty on the release event; the step falls back to the release tag, then the latest release, and rejects anything not v*
RELEASE_TAG: ${{ github.event.release.tag_name }}
run: |
TAG="${INPUT_TAG:-$RELEASE_TAG}"
Expand Down
5 changes: 4 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,12 @@ jobs:

- name: Get version
id: get-version
env:
# Through env, never pasted into the shell body (workflow-injection
# safety, and check-workflow-input-fallbacks.test.mjs).
INPUT_VERSION: ${{ github.event.inputs.version }} # input-empty-ok: empty on a tag push, where it is not read; a dispatch rejects anything not vX.Y.Z below
run: |
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
INPUT_VERSION="${{ github.event.inputs.version }}"
# Strict format: vX.Y.Z (optionally with -prerelease or +build).
# Manual-dispatch typos otherwise create bogus releases that pass
# the rest of the pipeline (semver validator on latest.json runs
Expand Down
16 changes: 13 additions & 3 deletions .github/workflows/soak.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ on:
description: "fast-check runs for the editing fuzz"
default: "500"
fuzz_seed:
description: "fast-check seed (empty = keep CI default)"
description: "fast-check seed (empty = the CI default, 20260805)"
default: ""

permissions:
Expand All @@ -47,7 +47,10 @@ jobs:
include:
- name: fuzz
label: Deep editing-op fuzz (scaled)
command: pnpm vitest run src/test/editingFuzz.test.ts
# verbose: the test NAME carries the runs and seed, and the default
# reporter prints no names for a passing file, so a green log
# would not say which seed actually ran.
command: pnpm vitest run src/test/editingFuzz.test.ts --reporter=verbose
- name: pathological
label: Full-size pathological inputs (killable child)
command: pnpm vitest run src/utils/markdownPipeline/__tests__/pathological/
Expand All @@ -69,8 +72,15 @@ jobs:
- name: ${{ matrix.label }}
env:
# Only the fuzz reads these; the others ignore them.
#
# `inputs.*` is the EMPTY STRING on a scheduled run, so every input
# needs its fallback here. FUZZ_SEED had none, and the test turned ""
# into seed 0: the weekly soak never ran its documented seed, which
# finds three editor bugs seed 0 does not (#1407). The test now
# refuses a non-integer, and check-workflow-input-fallbacks.test.mjs
# refuses an input without a fallback.
FUZZ_RUNS: ${{ inputs.fuzz_runs || '500' }}
FUZZ_SEED: ${{ inputs.fuzz_seed }}
FUZZ_SEED: ${{ inputs.fuzz_seed || '20260805' }}
PATHOLOGICAL_SCALE: "8"
run: ${{ matrix.command }}

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/update-homebrew.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ jobs:
runs-on: ubuntu-latest
timeout-minutes: 25
env:
VERSION: ${{ github.event.inputs.version }}
VERSION: ${{ github.event.inputs.version }} # input-empty-ok: required dispatch input; the first step rejects anything not X.Y.Z
REPO: xiaolai/vmark
steps:
- name: Validate version input
Expand Down
47 changes: 47 additions & 0 deletions patches/mdast-util-to-markdown@2.1.2.patch
Original file line number Diff line number Diff line change
@@ -1,3 +1,50 @@
diff --git a/lib/util/container-phrasing.js b/lib/util/container-phrasing.js
index 3b4dc46bcab677d1a86c0ca3cc0d11e876e7e81b..7b42522d79ac84ee7ef58c12345fac67a8cd6c16 100644
--- a/lib/util/container-phrasing.js
+++ b/lib/util/container-phrasing.js
@@ -88,9 +88,18 @@ export function containerPhrasing(parent, state, info) {
// If we had to encode the first character after the previous node and it’s
// still the same character,
// encode it.
+ //
+ // VMark patch (#1407 soak): encode the whole CODE POINT, not one UTF-16
+ // code unit. Encoding only the high surrogate of an astral character (an
+ // emoji, most CJK Extension B) emits `�` plus a raw low surrogate,
+ // which decodes to U+FFFD: the character is destroyed. Repairing that
+ // afterwards in the string is too late, because the attention handler
+ // beside it has already decided its flanking against the raw surrogate.
if (encodeAfter && encodeAfter === value.slice(0, 1)) {
+ const codePoint = /** @type {number} */ (value.codePointAt(0))
value =
- encodeCharacterReference(encodeAfter.charCodeAt(0)) + value.slice(1)
+ encodeCharacterReference(codePoint) +
+ value.slice(codePoint > 0xffff ? 2 : 1)
}

const encodingInfo = state.attentionEncodeSurroundingInfo
@@ -106,9 +115,20 @@ export function containerPhrasing(parent, state, info) {
encodingInfo.before &&
before === results[results.length - 1].slice(-1)
) {
+ // VMark patch (#1407 soak): the whole code point, as above — here the
+ // raw half left behind would be the high surrogate.
+ const previous = results[results.length - 1]
+ const low = previous.charCodeAt(previous.length - 1)
+ const high = previous.charCodeAt(previous.length - 2)
+ const width =
+ low >= 0xdc00 && low <= 0xdfff && high >= 0xd800 && high <= 0xdbff
+ ? 2
+ : 1
results[results.length - 1] =
- results[results.length - 1].slice(0, -1) +
- encodeCharacterReference(before.charCodeAt(0))
+ previous.slice(0, -width) +
+ encodeCharacterReference(
+ /** @type {number} */ (previous.codePointAt(previous.length - width))
+ )
}

if (encodingInfo.after) encodeAfter = after
diff --git a/lib/util/safe.js b/lib/util/safe.js
index 456fe215ae3d032ffaea4590f0d097bcb9195619..10f82c99cff8123142f230c087e6d09742f2b313 100644
--- a/lib/util/safe.js
Expand Down
20 changes: 10 additions & 10 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading