Markdown Lint optional core plugin and safe quick-fix actions #162

Closed
opened 2026-05-30 23:16:22 +00:00 by steve · 0 comments
Owner

Make the bundled Markdown Lint system extension optional in Core Plugins and harden markdownlint quick-fix/code-action generation so browser and Electron stay aligned and frontmatter-safe.

Problem

The markdown-lint system extension is still locked, so users cannot disable it from Core Plugins. Markdown quick-fix generation is also still duplicated between the browser worker and Electron sidecar, and both paths use markdownlint.applyFix(...) with fixInfo only. That can rewrite from the top of the file instead of the actual diagnostic line, which corrupts frontmatter-adjacent notes and makes the editor jump to the top during fix application.

Goal

Make Markdown Lint toggleable under Core Plugins, unify markdownlint issue-to-code-action behavior across browser and Electron, and add file-local ignore actions that preserve frontmatter safety.

Scope

  • Change the markdown-lint system extension from required to optional while keeping it enabled by default.
  • Move markdownlint issue mapping and code-action generation into shared host-neutral helpers under @lapis-notes/language-service/markdownlint/....
  • Replace applyFix(...) with applyFixes(..., [issue]) for markdown quick fixes.
  • Add Ignore markdownlint <RULE> on next line and Ignore markdownlint <RULE> for this file code actions.
  • Keep MD018 Lapis tag exemptions and surfaced MD018 rule ids intact.
  • Update relevant specs and regression coverage.

Non-goals

  • Vault-wide markdownlint rule-option passthrough beyond the existing disabledRules array.
  • Workspace-wide fix-all or formatter-style markdownlint commands.
  • Changing the shared CodeMirror action dispatch model beyond feeding it corrected edits.

Acceptance Criteria

  • Markdown Lint appears in Core Plugins as a normal toggleable bundled plugin.
  • Disabling the plugin removes markdown diagnostics/code actions; re-enabling restores them.
  • Browser worker and Electron sidecar share the same markdownlint issue-to-diagnostic and issue-to-code-action logic.
  • Applying a markdownlint fix in a note with YAML frontmatter preserves the frontmatter and edits only the intended line.
  • Diagnostics with a markdownlint rule code expose Fix, Ignore ... on next line, and Ignore ... for this file actions, except that next-line ignore is omitted for diagnostics inside leading YAML frontmatter.
  • MD018 tag-line exemptions from #161 still hold and still surface as MD018.

Implementation Notes

  • Keep the existing shared markdownlint config helper in packages/language-service/src/markdownlint/options.{ts,cjs} and add new shared runtime helpers beside it for issue mapping and code-action generation.
  • Export the new helper path from @lapis-notes/language-service so Electron can import it without duplicating markdownlint logic in the sidecar child.
  • Generate quick-fix edits by applying markdownlint.applyFixes(document.text, [issue]), diffing before/after into a minimal text replacement, and returning that edit through the existing language-service code-action shape.
  • Generate file-local suppressions only; do not route ignore actions through markdown-lint.disabledRules.
  • Insert file-level suppressions after leading frontmatter and before the first real content line so they apply to earlier diagnostics without corrupting YAML frontmatter.

Suggested Files or Specs To Inspect

  • packages/plugins/plugin-markdown-lint/src/index.ts
  • packages/language-service/src/workers/markdownlint.worker.ts
  • packages/desktop-electron/src-electron/language-service-sidecar-child.ts
  • packages/api/src/lib/plugin-manager.ts
  • packages/api/src/lib/components/editor/language-service/index.ts
  • packages/workspace/e2e/markdown-lint-tooltip.spec.ts
  • packages/workspace/e2e/core-plugin-settings.spec.ts
  • spec/src/20-packages/plugins/markdown-lint/index.md
  • spec/src/20-packages/language-service/index.md
  • spec/src/20-packages/workspace/index.md

Validation Commands

  • pnpm --filter @lapis-notes/language-service test -- markdownlint.test.ts
  • pnpm --filter @lapis-notes/api test -- plugin-manager.test.ts
  • pnpm --filter @lapis-notes/workspace test:e2e -- markdown-lint-tooltip.spec.ts core-plugin-settings.spec.ts
  • pnpm --filter @lapis-notes/desktop-electron test:e2e -- language-service-markdown.spec.ts
  • pnpm check:all
  • make spec-lint
  • mdbook build spec
  • pnpm test:smoke

Follow-up Tasks

Implementation Summary

Made Markdown Lint optional in Core Plugins, unified browser/native markdownlint runtime helpers, added ignore-next-line and ignore-for-file actions, hardened frontmatter-safe apply-fix behavior, and added browser regression coverage for toggleability and fix/tooltip behavior.

