From f458f716e39e3dda8f8ee0a8f0c2b57e0a6a5090 Mon Sep 17 00:00:00 2001 From: Glen Whitney Date: Fri, 12 Feb 2021 17:11:07 +0000 Subject: [PATCH] feat: Implement double-quoted filename features. (#13) Adds interpretation of ordinary Python character escapes (like "\t") and a special escape to fetch a particular Git version of a file, in double-quoted strings used as the FILENAME argument of a {! ... !} inclusion directive. Resolves #11. Resolves #12. Co-authored-by: Glen Whitney Reviewed-on: https://code.studioinfinity.org/glen/mkdocs-semiliterate/pulls/13 Co-Authored-By: Glen Whitney Co-Committed-By: Glen Whitney --- .drone.yml | 5 + .gitignore | 2 +- mkdocs_semiliterate/plugin.py | 91 ++++- setup.cfg | 2 +- tests/fixtures/git-inclusion/README.md | 7 + tests/fixtures/git-inclusion/mkdocs.yml | 6 + tests/fixtures/git-inclusion/refsite/404.html | 103 ++++++ .../git-inclusion/refsite/croppedindex.html | 128 +++++++ .../git-inclusion/refsite/css/base.css | 313 ++++++++++++++++++ .../refsite/css/bootstrap.min.css | 12 + .../refsite/css/font-awesome.min.css | 4 + tests/fixtures/quoted-filename/README.md | 7 + tests/fixtures/quoted-filename/mkdocs.yml | 6 + .../fixtures/quoted-filename/refsite/404.html | 103 ++++++ .../quoted-filename/refsite/croppedindex.html | 120 +++++++ .../quoted-filename/refsite/css/base.css | 313 ++++++++++++++++++ .../refsite/css/bootstrap.min.css | 12 + .../refsite/css/font-awesome.min.css | 4 + .../quoted-filename/snippet/Say \"Don't\"" | 1 + 19 files changed, 1225 insertions(+), 14 deletions(-) create mode 100644 tests/fixtures/git-inclusion/README.md create mode 100644 tests/fixtures/git-inclusion/mkdocs.yml create mode 100644 tests/fixtures/git-inclusion/refsite/404.html create mode 100644 tests/fixtures/git-inclusion/refsite/croppedindex.html create mode 100644 tests/fixtures/git-inclusion/refsite/css/base.css create mode 100644 tests/fixtures/git-inclusion/refsite/css/bootstrap.min.css create mode 100644 tests/fixtures/git-inclusion/refsite/css/font-awesome.min.css create mode 100644 tests/fixtures/quoted-filename/README.md create mode 100644 tests/fixtures/quoted-filename/mkdocs.yml create mode 100644 tests/fixtures/quoted-filename/refsite/404.html create mode 100644 tests/fixtures/quoted-filename/refsite/croppedindex.html create mode 100644 tests/fixtures/quoted-filename/refsite/css/base.css create mode 100644 tests/fixtures/quoted-filename/refsite/css/bootstrap.min.css create mode 100644 tests/fixtures/quoted-filename/refsite/css/font-awesome.min.css create mode 100644 "tests/fixtures/quoted-filename/snippet/Say \"Don't\"" diff --git a/.drone.yml b/.drone.yml index 3ce60f1..93b304c 100644 --- a/.drone.yml +++ b/.drone.yml @@ -10,6 +10,11 @@ kind: pipeline name: bootstrap steps: + - name: fetch tags + image: alpine/git + commands: + - git fetch --tags + - name: build_install_test image: python commands: diff --git a/.gitignore b/.gitignore index 8d18c4b..e47d817 100644 --- a/.gitignore +++ b/.gitignore @@ -124,7 +124,7 @@ venv.bak/ .ropeproject # mkdocs documentation -/site +site /semiliterate # mypy diff --git a/mkdocs_semiliterate/plugin.py b/mkdocs_semiliterate/plugin.py index e366576..54f2c0b 100644 --- a/mkdocs_semiliterate/plugin.py +++ b/mkdocs_semiliterate/plugin.py @@ -16,6 +16,8 @@ from mkdocs_simple_plugin.plugin import SimplePlugin, StreamExtract import os import re +import subprocess +import tempfile import yaml @@ -91,9 +93,12 @@ is checked for `{! ... !}`. # OK, we have found (the start of) an inclusion and must process it preamble = line[:include_match.start()] remainder = line[include_match.end(1):] + doublequoted = False body_pattern = StreamInclusion.include_quoted_file if include_match[2].isspace(): body_pattern = StreamInclusion.include_bare_file + elif include_match[2] == '"': + doublequoted = True body_match = body_pattern.search(remainder) if not body_match: for extra_line in self.input_stream: @@ -105,7 +110,64 @@ is checked for `{! ... !}`. errmsg = "semiliterate: End of file while scanning for `!}`" utils.log.error(errmsg) raise EOFError(errmsg) - include_path = self.include_root + '/' + body_match['fn'] + filename = body_match['fn'] + gitextract = False + r""" md +### Double-quoted filenames and Git extraction + +Standard Python escape sequences in double-quoted filenames are interpreted +as usual; for example you can write +``` +{! ../tests/fixtures/quoted-filename/README.md extract: + start: '(.*!.*)' + stop: '\s' +!} +``` +to include a file whose name (`snippet/Say "Don't"`, in this case) has both +double and single quotes. + +Further, `semiliterate` supports a special escape to extract a file from the +Git archive of the project (presuming it is under Git version control) and then +include content from that file. For example, you could write +``` +{! ../tests/fixtures/git-inclusion/README.md extract: + start: '(.*!.*)' + stop: '\s' +!} +``` + +to extract content starting after the `### install` line from the +`mkdocs.yml` file in the Git commit of this repository +tagged `0.1.0`. This feature is primarily useful if you are documenting the +development or changes to a project over time, or are documenting a feature +in a specific past release of your project, and want to be sure that +material included in your documentation does _not_ change as the project +progresses. (This behavior is as opposed to the usual case, in which you want +your documentation to incorporate the most up-to-date version of extracted +content.) + +The precise behavior for a FILENAME argument in a `{! ... !}` inclusion of the +form + +`"\git SPECIFIER"` + +is that the output of `git show SPECIFIER` is written to a temporary file, +and that file is extracted from. +""" + if doublequoted: + if filename[:5] == r'\git ': + gitextract = True + filename = filename[5:] + filename = (filename.encode('latin-1', 'backslashreplace') + .decode('unicode-escape')) + include_path = self.include_root + '/' + filename + if gitextract: + (write_handle, include_path) = tempfile.mkstemp() + utils.log.info( + f"semiliterate: extracting {filename} to {include_path}") + contents = subprocess.check_output(['git', 'show', filename]) + os.write(write_handle, contents) + os.close(write_handle) new_root = re.match(r'(.*)/', include_path)[1] try: include_parameters = yaml.safe_load(body_match['yml']) @@ -131,10 +193,23 @@ is checked for `{! ... !}`. class SemiliteratePlugin(SimplePlugin): r""" md An extension of the mkdocs-simple-plugin -In addition, block-comment markdown `/** md` ... `**/` is by -default scanned for in all files with _any_ extension, as it's valid in so many -disparate languages. +### Universal block-comment markdown +By default, `semiliterate` scans for block-comment markdown `/** md` ... `**/` +in all files with _any_ extension, as it's valid in so many disparate languages. +(As opposed to `simple`, which defaults to searching for such markdown in a +specific list of file types.) + """ + + super_sdict = dict(SimplePlugin.config_scheme) + super_semi_dflt = super_sdict['semiliterate'].default + semi_dflt = [b if 'js' not in b['pattern'] else dict(b, pattern=r'\.') + for b in super_semi_dflt] + altered_config_scheme = dict( + super_sdict, + semiliterate=config_options.Type(list, default=semi_dflt)).items() + + add_param_doc = r""" md ### Additional plugin parameters `semiliterate` adds a couple of new plugin parameters to further tailor its @@ -150,14 +225,6 @@ default values in parentheses at the beginning of each entry. terminate: '^\s*\)' !} """ - - super_sdict = dict(SimplePlugin.config_scheme) - super_semi_dflt = super_sdict['semiliterate'].default - semi_dflt = [b if 'js' not in b['pattern'] else dict(b, pattern=r'\.') - for b in super_semi_dflt] - altered_config_scheme = dict( - super_sdict, - semiliterate=config_options.Type(list, default=semi_dflt)).items() config_scheme = ( # Note documentation of each new parameter **follows** the parameter. *altered_config_scheme, diff --git a/setup.cfg b/setup.cfg index 99b4d31..fffab8d 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,6 +1,6 @@ [metadata] name = mkdocs-semiliterate -version = 0.1.1 +version = 0.2.0 description = Extension of mkdocs-simple-plugin adding easy content inclusion long_description = file: README.md long_description_content_type = text/markdown diff --git a/tests/fixtures/git-inclusion/README.md b/tests/fixtures/git-inclusion/README.md new file mode 100644 index 0000000..754dd01 --- /dev/null +++ b/tests/fixtures/git-inclusion/README.md @@ -0,0 +1,7 @@ +# Test of git extraction + +Hopefully we see + +{! "\git 0.1.0:mkdocs.yml" extract: {start: '### install'} !} + +here. diff --git a/tests/fixtures/git-inclusion/mkdocs.yml b/tests/fixtures/git-inclusion/mkdocs.yml new file mode 100644 index 0000000..bd3e416 --- /dev/null +++ b/tests/fixtures/git-inclusion/mkdocs.yml @@ -0,0 +1,6 @@ +site_name: Full inclusion +docs_dir: refsite # dummy +plugins: +- semiliterate: + ignore_folders: [refsite, snippet] + merge_docs_dir: false diff --git a/tests/fixtures/git-inclusion/refsite/404.html b/tests/fixtures/git-inclusion/refsite/404.html new file mode 100644 index 0000000..a5b03b3 --- /dev/null +++ b/tests/fixtures/git-inclusion/refsite/404.html @@ -0,0 +1,103 @@ + + + + + + + + + + + Full inclusion + + + + + + + + + + + + + + +
+
+ +
+
+

404

+

Page not found

+
+
+ + +
+
+ +
+
+

Documentation built with MkDocs.

+
+ + + + + + + diff --git a/tests/fixtures/git-inclusion/refsite/croppedindex.html b/tests/fixtures/git-inclusion/refsite/croppedindex.html new file mode 100644 index 0000000..c8c2f48 --- /dev/null +++ b/tests/fixtures/git-inclusion/refsite/croppedindex.html @@ -0,0 +1,128 @@ + + + + + + + + + + + Full inclusion + + + + + + + + + + + + + + +
+
+
+
+ +

Test of git extraction

+

Hopefully we see

+
      stop: '^\s*###'
+      replace: ['^# (.*\s*)$', '^\s*-(.*\s*)$']
+
+

markdown_extensions: +- abbr +- def_list +theme: + name: readthedocs +docs_dir: mkdocs_semiliterate # dummy

+

here.

+
+
+ +
+
+

Documentation built with MkDocs.

+
+ + + + + + + + + + + + + +
+
+ +
+
+

404

+

Page not found

+
+
+ + +
+
+ +
+
+

Documentation built with MkDocs.

+
+ + + + + + + diff --git a/tests/fixtures/quoted-filename/refsite/croppedindex.html b/tests/fixtures/quoted-filename/refsite/croppedindex.html new file mode 100644 index 0000000..328fde1 --- /dev/null +++ b/tests/fixtures/quoted-filename/refsite/croppedindex.html @@ -0,0 +1,120 @@ + + + + + + + + + + + Full inclusion + + + + + + + + + + + + + + +
+
+
+
+ +

Test of quoted inclusion

+

Hopefully we see

+

Shh... quiet world.

+

here.

+
+
+ +
+
+

Documentation built with MkDocs.

+
+ + + + + + + + +