Skip to content

Commit

Permalink
Add new code_index example (#13)
Browse files Browse the repository at this point in the history
  • Loading branch information
pydsigner committed Nov 10, 2023
1 parent 7ae3b94 commit 517434f
Show file tree
Hide file tree
Showing 9 changed files with 612 additions and 0 deletions.
178 changes: 178 additions & 0 deletions examples/code_index.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
from __future__ import annotations

from pathlib import Path
import typing as t

from anchovy import (
AnchovyCSSStep,
AssetMinifierStep,
CSSMinifierStep,
DirectCopyStep,
Matcher,
InputBuildSettings,
JinjaExtendedMarkdownStep,
JinjaRenderStep,
OutputDirPathCalc,
PathCalc,
REMatcher,
ResourcePackerStep,
Rule,
Step,
UnpackArchiveStep,
WorkingDirPathCalc,
)
from anchovy.custody import CustodyEntry

if t.TYPE_CHECKING:
from jinja2 import Environment


MARKDOWN_TEMPLATE = """---
template = "base.jinja.html"
footnote = "Generated from {path} by Anchovy."
---
# {path}
```py
{code}
```
"""


class Code2MarkdownStep(Step):
encoding = 'utf-8'
newline = '\n'
template = MARKDOWN_TEMPLATE
def __call__(self, path: Path, output_paths: list[Path]):
code = path.read_text(self.encoding)
processed = self.template.format(path=path.name, code=code)
for target_path in output_paths:
target_path.parent.mkdir(parents=True, exist_ok=True)
target_path.write_text(processed, self.encoding, newline=self.newline)


class CodeIndexStep(JinjaRenderStep):
encoding = 'utf-8'

def __init__(self,
leaf_matcher: Matcher,
leaf_calc: PathCalc,
env: Environment | None = None,
extra_globals: dict[str, t.Any] | None = None):
super().__init__(env, extra_globals)
self.leaf_matcher = leaf_matcher
self.leaf_calc = leaf_calc

@classmethod
def get_dependencies(cls):
return super().get_dependencies()

def __call__(self, path: Path, output_paths: list[Path]):
matched_paths: list[Path] = [path]
leaves: list[tuple[Path, Path]] = []
for sibling in path.parent.iterdir():
print('sibling:', sibling)
if sibling == path or sibling.is_dir():
continue
print('sibling matched thus')
if match := self.leaf_matcher(self.context, sibling):
print('sibling matched', match)
matched_paths.append(sibling)
leaves.append((
sibling,
self.leaf_calc(self.context, sibling, match).relative_to(self.context['output_dir']),
))

print('leaves:', leaves)
self.render_template(
path.relative_to(self.context['working_dir']).as_posix(),
{'leaves': leaves},
output_paths
)
return matched_paths, output_paths


# Optional, and can be overridden with CLI arguments.
SETTINGS = InputBuildSettings(
input_dir=Path(__file__).parent / 'code_index',
working_dir=Path('working/code_index'),
output_dir=Path('output/code_index'),
custody_cache=Path('output/code_index.json'),
)
RULES = [
# Ignore dotfiles found in either the input_dir or the working dir.
Rule(
(
REMatcher(r'(.*/)*\..*', parent_dir='input_dir')
| REMatcher(r'(.*/)*\..*', parent_dir='working_dir')
),
None
),
# Unpack archives.
Rule(
REMatcher(r'.*\.zip'),
[WorkingDirPathCalc(transform=lambda p: p.parent), None],
UnpackArchiveStep()
),
# Embed Python files in Markdown.
Rule(
REMatcher(r'.*\.py'),
[WorkingDirPathCalc('.md')],
Code2MarkdownStep()
),
# Render markdown files and stop processing.
Rule(
REMatcher(r'.*\.md'),
[WorkingDirPathCalc('.html'), None],
JinjaExtendedMarkdownStep(
default_template='base.j.html',
pygments_params={'classprefix': 'pyg-'},
)
),
# Render Jinja indices through working dir (so there's time for the archive
# to unpack) and stop processing.
Rule(
REMatcher(r'index\.jinja\.html', parent_dir='input_dir'),
[WorkingDirPathCalc(), None],
DirectCopyStep()
),
Rule(
REMatcher(r'index(?P<ext>\.jinja\.html)', parent_dir='working_dir'),
[WorkingDirPathCalc('.html'), None],
CodeIndexStep(
REMatcher(r'.*\.py'),
OutputDirPathCalc('.html')
)
),
# Ignore all other Jinja templates.
Rule(REMatcher(r'.*\.jinja\.html'), None),
# Preprocess Anchovy CSS and stop processing.
Rule(
REMatcher(r'.*(?P<ext>\.anchovy\.css)'),
[WorkingDirPathCalc('.css'), None],
AnchovyCSSStep()
),
# Pack CSS. Have to wait for working dir so Anchovy CSS processing is done.
Rule(
REMatcher(r'.*/css_pack.txt', parent_dir='input_dir'),
[WorkingDirPathCalc(), None],
DirectCopyStep()
),
Rule(
REMatcher(r'.*/css_pack.txt', parent_dir='working_dir'),
[WorkingDirPathCalc('.css'), None],
ResourcePackerStep('working_dir')
),
# Minify packed CSS and stop processing.
Rule(
REMatcher(r'.*/css_pack\.css', parent_dir='working_dir'),
[OutputDirPathCalc(), None],
CSSMinifierStep()
),
# Minify HTML/JS and stop processing.
Rule(
REMatcher(r'.*\.(html|js)', parent_dir='working_dir'),
[OutputDirPathCalc(), None],
AssetMinifierStep()
),
]
16 changes: 16 additions & 0 deletions examples/code_index/base.jinja.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<!doctype html>
<html lang="en">
<head>
<link rel="stylesheet" type="text/css" href="static/css_pack.css">
</head>
<body>
{% block content %}
<main>
{{ rendered_markdown | safe }}
</main>
{% endblock %}
<footer>
{{ footnote }}
</footer>
</body>
</html>
Binary file added examples/code_index/code.zip
Binary file not shown.
10 changes: 10 additions & 0 deletions examples/code_index/index.jinja.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{% set footnote = "An index of Anchovy example configuration code." %}
{% extends "base.jinja.html" %}
{% block content %}
<main>
<h1>Examples</h1>
{% for source, target in leaves %}
<a href="{{target.as_posix()}}"><h2>{{ source.name }}</h2></a>
{% endfor %}
</main>
{% endblock %}
28 changes: 28 additions & 0 deletions examples/code_index/static/core.anchovy.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
body {
font-family: 'Arial Narrow', sans-serif;
color: #eee;
background-color: #333;
padding: 10px;
}

main, footer {
margin: 0 auto;
max-width: 800px;
}

footer {
border-top: 1px #eee dotted;
padding-top: 10px;
}

.highlight {
padding: 10px;
border-radius: 5px;
}

a {
color: #eee;
:hover {
color: #aaf;
}
}
2 changes: 2 additions & 0 deletions examples/code_index/static/css_pack.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
static/core.css
static/pygments.css
85 changes: 85 additions & 0 deletions examples/code_index/static/pygments.anchovy.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
.highlight {
line-height: 1.2em;
background: #272822; color: #f8f8f2;
span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
.hll { background-color: #49483e }
.pyg-c { color: #959077 } /* Comment */
.pyg-err { color: #ed007e; background-color: #1e0010 } /* Error */
.pyg-esc { color: #f8f8f2 } /* Escape */
.pyg-g { color: #f8f8f2 } /* Generic */
.pyg-k { color: #66d9ef } /* Keyword */
.pyg-l { color: #ae81ff } /* Literal */
.pyg-n { color: #f8f8f2 } /* Name */
.pyg-o { color: #ff4689 } /* Operator */
.pyg-x { color: #f8f8f2 } /* Other */
.pyg-p { color: #f8f8f2 } /* Punctuation */
.pyg-ch { color: #959077 } /* Comment.Hashbang */
.pyg-cm { color: #959077 } /* Comment.Multiline */
.pyg-cp { color: #959077 } /* Comment.Preproc */
.pyg-cpf { color: #959077 } /* Comment.PreprocFile */
.pyg-c1 { color: #959077 } /* Comment.Single */
.pyg-cs { color: #959077 } /* Comment.Special */
.pyg-gd { color: #ff4689 } /* Generic.Deleted */
.pyg-ge { color: #f8f8f2; font-style: italic } /* Generic.Emph */
.pyg-ges { color: #f8f8f2; font-weight: bold; font-style: italic } /* Generic.EmphStrong */
.pyg-gr { color: #f8f8f2 } /* Generic.Error */
.pyg-gh { color: #f8f8f2 } /* Generic.Heading */
.pyg-gi { color: #a6e22e } /* Generic.Inserted */
.pyg-go { color: #66d9ef } /* Generic.Output */
.pyg-gp { color: #ff4689; font-weight: bold } /* Generic.Prompt */
.pyg-gs { color: #f8f8f2; font-weight: bold } /* Generic.Strong */
.pyg-gu { color: #959077 } /* Generic.Subheading */
.pyg-gt { color: #f8f8f2 } /* Generic.Traceback */
.pyg-kc { color: #66d9ef } /* Keyword.Constant */
.pyg-kd { color: #66d9ef } /* Keyword.Declaration */
.pyg-kn { color: #ff4689 } /* Keyword.Namespace */
.pyg-kp { color: #66d9ef } /* Keyword.Pseudo */
.pyg-kr { color: #66d9ef } /* Keyword.Reserved */
.pyg-kt { color: #66d9ef } /* Keyword.Type */
.pyg-ld { color: #e6db74 } /* Literal.Date */
.pyg-m { color: #ae81ff } /* Literal.Number */
.pyg-s { color: #e6db74 } /* Literal.String */
.pyg-na { color: #a6e22e } /* Name.Attribute */
.pyg-nb { color: #f8f8f2 } /* Name.Builtin */
.pyg-nc { color: #a6e22e } /* Name.Class */
.pyg-no { color: #66d9ef } /* Name.Constant */
.pyg-nd { color: #a6e22e } /* Name.Decorator */
.pyg-ni { color: #f8f8f2 } /* Name.Entity */
.pyg-ne { color: #a6e22e } /* Name.Exception */
.pyg-nf { color: #a6e22e } /* Name.Function */
.pyg-nl { color: #f8f8f2 } /* Name.Label */
.pyg-nn { color: #f8f8f2 } /* Name.Namespace */
.pyg-nx { color: #a6e22e } /* Name.Other */
.pyg-py { color: #f8f8f2 } /* Name.Property */
.pyg-nt { color: #ff4689 } /* Name.Tag */
.pyg-nv { color: #f8f8f2 } /* Name.Variable */
.pyg-ow { color: #ff4689 } /* Operator.Word */
.pyg-pm { color: #f8f8f2 } /* Punctuation.Marker */
.pyg-w { color: #f8f8f2 } /* Text.Whitespace */
.pyg-mb { color: #ae81ff } /* Literal.Number.Bin */
.pyg-mf { color: #ae81ff } /* Literal.Number.Float */
.pyg-mh { color: #ae81ff } /* Literal.Number.Hex */
.pyg-mi { color: #ae81ff } /* Literal.Number.Integer */
.pyg-mo { color: #ae81ff } /* Literal.Number.Oct */
.pyg-sa { color: #e6db74 } /* Literal.String.Affix */
.pyg-sb { color: #e6db74 } /* Literal.String.Backtick */
.pyg-sc { color: #e6db74 } /* Literal.String.Char */
.pyg-dl { color: #e6db74 } /* Literal.String.Delimiter */
.pyg-sd { color: #e6db74 } /* Literal.String.Doc */
.pyg-s2 { color: #e6db74 } /* Literal.String.Double */
.pyg-se { color: #ae81ff } /* Literal.String.Escape */
.pyg-sh { color: #e6db74 } /* Literal.String.Heredoc */
.pyg-si { color: #e6db74 } /* Literal.String.Interpol */
.pyg-sx { color: #e6db74 } /* Literal.String.Other */
.pyg-sr { color: #e6db74 } /* Literal.String.Regex */
.pyg-s1 { color: #e6db74 } /* Literal.String.Single */
.pyg-ss { color: #e6db74 } /* Literal.String.Symbol */
.pyg-bp { color: #f8f8f2 } /* Name.Builtin.Pseudo */
.pyg-fm { color: #a6e22e } /* Name.Function.Magic */
.pyg-vc { color: #f8f8f2 } /* Name.Variable.Class */
.pyg-vg { color: #f8f8f2 } /* Name.Variable.Global */
.pyg-vi { color: #f8f8f2 } /* Name.Variable.Instance */
.pyg-vm { color: #f8f8f2 } /* Name.Variable.Magic */
.pyg-il { color: #ae81ff } /* Literal.Number.Integer.Long */
}
Loading

0 comments on commit 517434f

Please sign in to comment.