crossnote

repository·develop·Indexed 20 days ago

https://github.com/shd101wyy/crossnote

A powerful markdown notebook tool (v0.9.31) featuring a MarkdownEngine for rendering HTML, math (MathJax/KaTeX), and diagrams (Mermaid, WaveDrom, ZenUML). It supports Obsidian-style inline note embedding, block IDs, and tag parsing, and utilizes reveal.js for presentation capabilities with Sass-based theme customization.

Tokens
18.8K
Snippets
62
Records
84
Agent score
66%

What's inside crossnote

  1. Prism.js integration in crossnote

    develop

    The project includes a bundled version of prism.js (version 0.12.9) which has been configured with all languages selected.

    Important Note for VSCode Web Extension Developers: To ensure compatibility with the VSCode web extension environment, the line _self = window in prism.js has been disabled. This prevents errors in environments where window is not globally writable in that specific manner.

  2. Use block attributes for metadata and queries

    develop

    Instead of Obsidian's field:: value syntax, Crossnote uses {...} block attributes. These provide typed key-value pairs that are more powerful for driving queries and Kanban views.

    Concept

    Block attributes are intended to replace inline metadata fields. They allow for structured data (boolean, number, string) that can be indexed by the notebook's search engine to power future query and Kanban features.

    Planned Query Syntax

    Future updates aim to support fenced code blocks for querying these attributes:

    ```query {status=todo tag=bug}
  3. Embed notes inline using `![[note]]` syntax

    develop

    Crossnote supports Obsidian-style inline note embedding. This allows you to embed the rendered content of one markdown file directly into another using the ![[note.md]] syntax.

    Key Behaviors

    • Markdown Files: Embeds the full rendered content of the referenced .md file.
    • Images: ![[image.png]] is automatically converted to standard markdown image syntax ![text](path).
    • Recursion: To prevent infinite loops, the embedding depth is limited to 3 levels.
    • Aliases: Supports alias syntax like ![[note|alias]].
    • Non-Markdown Files: Files that are not .md (e.g., PDFs) are rendered as code blocks or images rather than being dynamically embedded.
    • Configuration: Embedded content inherits the current notebook's configuration (themes, math settings, etc.).
    ![[my-note.md]]
    ![[image.png]]
    ![[note|with an alias]]
  4. Reference specific blocks using `^block-id`

    develop

    You can reference specific paragraphs, list items, or blockquotes within a note using Obsidian's block ID syntax.

    1. Assigning a Block ID

    Append ^block-id (a space followed by a caret and the ID) to the end of a non-code, non-heading line.

    This is a paragraph that I want to reference later. ^my-unique-id

    2. Referencing a Block

    Use the following syntaxes to link to or embed the specific block:

    • Link to block: [[note#heading^block-id]] or [[note^block-id]].
    • Embed block: ![[note^block-id]] or ![[note#heading^block-id]] (extracts only the referenced block).

    Limitations

    • Block IDs must be explicitly defined in the source text; they are not auto-generated by the renderer.
    • Block references within embedded content only extract the parent element (e.g., the containing <p> or <li>).
    // In source note.md
    - This is a list item. ^item-1
    
    // In another note
    ![[note#^item-1]]
  5. Configure manual dependency updates

    develop

    When updating or adding managed libraries, you must perform the following maintenance tasks to ensure the engine recognizes the new materials:

    1. Update the dependentLibraryMaterials variable in markdown-engine/index.ts (or markdown-engine.ts).
    2. For katex, ensure only the CSS and font files are included.
    3. For vega-lite, apply the following manual patches to the minified file:
      • Replace structuredClone with globalThis.structuredClone.
      • Replace require("vega") with require("../vega/vega.min.js").
  6. Create a custom reveal.js theme

    develop

    To create a new theme, duplicate an existing .scss file from the /css/theme/source directory.

    Each theme file must follow this specific four-step structure to ensure variables are correctly applied to the template:

    1. Include mixins: Import /css/theme/template/mixins.scss for shared utility functions.
    2. Include settings: Import /css/theme/template/settings.scss to declare the custom variables required by the template.
    3. Override: Define your custom styles here. You can either override the variables declared in step 2 or add custom CSS selectors and styles.
    4. Include template: Import /css/theme/template/theme.scss. This template file uses the variables defined in the previous steps to generate the final CSS output.

    To compile your new theme from Sass to CSS, run the following command in the reveal.js environment: npm run build -- css-themes

    npm run build -- css-themes
  7. Use Wikilinks and Block References

    develop

    Crossnote supports Obsidian-style wikilinks for embedding content:

    Use ![[link]] to embed content.

    • Images: Extensions like .png, .jpg, .svg, etc., are converted to standard ![alt](url) markdown.
    • Other files: Converted to a <wikilink-embed> custom element with data-wikilink-embed-path and data-wikilink-embed-text attributes.

    Block References

    • Heading References: Use #HeadingName to transclude a specific section. The engine resolves the heading (case-insensitively) and includes the heading and all its sub-sections until the next heading of the same or higher level.
    • Block IDs: Use ^block-id at the end of a line to create a unique identifier. You can then reference this specific block using #^block-id. The engine will emit only the contiguous paragraph containing that marker.
  8. Run and modify code chunks

    develop

    The engine supports executing code blocks and optionally modifying the source file to include the output.

    Execution Flow:

    1. Code chunks are identified during the Markdown transformation phase.
    2. If runAllCodeChunks is passed to parseMD, the engine executes all chunks and then re-parses the Markdown.
    3. Source Modification: The engine can automatically insert the execution result back into the .md file using specific comment markers:
      • <!-- code_chunk_output -->
      • <!-- /code_chunk_output -->

    This allows for a 'literate programming' workflow where the Markdown file itself stores the results of the code execution.

  9. How front-matter rendering options work

    develop

    The frontMatterRenderingOption in the notebook configuration determines how the YAML front-matter block is displayed in the rendered output:

    • Hide (n): The front-matter is completely removed from the rendered content (Default behavior).
    • Table (t): The front-matter is converted into an HTML <table> and displayed at the top of the document.
    • Code Block (c): The front-matter is converted into a YAML fenced code block (e.g., ```yaml ... ```).
    • Pandoc Mode: If the markdownParser is set to pandoc, the front-matter is preserved as-is for the Pandoc engine to process.
  10. Enable Tag Syntax for #tags

    develop

    If notebook.config.enableTagSyntax is enabled and the parser is not markdown-it, Crossnote will transform #tag-name into a clickable HTML anchor: <a class="tag" data-tag="tagName" href="tag://tagName">#tagName</a>.

    To avoid false positives, the engine skips tags found inside:

    • {...} block-attribute spans
    • [...] link/image text spans
    • (...) link/image URL spans
  11. Configure and use Tag parsing (`#tag`)

    develop

    Crossnote supports Obsidian-style tag parsing. Tags are identified by the # prefix and can include nested structures using forward slashes.

    Usage

    • Basic Tag: #tag-name
    • Nested Tag: #parent/child

    Rules

    • Valid Characters: [0-9A-Za-z_-/].
    • Exclusions: Tags are not matched inside code blocks, inline code, URL fragments (/#), HTML entities (&#), or query parameters (?).
    • Validation: A tag must contain at least one letter or underscore (numbers-only like #123 are not treated as tags).
    • Line Start: A # at the start of a line followed by a non-space character is treated as a tag rather than a heading.

    Configuration

    Tags can be enabled or disabled in the NotebookConfig using the enableTagSyntax boolean flag (defaults to true).

    // NotebookConfig example
    {
      enableTagSyntax: true
    }