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
10 changes: 9 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -542,7 +542,13 @@ jobs:
with:
cache: gradle
distribution: temurin
java-version: 26
# Two JDKs: the last listed becomes the default JAVA_HOME
# for Gradle and AGP, while 17 is exported as
# JAVA_HOME_17_X64 so the Maven consumer exercises the
# published artifact on the advertised JVM 17 floor.
java-version: |
17
26
- uses: actions/setup-node@v7
with:
node-version: 26.5.0
Expand All @@ -554,6 +560,8 @@ jobs:
- name: Install Android build dependencies
run: sdkmanager "platforms;android-36" "cmake;3.22.1" "ndk;28.2.13676358"
- name: Verify Kotlin publication consumers
env:
MARKDOWN_CORE_MAVEN_CONSUMER_JAVA_HOME: ${{ env.JAVA_HOME_17_X64 }}
run: pnpm check:kotlin-consumers

kotlin-android-test-build:
Expand Down
46 changes: 39 additions & 7 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,16 @@ on:
description: Tag release run containing the validated artifacts
required: true
type: string
central-deployment-id:
description: Central deployment id from the source run's Maven stage
required: true
type: string

permissions:
actions: read
contents: read

concurrency:
group: release-${{ github.ref }}
# Key on the effective release tag: a tag push and a manual resume for
# the same release share one lock, while resumes for different tags
# dispatched from the same branch do not collide.
group: release-${{ github.event_name == 'workflow_dispatch' && format('refs/tags/{0}', inputs.release-tag) || github.ref }}
cancel-in-progress: false

jobs:
Expand Down Expand Up @@ -262,7 +261,23 @@ jobs:
run: |
deployment=$(scripts/central-portal.sh upload build/markdown-core-maven-central.zip)
echo "deployment-id=$deployment" >>"$GITHUB_OUTPUT"
mkdir -p build/central-deployment
{
echo "deployment-id=$deployment"
echo "release-tag=$GITHUB_REF_NAME"
echo "version=$(cat VERSION)"
} >build/central-deployment/central-deployment.env
scripts/wait-central-deployment.sh "$deployment" VALIDATED
- name: Publish the deployment binding for manual resume
# Uploaded even when the VALIDATED wait above fails: a resume
# must recover the deployment this run created, and only this
# run's own record can prove which deployment that is.
if: ${{ always() }}
uses: actions/upload-artifact@v7
with:
name: release-central-deployment
path: build/central-deployment
if-no-files-found: ignore

npm-publish:
name: Publish Release - ES / npm
Expand Down Expand Up @@ -377,13 +392,31 @@ jobs:
- name: Validate the source run against the tag
# A stale or mistyped run id must not attach another version's
# artifacts to this tag: the source run must be the push-
# triggered release run of exactly this tag and commit.
# triggered release run of exactly this tag and commit, and it
# must have finished — a resume racing a still-publishing run
# would double-publish.
run: |
run_info=$(gh api "repos/$GITHUB_REPOSITORY/actions/runs/$SOURCE_RUN_ID")
test "$(jq -r '.path' <<<"$run_info")" = ".github/workflows/release.yml"
test "$(jq -r '.event' <<<"$run_info")" = "push"
test "$(jq -r '.head_branch' <<<"$run_info")" = "$RELEASE_TAG"
test "$(jq -r '.head_sha' <<<"$run_info")" = "$(git rev-parse HEAD)"
test "$(jq -r '.status' <<<"$run_info")" = "completed"
- name: Bind the Central deployment produced by the source run
# The deployment id is not an operator input: it is downloaded
# from the validated source run itself, so a resume can never
# pair this tag's artifacts with another release's Central
# deployment. The recorded tag and version are cross-checked
# against this run's checkout of the protected tag.
run: |
gh run download "$SOURCE_RUN_ID" --name release-central-deployment --dir central-deployment
deployment_id=$(sed -n 's/^deployment-id=//p' central-deployment/central-deployment.env)
bound_tag=$(sed -n 's/^release-tag=//p' central-deployment/central-deployment.env)
bound_version=$(sed -n 's/^version=//p' central-deployment/central-deployment.env)
test -n "$deployment_id"
test "$bound_tag" = "$RELEASE_TAG"
test "$bound_version" = "$(cat VERSION)"
echo "DEPLOYMENT_ID=$deployment_id" >>"$GITHUB_ENV"
- name: Download the validated release artifacts
run: |
mkdir -p release-npm release-files
Expand Down Expand Up @@ -411,7 +444,6 @@ jobs:
# idempotent here: an already-published deployment
# short-circuits, so resumes from any failure point converge.
env:
DEPLOYMENT_ID: ${{ inputs.central-deployment-id }}
MAVEN_CENTRAL_USERNAME: ${{ secrets.MAVEN_CENTRAL_USERNAME }}
MAVEN_CENTRAL_PASSWORD: ${{ secrets.MAVEN_CENTRAL_PASSWORD }}
run: |
Expand Down
4 changes: 4 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ Makefile
packages/markdown-core/tests/fixtures/
packages/markdown-core/tests/canonical-ast/

