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
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ All notable changes to AS Notes will be documented here.

## Pending Release

- Feature: Inline Markdown editor (Typora-like syntax shadowing). Bold, italic, headings, links, images, code blocks, tables, emoji, Mermaid diagrams, and LaTeX math are rendered inline with a three-state visibility model (rendered/ghost/raw). Toggle via command palette or editor title bar eye icon. Based on markdown-inline-editor-vscode by SeardnaSchmid (MIT).
- Feature: Detects conflicting Markdown Inline Editor extensions and offers to disable them.
- Feature: Outliner mode awareness -- bullet markers and checkbox syntax always remain visible when outliner mode is active.

## [2.2.9] - 2026-03-24

- Feature: Improved default themes for static HTML publishing.
Expand Down
44 changes: 44 additions & 0 deletions LICENCE-THIRD-PARTY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Third-Party Licence Notice

The inline editor functionality in this extension is derived from
[markdown-inline-editor-vscode](https://github.com/SeardnaSchmid/markdown-inline-editor-vscode),
which is itself based on
[markdown-inline-preview-vscode](https://github.com/domdomegg/markdown-inline-preview-vscode).

Both are licensed under the MIT License. The original licence texts are
reproduced below.

---

## markdown-inline-editor-vscode

MIT License

Copyright (c) 2024 SeardnaSchmid

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

---

## markdown-inline-preview-vscode

Copyright (c) Adam Jones (domdomegg)
<https://github.com/domdomegg/markdown-inline-preview-vscode>

MIT License (same terms as above).
30 changes: 30 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,36 @@ The extension is aware of existing fence pairs: if the backticks are already bal

In outliner mode, pressing Enter on a closing `` ``` `` line that belongs to a bullet code block inserts a new bullet at the parent's indentation.

### Inline Editor (Syntax Shadowing)

AS Notes includes a built-in inline Markdown editor that renders formatting directly in the text editor, similar to Typora. Standard Markdown syntax characters (`**`, `##`, `[]()`, etc.) are replaced with their visual equivalents as you write.

**Three-state visibility:**

| State | When | What you see |
|---|---|---|
| **Rendered** | Cursor is elsewhere | Clean formatted text (syntax hidden) |
| **Ghost** | Cursor is on the line | Syntax characters at reduced opacity |
| **Raw** | Cursor is inside the construct | Full Markdown source |

**Supported constructs:**

Bold, italic, strikethrough, headings (H1-H6), inline code, links, images, blockquotes, horizontal rules, unordered/task lists, code blocks (with language labels), YAML frontmatter, GFM tables, emoji shortcodes (`:smile:` etc.), Mermaid diagrams (inline SVG), LaTeX/math (KaTeX/MathJax), GitHub mentions and issue references.

**Toggle:** Use the **AS Notes: Toggle Inline Editor** command or click the eye icon in the editor title bar. The toggle state is persisted per workspace.

**Outliner mode awareness:** When outliner mode is active, bullet markers and checkbox syntax are styled inline (bullets render as styled bullets, checkboxes render with bullet and checkbox graphic) alongside the outliner structure.

| Setting | Default | Description |
|---|---|---|
| `as-notes.inlineEditor.enabled` | `true` | Enable/disable inline rendering |
| `as-notes.inlineEditor.decorations.ghostFaintOpacity` | `0.3` | Opacity for ghost-state syntax characters |
| `as-notes.inlineEditor.links.singleClickOpen` | `false` | Open links with a single click (instead of Ctrl+Click) |

See [Settings](#settings) for the full list of inline editor settings.

> Based on [markdown-inline-editor-vscode](https://github.com/SeardnaSchmid/markdown-inline-editor-vscode) by SeardnaSchmid (MIT licence).

## AS Notes Pro Features

A **Pro licence** unlocks premium features. When a valid key is active the status bar shows **AS Notes (Pro)**.
Expand Down
78 changes: 78 additions & 0 deletions TECHNICAL.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,13 @@ This document explains the internal architecture, algorithms, and design decisio
- [Default vs active](#default-vs-active)
- [Why segments prevent decoration conflicts](#why-segments-prevent-decoration-conflicts)
- [Debug logging](#debug-logging)
- [Inline editor (syntax shadowing)](#inline-editor-syntax-shadowing)
- [Three-state visibility model](#three-state-visibility-model)
- [Architecture](#architecture)
- [Outliner mode awareness](#outliner-mode-awareness)
- [Conflict detection](#conflict-detection)
- [Settings](#settings)
- [CSS injection for heading font sizes](#css-injection-for-heading-font-sizes)
- [Click navigation](#click-navigation)
- [DocumentLinkProvider and command URIs](#documentlinkprovider-and-command-uris)
- [File resolution](#file-resolution)
Expand Down Expand Up @@ -1315,6 +1322,77 @@ Diagnostic logging is provided by `LogService` (`src/LogService.ts`), a pure Nod

---

## Inline editor (syntax shadowing)

The inline editor provides Typora-like WYSIWYG rendering of standard Markdown syntax directly in the VS Code editor. It is based on [markdown-inline-editor-vscode](https://github.com/SeardnaSchmid/markdown-inline-editor-vscode) by SeardnaSchmid (MIT licence), integrated as a full code copy in `src/inline-editor/`.

### Three-state visibility model

Each Markdown construct uses a three-state visibility model:

| State | When | Effect |
|---|---|---|
| **Rendered** | Cursor is not on the line | Syntax characters are hidden; styled output is shown (e.g. **bold** without `**`) |
| **Ghost** | Cursor is on the line but outside the construct | Syntax characters are shown at reduced opacity (configurable via `as-notes.inlineEditor.decorations.ghostFaintOpacity`) |
| **Raw** | Cursor is inside the construct (or text is selected) | Full Markdown source is shown |

The filtering logic lives in `decorator/visibility-model.ts` (`filterDecorationsForEditor`). It processes each `DecorationRange` from the parser against the current cursor/selection positions to decide which state applies.

### Architecture

| Component | File | Responsibility |
|---|---|---|
| `InlineEditorManager` | `InlineEditorManager.ts` | Lifecycle orchestration, wiring providers/commands/listeners |
| `MarkdownParser` | `parser.ts` | Remark-based AST parsing to extract `DecorationRange[]` and `ScopeRange[]` |
| `MarkdownParseCache` | `markdown-parse-cache.ts` | LRU cache (10 documents) of parse results |
| `Decorator` | `decorator.ts` | Orchestrates decoration lifecycle, applies filtered results to editor |
| `DecorationTypeRegistry` | `decorator/decoration-type-registry.ts` | Caches VS Code `TextEditorDecorationType` instances |
| Visibility model | `decorator/visibility-model.ts` | Three-state filtering logic |
| Hover providers | `image-hover-provider.ts`, `link-hover-provider.ts`, `code-block-hover-provider.ts` | Rich hover popups for images, links, code blocks |
| Link provider | `link-provider.ts` | Clickable links in rendered mode |
| Checkbox toggle | `decorator/checkbox-toggle.ts` | Click-to-toggle `[ ]`/`[x]` (two-state, complements AS Notes' three-state keyboard toggle) |

### Outliner mode awareness

When the `as-notes.outlinerMode` setting is active, bullet markers (`-`, `*`, `+`) and checkbox syntax (`- [ ]`, `- [x]`) are never hidden or ghosted by the inline editor. This is enforced in `filterDecorationsForEditor` via the `outlinerAlwaysRawTypes` set, which skips `listItem`, `checkboxUnchecked`, and `checkboxChecked` decoration types when `outlinerMode` is true.

### Conflict detection

On activation, `InlineEditorManager` checks whether the standalone Markdown Inline Editor extension (original or fork) is installed. If detected, it shows a warning with an option to disable the conflicting extension, preventing issues such as duplicate hover popups and double checkbox toggles.

### Settings

All settings are under the `as-notes.inlineEditor.*` namespace. The toggle is also available as the `AS Notes: Toggle Inline Editor` command and as an eye icon in the editor title bar (visible for Markdown files).

### CSS injection for heading font sizes

VS Code's `DecorationRenderOptions` API has no `fontSize` property. The inline editor works around this by injecting CSS via the `textDecoration` property:

```ts
textDecoration: 'none; font-size: 180%;'
```

The semicolon after `none` terminates the `text-decoration` CSS declaration, and `font-size: 180%` starts a new declaration within the same generated `<style>` rule. This is a well-known technique used by several VS Code extensions.

**VS Code fontWeight/textDecoration conflict:** When a `DecorationRenderOptions` object includes both `fontWeight` and `textDecoration`, VS Code sanitises or regenerates the CSS in a way that strips the injected properties from `textDecoration`. The font-size injection silently fails with no error. This was confirmed through systematic isolation testing (iterations 5-10 of the integration task):

| Decoration options | Font-size applied? |
|---|---|
| `{ textDecoration: 'none; font-size: 300%;' }` | Yes |
| `{ textDecoration: 'none; font-size: 250%;' }` | Yes |
| `{ textDecoration: 'none; font-size: 250%;', fontWeight: 'bold' }` | **No** |
| `{ textDecoration: 'none; font-size: 180%;', fontWeight: 'bold' }` | **No** |

The fix is to inject `font-weight` via the same CSS injection string rather than using the `fontWeight` API property:

```ts
textDecoration: `none; font-size: ${size}; font-weight: bold;`
```

This applies to `createHeadingDecoration()` in `decorations.ts`. Other decoration types that use `fontWeight` (e.g. `BoldDecorationType`, `BlockquoteDecorationType`, `ListItemDecorationType`) are unaffected because they do not also inject CSS via `textDecoration`. The generic `HeadingDecorationType()` uses `fontWeight: 'bold'` alone (no `textDecoration` injection) and is also unaffected.

---

## Click navigation

### DocumentLinkProvider and command URIs
Expand Down
1 change: 1 addition & 0 deletions docs-src/docs/Getting Started.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ Create a new `.md` file and start writing. Type `[[` anywhere to trigger [[Wikil
| Store sensitive notes | [[Encrypted Notes]] |
| Publish notes as a website | [[Publishing a Static Site]] |
| Adjust extension settings | [[Settings]] |
| Inline formatting preview | [[Inline Editor]] |

## Excluding Files from the Index

Expand Down
138 changes: 138 additions & 0 deletions docs-src/docs/Inline Editor.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
# Inline Editor

AS Notes includes a built-in inline Markdown editor that renders formatting directly in the text editor, similar to Typora. Standard Markdown syntax characters are replaced with their visual equivalents as you write, giving you a clean reading experience without switching between edit and preview modes.

## Three-State Visibility

The inline editor uses a three-state system to manage syntax visibility:

| State | When | What you see |
|---|---|---|
| **Rendered** | Cursor is on a different line | Clean formatted text with syntax hidden |
| **Ghost** | Cursor is on the same line, outside the construct | Syntax characters at reduced opacity (30% by default) |
| **Raw** | Cursor is inside the construct | Full Markdown source |

This cycle lets you read comfortably while always having access to the raw Markdown when you need to edit.

**Example with bold text:**

- **Rendered:** The word appears **bold** with no asterisks visible
- **Ghost:** Move your cursor to the same line and faint `**` markers appear around the bold word
- **Raw:** Click directly on the bold word and the full `**bold**` syntax is shown

## Supported Constructs

The inline editor renders the following Markdown constructs:

### Text Formatting

- **Bold** (`**text**`) - rendered as bold text
- *Italic* (`*text*`) - rendered as italic text
- ***Bold italic*** (`***text***`) - rendered as both
- ~~Strikethrough~~ (`~~text~~`) - rendered with a line through it
- `Inline code` (`` `code` ``) - rendered with code styling

### Headings

Headings (`# H1` through `###### H6`) are rendered at progressively larger font sizes with bold styling. The `#` markers are hidden when rendered, visible at full opacity when the cursor is on the heading line (heading markers do not use ghost-faint like other constructs).

| Level | Font size |
|---|---|
| H1 | 180% |
| H2 | 140% |
| H3 | 120% |
| H4 | 110% |
| H5 | 105% |
| H6 | 100% |

Heading colours can be customised per level in [[Settings]].

### Links and Images

- **Links** (`[text](url)`) - syntax hidden, link text shown with link colour. Hover to preview the URL. Ctrl+Click to navigate.
- **Images** (`![alt](path)`) - hover to see an image preview.

### Blockquotes and Horizontal Rules

- **Blockquotes** (`> text`) - the `>` marker is styled, text is indented
- **Horizontal rules** (`---` or `***`) - rendered as a visual separator

### Lists

- **Unordered lists** (`- item`) - the `-` marker is replaced with a styled bullet
- **Task lists** (`- [ ] item` / `- [x] item`) - rendered with a styled bullet and checkbox. Click the checkbox to toggle it.
- **Ordered lists** (`1. item`) - numbers are styled

### Code Blocks

Fenced code blocks (` ``` `) display the language label at reduced opacity when rendered. Move the cursor inside the block to see the full raw source.

### Tables

GFM pipe tables are rendered with visual grid styling. Move the cursor inside the table to see the raw pipe syntax. AS Notes' table slash commands (add/remove rows and columns) work alongside the visual rendering.

### YAML Frontmatter

Frontmatter blocks (`---` delimiters and content) are rendered at reduced opacity when the cursor is elsewhere. Move the cursor inside to see the full raw YAML.

### Emoji

Emoji shortcodes like `:smile:` or `:seedling:` are rendered as their emoji characters. The shortcode is visible in ghost/raw state.

### Mermaid Diagrams

Mermaid diagram code blocks (` ```mermaid `) are rendered as inline SVG diagrams. Hover over the code block for a preview.

### Math / LaTeX

Inline math (`$...$`) and display math (`$$...$$`) are rendered using KaTeX/MathJax. Enable or disable via the `as-notes.inlineEditor.defaultBehaviors.math` setting.

### GitHub Mentions and Issues

`@username` mentions and `#123` issue references are rendered with styled decorations. Enable or disable via the `as-notes.inlineEditor.defaultBehaviors.mentionLinks` setting.

## Toggle

Toggle the inline editor on or off using any of these methods:

- **Command Palette:** Run **AS Notes: Toggle Inline Editor** (`Ctrl+Shift+P`)
- **Editor title bar:** Click the eye icon
- **Setting:** Set `as-notes.inlineEditor.enabled` to `false` in VS Code settings

When toggled off, all inline decorations are removed and you see plain Markdown.

## Outliner Mode

When [[Settings|outliner mode]] is active, the inline editor works alongside it. Bullet markers and checkbox syntax are styled (bullets show as `bullet`, checkboxes show bullet + checkbox graphic) rather than being hidden. The three-state visibility still applies to inline formatting within bullet content (bold, italic, code, links, etc.).

## Conflict Detection

If you have the standalone [Markdown Inline Editor](https://github.com/SeardnaSchmid/markdown-inline-editor-vscode) extension installed, AS Notes will show a warning notification on activation. Running both will cause duplicate decorations and broken checkbox toggles. The notification offers two options:

- **Disable Extension** - disables the standalone extension
- **Disable Inline Editor** - disables the AS Notes inline editor, keeping the standalone extension active

## Settings

All inline editor settings are under the `as-notes.inlineEditor` namespace. See [[Settings]] for the full list.

Key settings:

| Setting | Default | Description |
|---|---|---|
| `as-notes.inlineEditor.enabled` | `true` | Master toggle |
| `as-notes.inlineEditor.decorations.ghostFaintOpacity` | `0.3` | Opacity for ghost-state syntax |
| `as-notes.inlineEditor.links.singleClickOpen` | `false` | Open links with single click |
| `as-notes.inlineEditor.defaultBehaviors.emoji` | `true` | Render emoji shortcodes |
| `as-notes.inlineEditor.defaultBehaviors.math` | `true` | Render math expressions |
| `as-notes.inlineEditor.colors.*` | *(theme)* | Override heading, link, code colours |

## Troubleshooting

**Inline editor not active:** AS Notes must be in full mode (`.asnotes/` directory exists). Check the status bar - it should show "AS Notes" not "AS Notes (passive)".

**Decorations not appearing on a file:** The inline editor only activates for Markdown files within the AS Notes root directory. Files outside the root (e.g. a `README.md` at the workspace root when `rootDirectory` is set) are not decorated.

**Performance on large files:** The inline editor uses a parse cache and incremental updates. If you notice lag on very large files (1000+ lines), toggle the inline editor off for that session.

**Heading sizes not rendering:** This is a known VS Code platform behaviour where the `fontWeight` decoration property interferes with CSS font-size injection via `textDecoration`. AS Notes works around this by injecting `font-weight` through the CSS string. If heading sizes still don't appear, please report the issue with your VS Code version.
Loading
Loading