Make the bundled Markdown Lint system extension optional in Core Plugins and harden markdownlint quick-fix/code-action generation so browser and Electron stay aligned and frontmatter-safe. ## Problem The markdown-lint system extension is still locked, so users cannot disable it from Core Plugins. Markdown quick-fix generation is also still duplicated between the browser worker and Electron sidecar, and both paths use `markdownlint.applyFix(...)` with `fixInfo` only. That can rewrite from the top of the file instead of the actual diagnostic line, which corrupts frontmatter-adjacent notes and makes the editor jump to the top during fix application. ## Goal Make Markdown Lint toggleable under Core Plugins, unify markdownlint issue-to-code-action behavior across browser and Electron, and add file-local ignore actions that preserve frontmatter safety. ## Scope - Change the markdown-lint system extension from required to optional while keeping it enabled by default. - Move markdownlint issue mapping and code-action generation into shared host-neutral helpers under `@lapis-notes/language-service/markdownlint/...`. - Replace `applyFix(...)` with `applyFixes(..., [issue])` for markdown quick fixes. - Add `Ignore markdownlint <RULE> on next line` and `Ignore markdownlint <RULE> for this file` code actions. - Keep MD018 Lapis tag exemptions and surfaced `MD018` rule ids intact. - Update relevant specs and regression coverage. ## Non-goals - Vault-wide markdownlint rule-option passthrough beyond the existing `disabledRules` array. - Workspace-wide fix-all or formatter-style markdownlint commands. - Changing the shared CodeMirror action dispatch model beyond feeding it corrected edits. ## Acceptance Criteria - Markdown Lint appears in Core Plugins as a normal toggleable bundled plugin. - Disabling the plugin removes markdown diagnostics/code actions; re-enabling restores them. - Browser worker and Electron sidecar share the same markdownlint issue-to-diagnostic and issue-to-code-action logic. - Applying a markdownlint fix in a note with YAML frontmatter preserves the frontmatter and edits only the intended line. - Diagnostics with a markdownlint rule code expose `Fix`, `Ignore ... on next line`, and `Ignore ... for this file` actions, except that next-line ignore is omitted for diagnostics inside leading YAML frontmatter. - MD018 tag-line exemptions from #161 still hold and still surface as `MD018`. ## Implementation Notes - Keep the existing shared markdownlint config helper in `packages/language-service/src/markdownlint/options.{ts,cjs}` and add new shared runtime helpers beside it for issue mapping and code-action generation. - Export the new helper path from `@lapis-notes/language-service` so Electron can import it without duplicating markdownlint logic in the sidecar child. - Generate quick-fix edits by applying `markdownlint.applyFixes(document.text, [issue])`, diffing before/after into a minimal text replacement, and returning that edit through the existing language-service code-action shape. - Generate file-local suppressions only; do not route ignore actions through `markdown-lint.disabledRules`. - Insert file-level suppressions after leading frontmatter and before the first real content line so they apply to earlier diagnostics without corrupting YAML frontmatter. ## Suggested Files or Specs To Inspect - `packages/plugins/plugin-markdown-lint/src/index.ts` - `packages/language-service/src/workers/markdownlint.worker.ts` - `packages/desktop-electron/src-electron/language-service-sidecar-child.ts` - `packages/api/src/lib/plugin-manager.ts` - `packages/api/src/lib/components/editor/language-service/index.ts` - `packages/workspace/e2e/markdown-lint-tooltip.spec.ts` - `packages/workspace/e2e/core-plugin-settings.spec.ts` - `spec/src/20-packages/plugins/markdown-lint/index.md` - `spec/src/20-packages/language-service/index.md` - `spec/src/20-packages/workspace/index.md` ## Validation Commands - `pnpm --filter @lapis-notes/language-service test -- markdownlint.test.ts` - `pnpm --filter @lapis-notes/api test -- plugin-manager.test.ts` - `pnpm --filter @lapis-notes/workspace test:e2e -- markdown-lint-tooltip.spec.ts core-plugin-settings.spec.ts` - `pnpm --filter @lapis-notes/desktop-electron test:e2e -- language-service-markdown.spec.ts` - `pnpm check:all` - `make spec-lint` - `mdbook build spec` - `pnpm test:smoke` ## Related Issues - Follow-up to #92 — [Add markdown lint quick fixes and vault-scoped rule suppressions](../closed/92-add-markdown-lint-quick-fixes-and-vault-scoped-rule-suppressions.md) - Preserve MD018 behavior from #161 — [Exempt Lapis tag lines from markdownlint MD018](../closed/161-exempt-lapis-tag-lines-from-markdownlint-md018.md) ## Follow-up Tasks ## Implementation Summary Made Markdown Lint optional in Core Plugins, unified browser/native markdownlint runtime helpers, added ignore-next-line and ignore-for-file actions, hardened frontmatter-safe apply-fix behavior, and added browser regression coverage for toggleability and fix/tooltip behavior. <!-- backlog:task_id=TASK-MARKDOWN-LINT-OPTIONAL source_spec=spec/src/20-packages/plugins/markdown-lint/index.md related_issue=92 -->
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
lapis-notes/lapis#162
No description provided.