# Harness-owned state: local settings and agent worktrees live here, never
# repository sources.
.claude/

# Generated, copied, and package-manager content
packages/markdown-core/core/case_fold_switch.inc
packages/markdown-core/core/entities.inc
Expand Down
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,16 +92,16 @@ pnpm add @nouprax/es-markdown-core
```

```js
import { Document, TreeDumper, Walker } from "@nouprax/es-markdown-core";
import { Document, MarkupDumper, MarkupWalker } from "@nouprax/es-markdown-core";

const document = Document.parse("# Hello", { directives: false });
new Walker().walk(document, (event, node) => {
console.log(event, node.kind, node.scope);
new MarkupWalker().walk(document, (event, node, scope) => {
console.log(event, node.kind, scope.start.line);
});
console.log(TreeDumper.dump(document));
console.log(MarkupDumper.dump(document));
```

The package supports Node.js 20 or later and browser environments that can load
The package supports Node.js 24 or later and browser environments that can load
its WebAssembly asset. Module import completes WebAssembly initialization, so
parsing is synchronous after the import resolves. The generated TypeScript
surface is recursively readonly; JavaScript objects are not runtime-frozen.
Expand Down
8 changes: 8 additions & 0 deletions docs/specs/sessions-and-deltas.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,14 @@ successful commit does. Requesting a scope from a snapshot that was
superseded before it ever materialized is a documented programmer error
(platforms trap), as is passing a node of a different session or revision.

A caller that retains a snapshot across commits makes the contract explicit
with `materialize()` on the snapshot: it performs the same one-time
resolution immediately, so the retained value's usability no longer depends
on whether some other read happened to run while the snapshot was current.
Structural traversal never depends on materialization: the scope-free
visitor overload of `MarkupWalker` walks any retained snapshot regardless of
resolver state.

## Edits

- `edit(byteStart, byteEnd, replacement)` replaces the byte range
Expand Down
2 changes: 2 additions & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ jdk = "26"
jvm-bytecode = "17"
kotlin = "2.4.0"
kotlin-stdlib = "2.2.21"
dokka = "2.1.0"
kotlinx-coroutines = "1.10.2"
ktlintCli = "1.8.0"
ktlintPlugin = "14.2.0"
Expand All @@ -16,6 +17,7 @@ android-library = { id = "com.android.library", version.ref = "agp" }
android-kotlin-multiplatform-library = { id = "com.android.kotlin.multiplatform.library", version.ref = "agp" }
jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
kotlin-multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" }
dokka = { id = "org.jetbrains.dokka", version.ref = "dokka" }
ktlint = { id = "org.jlleitschuh.gradle.ktlint", version.ref = "ktlintPlugin" }

[libraries]
Expand Down
Loading
Loading