anthus-markus 0.5.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. anthus_markus-0.5.1/.gitignore +23 -0
  2. anthus_markus-0.5.1/CHANGELOG.md +9 -0
  3. anthus_markus-0.5.1/LICENSE +21 -0
  4. anthus_markus-0.5.1/PKG-INFO +135 -0
  5. anthus_markus-0.5.1/README.md +96 -0
  6. anthus_markus-0.5.1/behave.ini +6 -0
  7. anthus_markus-0.5.1/docs/LANGUAGE.md +80 -0
  8. anthus_markus-0.5.1/examples/getting-started.md +51 -0
  9. anthus_markus-0.5.1/features/cli.feature +81 -0
  10. anthus_markus-0.5.1/features/directives.feature +335 -0
  11. anthus_markus-0.5.1/features/document-ir.feature +167 -0
  12. anthus_markus-0.5.1/features/environment.py +33 -0
  13. anthus_markus-0.5.1/features/front_matter.feature +189 -0
  14. anthus_markus-0.5.1/features/gfm.feature +63 -0
  15. anthus_markus-0.5.1/features/site.feature +96 -0
  16. anthus_markus-0.5.1/features/steps/markus_steps.py +394 -0
  17. anthus_markus-0.5.1/features/themes.feature +1127 -0
  18. anthus_markus-0.5.1/features/validation.feature +167 -0
  19. anthus_markus-0.5.1/pyproject.toml +98 -0
  20. anthus_markus-0.5.1/site/assets/pipeline.svg +23 -0
  21. anthus_markus-0.5.1/site/gallery.md +189 -0
  22. anthus_markus-0.5.1/site/gfm.md +56 -0
  23. anthus_markus-0.5.1/site/index.md +202 -0
  24. anthus_markus-0.5.1/site/site.css +293 -0
  25. anthus_markus-0.5.1/src/markusmd/__init__.py +34 -0
  26. anthus_markus-0.5.1/src/markusmd/__main__.py +6 -0
  27. anthus_markus-0.5.1/src/markusmd/_frontmatter_yaml.py +98 -0
  28. anthus_markus-0.5.1/src/markusmd/api.py +112 -0
  29. anthus_markus-0.5.1/src/markusmd/ast.py +245 -0
  30. anthus_markus-0.5.1/src/markusmd/attributes.py +95 -0
  31. anthus_markus-0.5.1/src/markusmd/blocks.py +608 -0
  32. anthus_markus-0.5.1/src/markusmd/cli.py +149 -0
  33. anthus_markus-0.5.1/src/markusmd/errors.py +33 -0
  34. anthus_markus-0.5.1/src/markusmd/parse.py +258 -0
  35. anthus_markus-0.5.1/src/markusmd/preview.py +61 -0
  36. anthus_markus-0.5.1/src/markusmd/py.typed +0 -0
  37. anthus_markus-0.5.1/src/markusmd/registry.py +724 -0
  38. anthus_markus-0.5.1/src/markusmd/render.py +158 -0
  39. anthus_markus-0.5.1/src/markusmd/sitebuild.py +392 -0
  40. anthus_markus-0.5.1/src/markusmd/static/markus.css +1122 -0
  41. anthus_markus-0.5.1/src/markusmd/static/playground.html +138 -0
  42. anthus_markus-0.5.1/src/markusmd/static/site.css +293 -0
  43. anthus_markus-0.5.1/src/markusmd/static/themes/catppuccin-latte.css +25 -0
  44. anthus_markus-0.5.1/src/markusmd/static/themes/catppuccin.css +25 -0
  45. anthus_markus-0.5.1/src/markusmd/static/themes/ethereal.css +25 -0
  46. anthus_markus-0.5.1/src/markusmd/static/themes/everforest.css +25 -0
  47. anthus_markus-0.5.1/src/markusmd/static/themes/flexoki-light.css +25 -0
  48. anthus_markus-0.5.1/src/markusmd/static/themes/gruvbox.css +25 -0
  49. anthus_markus-0.5.1/src/markusmd/static/themes/hackerman.css +25 -0
  50. anthus_markus-0.5.1/src/markusmd/static/themes/kanagawa.css +25 -0
  51. anthus_markus-0.5.1/src/markusmd/static/themes/last-horizon.css +25 -0
  52. anthus_markus-0.5.1/src/markusmd/static/themes/lumon.css +25 -0
  53. anthus_markus-0.5.1/src/markusmd/static/themes/lupine.css +25 -0
  54. anthus_markus-0.5.1/src/markusmd/static/themes/matte-black.css +25 -0
  55. anthus_markus-0.5.1/src/markusmd/static/themes/miasma.css +25 -0
  56. anthus_markus-0.5.1/src/markusmd/static/themes/nord.css +25 -0
  57. anthus_markus-0.5.1/src/markusmd/static/themes/osaka-jade.css +25 -0
  58. anthus_markus-0.5.1/src/markusmd/static/themes/retro-82.css +25 -0
  59. anthus_markus-0.5.1/src/markusmd/static/themes/ristretto.css +25 -0
  60. anthus_markus-0.5.1/src/markusmd/static/themes/rose-pine.css +25 -0
  61. anthus_markus-0.5.1/src/markusmd/static/themes/solitude.css +25 -0
  62. anthus_markus-0.5.1/src/markusmd/static/themes/tokyo-night.css +25 -0
  63. anthus_markus-0.5.1/src/markusmd/static/themes/vantablack.css +25 -0
  64. anthus_markus-0.5.1/src/markusmd/static/themes/white.css +25 -0
  65. anthus_markus-0.5.1/src/markusmd/themes.py +42 -0
