Hamen Notes — compiler 1.0.0
Notes mode is for writing quickly, then adding emphasis, relationships, and working without designing an entire document first. It is part of the stable Hamen Markup 1.0 source contract. Existing .hmk documents retain their syntax.
Start writing
From the project directory:
.venv/bin/hmk edit examples/learning-notes.hmn --root .
Open the printed local address. For a new note, use hmk edit my-notes.hmn. The file is created when you press Save. The editor runs locally and does not send notes to a remote service.
.hmn files enable notes mode automatically. In a .hmk file, put @Notes() at the top. The editor uses notes mode by default; hmk edit document.hmk --document retains strict document parsing. The Python API also accepts notes=True.
# Newton's second law
A force changes an object's ==acceleration==.
The relationship is $F = m*a$.
- More force produces more acceleration.
- More mass requires more force.
/q What happens when the net force is zero?
No document wrapper, page configuration, or explicit paragraphs are required. Consecutive prose lines form one paragraph; a blank line starts another. # through ###### create headings. -, +, and 1. create lists, including indented sublists. Use // for a comment in notes mode. In ordinary .hmk documents, # remains a comment.
The full component syntax remains available. Notes default to a continuous page on screen. PDF output is paginated; configure it with @Page(size: A4, margin: 20mm).
1. Marks that compose
| Short form | Component | Result |
|---|---|---|
==text== |
@Highlight[text] |
Highlight |
__text__ |
@Underline[text] |
Underline |
[[text]] |
@Circle[text] |
Circled text |
{{text}} |
@Box[text] |
Boxed text |
~~text~~ |
@Strike[text] |
Strike through |
**text** |
@Strong[text] |
Bold |
*text* |
@Emphasis[text] |
Italics |
| — | @Bracket[text] |
A bracket under a phrase |
Marks work inside words and headings: # H[[text]]ey. The same inline parser handles ordinary prose, component bodies, visible titles, labels, recall prompts, cloze hints, and derivation explanations. Custom component parameters and string @Value output participate in notes syntax.
Marks can nest: ==remember the [[exception]]==. Component forms accept ordinary style properties, for example @Highlight(background: #ddecb8)[a different colour]. The new mark components also accept positional text: @Highlight("important").
Use a backslash before shorthand punctuation to write it literally. Raw code, math, chemistry, and relationship expressions stay literal. In a derivation, the math stays raw while the explanation after | accepts marks. Mark delimiters must nest completely; crossing ranges are not supported.
Marks cover text on one line. Block containers hold headings, paragraphs, lists, diagrams, and other blocks; placing a block inside an inline mark reports a source diagnostic. Use @Panel or :::box for that content.
Select text and use the editor toolbar to apply a mark without entering its syntax. The command palette is available with Command/Ctrl+K.
2. Placement and anchored annotations
Give meaningful content an explicit ID, then place related content beside, above, below, or in its margin:
@P(id: law): Force changes motion.
@Example(beside: law): Pushing an empty cart.
@Important(below: law): Always identify the system first.
@Annotate(law, placement: Margin):
A reminder attached to this exact passage.
beside, above, below, and marginOf are available on components. Use one relationship per component. Annotate supports Margin, Beside, Above, and Below, with an optional connector: false.
For an exact phrase or term, use @Span(id: acceleration)[acceleration] inside a paragraph. The annotation aligns with the containing paragraph; its connector points to the identified phrase. The editor's Anchor button inserts a unique ID around selected text. Insert Annotation uses the most recently created anchor.
Side notes share a rail and stack without overlapping. Narrow screens place them beneath the main content. Source IDs stay the same when sections move. Missing targets and cyclic relationships produce diagnostics.
3. Personal shorthand
@Shorthand("why", "@Question: {text}")
@Shorthand("result", "@Important: {text}")
/why Why is acceleration constant?
/result The force must be constant too.
Built-in shorthand: /def, /ex, /q, /important, /scratch, /recall, /box, /aside, /tip, /warning, /summary, /fold, /quote, and /task. Press Tab after the shorthand and optional text to expand it into editable source. Compilation also expands unexpanded shorthand. Declarations are top-level and apply to the note; expansions are not recursively interpreted as more shorthand. {text} inserts the rest of the line verbatim, so use a prose slot when the text can contain quotes. Multiline expansions use \n in the quoted definition.
4. Relationship diagrams
@Relations:
Evidence -> Model -> Prediction
Model -> Assumptions
Prediction -[test]-> Evidence
Repeated labels refer to the same node. Chains, branches, cycles, and labeled arrows are supported. Labels can be quoted. Layout and connector paths are generated automatically. The current limit is 100 nodes and 200 edges per diagram; node labels are limited to 160 characters. Larger diagrams are readable through horizontal scrolling on small screens. Use the original Diagram, Node, and Edge components for manual positioning.
5. Connections between content
@P(id: observation): The cart accelerates.
@Important(id: conclusion): A net force acts on it.
@Connect(observation, conclusion, label: "Explained by", kind: Arrow)
Connect supports Arrow, Line, and Bracket. It can connect identified prose, equations, diagrams, or sections. Connectors redraw when layout changes and route through the outer margin between separate sections. A visible pair of links preserves the relationship for navigation and accessibility. Arrows are drawn within a screen document or individual printed page; connections across printed pages retain links rather than drawing across page boundaries.
6. Keyboard mathematics
Write $...$ inside prose, or use @Calc("...", display: true) / a raw @Calc: block.
Speed is $v = d/t$.
The distance is $sqrt(x^2 + y^2)$.
A small matrix is $[1, 0; 0, 1]$.
Supported notation includes numbers, variables, implicit multiplication (2x), + - * /, powers and subscripts, comparisons, parentheses, Greek names, sqrt, abs, sin, cos, tan, log, ln, exp, vec, and cancel. Matrix columns use commas; rows use semicolons. Division produces a fraction. Power is right-associative. A unary minus follows the usual convention: -x^2 means -(x^2).
This is a bounded notation parser, not a symbolic algebra engine. It formats working but does not verify that a derivation is mathematically correct. Full TeX remains available through Math and Equation.
7. Working and derivations
@Derivation(reveal: true):
2*x + 4 = 10 | subtract 4 from both sides
2*x = 6 | divide by 2
x = 3 | check by substitution
Separate an expression and its explanation with |. Equality signs align across steps. reveal: true adds Next step and Show all controls on the web. PDF output includes every step.
For individually identified or styled steps:
@Steps:
@Step("2*x = 6", "Divide by two", id: divide)
@Step("x = 3", "The result", id: result)
@Connect(divide, result, label: "Substitute", kind: Arrow)
Use cancel(...) inside keyboard math to show cancellation.
8. Structures for thinking
Important, Question, Example, Alternative, and Uncertain accept ordinary text or nested content. Optional positional titles replace their default labels. Definition remains available, with /def providing a short form.
@Compare:
@Side("First approach"):
Its main property.
@Side("Second approach"):
How it differs.
@ProsCons:
@Pro: A benefit.
@Con: A drawback.
@CauseEffect:
@Cause: What changed.
@Effect: What followed.
@Question: What remains unclear?
@Answer: My current understanding.
These are flexible containers. They do not require every side or answer to be filled before a note can render.
Boxes, asides, and foldable detail
Use fences to wrap blocks without indenting their contents. Titles are optional and accept marks:
:::box ==The main idea==
# H[[text]]ey
A paragraph with an {{inline box}} and $x^2$.
:::aside A side thought
- A supporting point.
- [ ] Something to check.
:::
:::fold More detail
A longer explanation, hidden until opened.
:::
:::
Each ::: closes the most recent opening fence. Fences support box, aside, tip, warning, summary, fold, quote, important, example, question, scratch, compare, side, and recall. They nest with each other and with indented components. Raw code inside a fence still needs its normal indentation.
Equivalent component forms include @Panel("Title"): (also @Box:), @Aside:, @Tip:, @Warning:, @Summary:, and @Fold("More detail"):. @Box[text] and {{text}} box an inline phrase. @Fold(open: true) starts expanded. PDF exports show all disclosure content.
Select paragraphs and click Box block or Aside to wrap them. The Insert menu and command palette offer the other blocks. Box on a multiline selection also creates a block. Moving or grouping a fenced block preserves all of its nested content and IDs.
Checklists and quotations
- [ ] Explain the idea without looking.
- [x] Work through the example.
> A thought worth keeping.
Tasks accept marks, math, and nested content. @Task(checked: false): ... is the explicit form. Checking a direct task in the editor updates its source and participates in undo; Save persists it. Tasks generated by shorthand, templates, or imported notes must be changed in their original definition. Standalone HTML checkbox changes are temporary.
9. Personal visual styles
@NoteStyle(roles: {
Important: {background: #f5eab7},
Question: {color: #41688c},
Example: {borderColor: #748d5a},
Paragraph: {family: "HMK Sans", size: 12pt}
})
Declare component defaults once, before their use. Individual component properties override defaults. Existing Theme, TextStyle, Def, and local font declarations also work. Styles use the same validated properties as regular components.
10. Scratch work and uncertainty
@Scratch(id: attempt, status: Tentative):
Try a different approach here.
@Alternative: An explanation worth comparing.
@Uncertain: Check this assumption later.
Scratch work is intentionally valid in normal output; it is different from the older Todo component, which prevents a production build. Use Promote scratch to main notes in the editor to turn a Scratch section into a Section while keeping its content and ID.
11. Recall in the original note
@Recall("What is the key assumption?"):
The force remains constant.
The answer is @Cloze("Try to remember")[constant acceleration].
Recall is a keyboard-accessible disclosure. Cloze hides a phrase until revealed and can hide it again. Worked steps can reveal incrementally. PDF exports always include answers and all working, with no interactive controls required. This release does not schedule spaced repetition or track learning scores.
12. Editing without losing the thought
The local editor provides:
- Write, Split, and Read views; double-click rendered components to return to their source line.
- A preview updated after typing pauses briefly. Incomplete components show diagnostics and recoverable source; the previous preview remains available if recovery fails.
- Toolbar marks, structure insertion, custom shorthand with Tab, and a searchable command palette.
- Move section up/down with Option/Alt+Up/Down; Group, Ungroup, Split paragraph, and Combine commands.
- Undo and redo for typing and editor commands. IDs and connections remain in the source during rearrangement.
- Command/Ctrl+S to save the actual file. A separate local browser draft supports recovery after reload; it is not a substitute for saving.
- Detection of an externally changed file before saving. Reload keeps an unsaved draft available to restore; Download preserves a separate source copy.
Grouping wraps existing source in @Block:. Ungroup removes a plain Block wrapper; it will not discard a named block's identity. Split is for ordinary prose. Editor operations never rewrite reference IDs.
The local server serves only editor files, compiler assets, and resources referenced by compiled notes. Writes require the session token and a matching file revision. It binds to loopback, not a public network interface. Close the terminal process when finished.
Export and portability
hmk check examples/learning-notes.hmn --root .
hmk build examples/learning-notes.hmn --root . -o output/learning-notes.html
hmk build examples/learning-notes.hmn --root . -o output/learning-notes.pdf
hmk pack examples/learning-notes.hmn --root . -o output/learning-notes.hmkp
HTML output still requires the adjacent .assets directory. The source remains plain text; .hmkp bundles include the original note and referenced local resources. The editor is bundled in the Python package and needs no Node build step.
Runnable specimens are examples/learning-notes.hmn and examples/composable-notes.hmn. The cross-feature matrix is in tests/test_note_composition.py. Language and persistence tests are in tests/test_notes.py; browser editing, study behavior, responsive layout, and PDF tests are in tests/test_notes_browser.py.