@@ -0,0 +1,23 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ *$py.class
4
+ *.egg-info/
5
+ .eggs/
6
+ dist/
7
+ build/
8
+ .venv/
9
+ venv/
10
+ .env
11
+ .python-version
12
+ .pytest_cache/
13
+ .ruff_cache/
14
+ .mypy_cache/
15
+ .coverage
16
+ htmlcov/
17
+ pretty.output
18
+ _site/
19
+ site/_build/
20
+ *.html
21
+ !src/markusmd/static/*.html
22
+ project/.overlay/
23
+ project/.cache/
@@ -0,0 +1,9 @@
1
+ # Changelog
2
+
3
+ ## 0.1.0
4
+
5
+ - Initial Markus language: GFM baseline, YAML front matter, and a small
6
+ semantic directive registry.
7
+ - HTML renderer with bundled CSS.
8
+ - `markus` CLI: `convert`, `ast`, `validate`, `preview`, `site`.
9
+ - GitHub Pages demo generated from Markus sources in `site/`.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Anthus AI Solutions
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,135 @@
1
+ Metadata-Version: 2.5
2
+ Name: anthus-markus
3
+ Version: 0.5.1
4
+ Summary: Markus: GitHub-flavored Markdown with semantic layout directives.
5
+ Project-URL: Homepage, https://github.com/AnthusAI/Markus
6
+ Project-URL: Documentation, https://github.com/AnthusAI/Markus#readme
7
+ Project-URL: Repository, https://github.com/AnthusAI/Markus
8
+ Project-URL: Issues, https://github.com/AnthusAI/Markus/issues
9
+ Author-email: Anthus AI Solutions <info@anthus.ai>
10
+ License-Expression: MIT
11
+ License-File: LICENSE
12
+ Keywords: commonmark,directives,gfm,layout,markdown,publishing
13
+ Classifier: Development Status :: 3 - Alpha
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Operating System :: OS Independent
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Programming Language :: Python :: 3.13
22
+ Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
23
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
24
+ Classifier: Topic :: Text Processing :: Markup
25
+ Classifier: Topic :: Text Processing :: Markup :: Markdown
26
+ Classifier: Typing :: Typed
27
+ Requires-Python: >=3.10
28
+ Requires-Dist: markdown-it-py[linkify]<5,>=3.0
29
+ Requires-Dist: mdit-py-plugins<1,>=0.4.0
30
+ Requires-Dist: pydantic<3,>=2.0
31
+ Requires-Dist: pyyaml<7,>=6.0
32
+ Provides-Extra: dev
33
+ Requires-Dist: behave>=1.2.6; extra == 'dev'
34
+ Requires-Dist: build>=1.2; extra == 'dev'
35
+ Requires-Dist: pre-commit; extra == 'dev'
36
+ Requires-Dist: ruff>=0.6; extra == 'dev'
37
+ Requires-Dist: tox; extra == 'dev'
38
+ Description-Content-Type: text/markdown
39
+
40
+ # Markus
41
+
42
+ **GitHub-flavored Markdown with a small vocabulary for layout intent.**
43
+
44
+ Markus keeps Markdown as the content language, then adds colon-fenced
45
+ directives for the things GFM cannot say: *this is a pull quote*, *these
46
+ items are peer cards*, *these two views belong together*. Authors encode
47
+ meaning. The renderer turns that meaning into accessible HTML and responsive
48
+ CSS — or, later, print, EPUB, or email.
49
+
50
+ ## Install
51
+
52
+ ```bash
53
+ pip install anthus-markus
54
+ ```
55
+
56
+ Python 3.10 or newer.
57
+
58
+ ## Convert a page
59
+
60
+ ```bash
61
+ markus convert examples/getting-started.md -o page.html
62
+ markus validate examples/getting-started.md
63
+ markus ast examples/getting-started.md
64
+ ```
65
+
66
+ Python API:
67
+
68
+ ```python
69
+ from markusmd import convert
70
+
71
+ html = convert(open("page.md", encoding="utf-8").read())
72
+ ```
73
+
74
+ ## Directives
75
+
76
+ ```md
77
+ :::pull-quote{attribution="Engineering principle" tone="primary"}
78
+ The best system is often the one whose failure modes you can explain.
79
+ :::
80
+
81
+ :::feature-grid{columns=3}
82
+ :::feature-card{icon="bolt"}
83
+ ## Low latency
84
+ Keep common interactions local.
85
+ :::
86
+ :::
87
+ ```
88
+
89
+ The 0.1 vocabulary:
90
+
91
+ | Directive | Intent |
92
+ | --- | --- |
93
+ | `callout` (`note`, `warning`, `tip`, `caution`) | Status or editorial note |
94
+ | `pull-quote` | Editorial quotation |
95
+ | `card-grid` / `card` | Peer items |
96
+ | `two-up` / `column` | A conceptual pair |
97
+ | `figure` | Media with caption and credit |
98
+ | `details` | Progressive disclosure |
99
+ | `aside` | Supporting, non-linear material |
100
+ | `metric` | A labeled fact (`::metric{...}`) |
101
+
102
+ Unknown names and unknown attributes fail validation. That is intentional:
103
+ Markus must not decay into an untyped CSS API. See
104
+ [docs/LANGUAGE.md](docs/LANGUAGE.md) for the full contract.
105
+
106
+ ## Demo site
107
+
108
+ **[anthusai.github.io/Markus/](https://anthusai.github.io/Markus/)** — written in
109
+ Markus and built by Markus.
110
+
111
+ To run the same site locally:
112
+
113
+ ```bash
114
+ pip install -e ".[dev]"
115
+ markus site site --out _site --serve --port 43147
116
+ ```
117
+
118
+ ## Preview locally
119
+
120
+ ```bash
121
+ markus preview examples/getting-started.md
122
+ ```
123
+
124
+ ## Development
125
+
126
+ ```bash
127
+ pip install -e ".[dev]"
128
+ behave # Gherkin behavior specs
129
+ ruff check src features
130
+ python -m build
131
+ ```
132
+
133
+ ## License
134
+
135
+ MIT © Anthus AI Solutions
@@ -0,0 +1,96 @@
1
+ # Markus
2
+
3
+ **GitHub-flavored Markdown with a small vocabulary for layout intent.**
4
+
5
+ Markus keeps Markdown as the content language, then adds colon-fenced
6
+ directives for the things GFM cannot say: *this is a pull quote*, *these
7
+ items are peer cards*, *these two views belong together*. Authors encode
8
+ meaning. The renderer turns that meaning into accessible HTML and responsive
9
+ CSS — or, later, print, EPUB, or email.
10
+
11
+ ## Install
12
+
13
+ ```bash
14
+ pip install anthus-markus
15
+ ```
16
+
17
+ Python 3.10 or newer.
18
+
19
+ ## Convert a page
20
+
21
+ ```bash
22
+ markus convert examples/getting-started.md -o page.html
23
+ markus validate examples/getting-started.md
24
+ markus ast examples/getting-started.md
25
+ ```
26
+
27
+ Python API:
28
+
29
+ ```python
30
+ from markusmd import convert
31
+
32
+ html = convert(open("page.md", encoding="utf-8").read())
33
+ ```
34
+
35
+ ## Directives
36
+
37
+ ```md
38
+ :::pull-quote{attribution="Engineering principle" tone="primary"}
39
+ The best system is often the one whose failure modes you can explain.
40
+ :::
41
+
42
+ :::feature-grid{columns=3}
43
+ :::feature-card{icon="bolt"}
44
+ ## Low latency
45
+ Keep common interactions local.
46
+ :::
47
+ :::
48
+ ```
49
+
50
+ The 0.1 vocabulary:
51
+
52
+ | Directive | Intent |
53
+ | --- | --- |
54
+ | `callout` (`note`, `warning`, `tip`, `caution`) | Status or editorial note |
55
+ | `pull-quote` | Editorial quotation |
56
+ | `card-grid` / `card` | Peer items |
57
+ | `two-up` / `column` | A conceptual pair |
58
+ | `figure` | Media with caption and credit |
59
+ | `details` | Progressive disclosure |
60
+ | `aside` | Supporting, non-linear material |
61
+ | `metric` | A labeled fact (`::metric{...}`) |
62
+
63
+ Unknown names and unknown attributes fail validation. That is intentional:
64
+ Markus must not decay into an untyped CSS API. See
65
+ [docs/LANGUAGE.md](docs/LANGUAGE.md) for the full contract.
66
+
67
+ ## Demo site
68
+
69
+ **[anthusai.github.io/Markus/](https://anthusai.github.io/Markus/)** — written in
70
+ Markus and built by Markus.
71
+
72
+ To run the same site locally:
73
+
74
+ ```bash
75
+ pip install -e ".[dev]"
76
+ markus site site --out _site --serve --port 43147
77
+ ```
78
+
79
+ ## Preview locally
80
+
81
+ ```bash
82
+ markus preview examples/getting-started.md
83
+ ```
84
+
85
+ ## Development
86
+
87
+ ```bash
88
+ pip install -e ".[dev]"
89
+ behave # Gherkin behavior specs
90
+ ruff check src features
91
+ python -m build
92
+ ```
93
+
94
+ ## License
95
+
96
+ MIT © Anthus AI Solutions
@@ -0,0 +1,6 @@
1
+ [behave]
2
+ paths = features
3
+ show_skipped = false
4
+ stdout_capture = false
5
+ log_capture = false
6
+ format = pretty
@@ -0,0 +1,80 @@
1
+ # Markus language
2
+
3
+ Markus is **GitHub Flavored Markdown** plus a small registry of colon-fenced
4
+ semantic directives. Authors encode intent. The renderer chooses layout.
5
+
6
+ ## Document metadata
7
+
8
+ Optional YAML front matter:
9
+
10
+ ```md
11
+ ---
12
+ title: The future of local inference
13
+ authors:
14
+ - Ada
15
+ date: 2026-09-04
16
+ ---
17
+ ```
18
+
19
+ ## Container directives
20
+
21
+ ```
22
+ :::name{key="value" flag other=1}
23
+ Markdown, including nested directives.
24
+ :::
25
+ ```
26
+
27
+ | Name | Meaning | Notable attributes |
28
+ | --- | --- | --- |
29
+ | `callout` | Note, warning, tip, or caution | `kind`, `title` |
30
+ | `note`, `warning`, `tip`, `caution` | Aliases for `callout` | `title` |
31
+ | `pull-quote` | Editorial quotation | `attribution`, `source`, `tone`, `align` |
32
+ | `card-grid` / `feature-grid` | Peer cards | `label`, `columns` (hint) |
33
+ | `card` / `feature-card` | One peer item | `icon`, `title`, `span` (`1`–`6` or `full`) |
34
+ | `two-up` | A conceptual pair | `ratio` (`1:1`, `2:1`, `1:2`), `align` |
35
+ | `column` | One side of `two-up` | — |
36
+ | `figure` | Media with caption | `src`, `alt`, `caption`, `credit` |
37
+ | `details` | Progressive disclosure | `summary`, `open` |
38
+ | `aside` | Supporting, non-linear material | `title` |
39
+ | `tabs` | Tabbed container | `label` |
40
+ | `tab` | One tab panel | `label` |
41
+ | `step-list` | Ordered sequence of steps | — |
42
+ | `step` | Single step | — |
43
+ | `timeline` | Chronological sequence | `label` |
44
+ | `timeline-event` | Single event in a timeline | `date`, `time`, `title`, `icon` |
45
+
46
+ A trailing kramdown-style attribute list is also accepted inside a directive:
47
+
48
+ ```md
49
+ :::pull-quote
50
+ > Measure what matters.
51
+ {: attribution="Editorial principle" }
52
+ :::
53
+ ```
54
+
55
+ ## Leaf directives
56
+
57
+ ```
58
+ ::metric{value="12" unit="ms" label="p95 latency" delta="-8%"}
59
+ ::video{src="screencast.mp4" title="Walkthrough"}
60
+ ```
61
+
62
+ | Name | Meaning | Notable attributes |
63
+ | --- | --- | --- |
64
+ | `metric` | Key metric fact | `value`, `unit`, `label`, `delta` |
65
+ | `video` | Video player | `src`, `title`, `poster` |
66
+
67
+ ## Nesting rules
68
+
69
+ - `card-grid` may contain only `card` (or the `feature-card` alias)
70
+ - `two-up` must contain exactly two `column` children
71
+ - `tabs` may contain only `tab`
72
+ - `step-list` may contain only `step`
73
+ - `timeline` may contain only `timeline-event`
74
+ - Other containers may nest Markdown and further directives
75
+ - Fenced code blocks are not scanned for directives
76
+
77
+ ## What does not belong in source
78
+
79
+ Do not add `margin`, `width`, `font-size`, or other presentation keys.
80
+ Unknown directive names and unknown attributes fail validation.
@@ -0,0 +1,51 @@
1
+ # Getting started with Markus
2
+
3
+ Markus is GitHub Flavored Markdown plus colon-fenced directives that name
4
+ layout *intent* rather than CSS.
5
+
6
+ :::pull-quote{attribution="Engineering principle" tone="primary"}
7
+ The best system is often the one whose failure modes you can explain.
8
+ :::
9
+
10
+ :::feature-grid{columns=3}
11
+ :::feature-card{icon="bolt"}
12
+ ## Low latency
13
+
14
+ Keep common interactions local to minimize round trips.
15
+ :::
16
+
17
+ :::feature-card{icon="lock"}
18
+ ## Private by default
19
+
20
+ Do not transmit user data unless the task requires it.
21
+ :::
22
+
23
+ :::feature-card{icon="gauge"}
24
+ ## Measurable cost
25
+
26
+ Track tokens, watts, requests, and time-to-result.
27
+ :::
28
+ :::
29
+
30
+ :::two-up{ratio="1:1" align="start"}
31
+ :::column
32
+ ## What changes
33
+
34
+ - A local model lowers marginal request cost
35
+ - Deployment becomes a systems problem
36
+ :::
37
+
38
+ :::column
39
+ ## What remains
40
+
41
+ - Evaluation
42
+ - Retrieval quality
43
+ - UX
44
+ - Observability
45
+ :::
46
+ :::
47
+
48
+ :::callout{kind="note" title="Editorial guidance"}
49
+ Use `two-up` to express a conceptual pairing, not merely because two
50
+ paragraphs happen to fit beside each other.
51
+ :::
@@ -0,0 +1,81 @@
1
+ Feature: Markus command line
2
+ As a writer in a terminal
3
+ I want to convert, validate, and inspect Markus files
4
+ So that I can publish HTML without embedding the library myself
5
+
6
+ Scenario: Convert a file to HTML
7
+ Given a Markus file "page.md" with:
8
+ """
9
+ # Hello Markus
10
+ """
11
+ When I run "markus convert page.md --fragment --no-css"
12
+ Then the command should succeed
13
+ And stdout should contain "<h1>Hello Markus</h1>"
14
+
15
+ Scenario: Validate a well-formed file
16
+ Given a Markus file "ok.md" with:
17
+ """
18
+ :::tip
19
+ Ship the small vocabulary first.
20
+ :::
21
+ """
22
+ When I run "markus validate ok.md"
23
+ Then the command should succeed
24
+ And stdout should contain "ok"
25
+
26
+ Scenario: Validate rejects unknown directives
27
+ Given a Markus file "bad.md" with:
28
+ """
29
+ :::carousel
30
+ Nope.
31
+ :::
32
+ """
33
+ When I run "markus validate bad.md"
34
+ Then the command should fail
35
+ And stderr should contain "Unknown directive 'carousel'"
36
+
37
+ Scenario: Print a JSON AST
38
+ Given a Markus file "quote.md" with:
39
+ """
40
+ :::pull-quote{attribution="Ada"}
41
+ Make it matter.
42
+ :::
43
+ """
44
+ When I run "markus ast quote.md"
45
+ Then the command should succeed
46
+ And stdout should contain "pull-quote"
47
+ And stdout should contain "Ada"
48
+
49
+ Scenario: Convert a file to HTML with minified CSS
50
+ Given a Markus file "styled.md" with:
51
+ """
52
+ # Styled Page
53
+ """
54
+ When I run "markus convert styled.md --minify-css"
55
+ Then the command should succeed
56
+ And stdout should contain "<h1>Styled Page</h1>"
57
+ And stdout should contain "<style>"
58
+ And stdout should not contain "/* Markus default presentation layer"
59
+ And stdout should contain ":root{"
60
+
61
+ Scenario: Convert with minified CSS and no-css omits CSS
62
+ Given a Markus file "plain.md" with:
63
+ """
64
+ # Plain Page
65
+ """
66
+ When I run "markus convert plain.md --minify-css --no-css"
67
+ Then the command should succeed
68
+ And stdout should contain "<h1>Plain Page</h1>"
69
+ And stdout should not contain "<style>"
70
+
71
+ Scenario: Convert fragment with minified CSS
72
+ Given a Markus file "frag.md" with:
73
+ """
74
+ # Fragment
75
+ """
76
+ When I run "markus convert frag.md --fragment --minify-css"
77
+ Then the command should succeed
78
+ And stdout should contain "<style>"
79
+ And stdout should not contain "/* Markus default presentation layer"
80
+ And stdout should contain "markus-document"
81
+ And stdout should contain "<h1>Fragment</h1>"