diff --git a/build.sh b/build.sh index 0da930fe..fc806f2b 100755 --- a/build.sh +++ b/build.sh @@ -2,7 +2,7 @@ set -e pip install -r requirements.txt pip install -e . -# md file="build.snippet" +# md file="build.snippet" content="^#?\s?(.*)" # Building this package requires generating the readme files for the examples. # # ```bash diff --git a/examples/.pages b/examples/.pages index b8baf24a..7c3316bb 100644 --- a/examples/.pages +++ b/examples/.pages @@ -10,6 +10,7 @@ nav: - Front matter extraction: examples/ok-mkdocs-custom-extract - Advanced replacement: examples/ok-source-replace - Extract with inline settings: examples/ok-mkdocs-inline-settings + - Ignore a file: examples/ok-mkdocs-ignore-file - Extract docs with macros: examples/ok-with-macros - Extract docs with mkdocstrings: examples/ok-with-mkdocstrings - Extract a snippet: examples/ok-source-with-snippet diff --git a/examples/README.md.jinja b/examples/README.md.jinja index b6043358..ad2c5c47 100644 --- a/examples/README.md.jinja +++ b/examples/README.md.jinja @@ -1,3 +1,4 @@ + # {{ title }} diff --git a/examples/gen_readme.py b/examples/gen_readme.py index 5cdc2307..f876a2ea 100755 --- a/examples/gen_readme.py +++ b/examples/gen_readme.py @@ -96,7 +96,7 @@ def __init__(self, readme_template): def include_input(self, path): """The files to expand as input examples.""" - include_list = ['.py', '.c', '.litcoffee'] + include_list = ['.py', '.c', '.litcoffee', '.cpp'] return any(extension in path.displayname for extension in include_list) def include_output(self, path): diff --git a/examples/ok-mkdocs-ignore-file/hello_world.cpp b/examples/ok-mkdocs-ignore-file/hello_world.cpp new file mode 100644 index 00000000..b6835529 --- /dev/null +++ b/examples/ok-mkdocs-ignore-file/hello_world.cpp @@ -0,0 +1,19 @@ +/** md-ignore + +# Ignore me + +Ignore everything beyond the first line since it contains md-ignore. +**/ + +#include + +int main() { + /** md + # Hello world + + This is the main function for hello world. + It outputs "Hello World!" to the screen. + **/ + std::cout << "Hello World!"; + return 0; +} diff --git a/examples/ok-mkdocs-ignore-file/index.md b/examples/ok-mkdocs-ignore-file/index.md new file mode 100644 index 00000000..0233cc6b --- /dev/null +++ b/examples/ok-mkdocs-ignore-file/index.md @@ -0,0 +1,3 @@ +# Hello World + +This is for testing files in the main directory. diff --git a/examples/ok-mkdocs-ignore-file/mkdocs-test.yml b/examples/ok-mkdocs-ignore-file/mkdocs-test.yml new file mode 100644 index 00000000..da791dcc --- /dev/null +++ b/examples/ok-mkdocs-ignore-file/mkdocs-test.yml @@ -0,0 +1,4 @@ +# This tests if the site directory is ignored in both build and serve. +site_name: ok-mkdocs-ignore-file +plugins: +- simple: diff --git a/mkdocs_simple_plugin/plugin.py b/mkdocs_simple_plugin/plugin.py index 097c8258..bb67b02f 100644 --- a/mkdocs_simple_plugin/plugin.py +++ b/mkdocs_simple_plugin/plugin.py @@ -44,7 +44,7 @@ {% include "mkdocs_simple_plugin/inline_params.snippet" %} -## Settings +## Default settings Below are the default settings of the plugin. @@ -56,6 +56,8 @@ If you add your own settings but want to also use any of these, you must reiterate the settings you want in your `mkdocs.yml` file. +## Configuration scheme + {% include "mkdocs_simple_plugin/config_scheme.snippet" %} ## Build @@ -97,32 +99,38 @@ class SimplePlugin(BasePlugin): # md file=config_scheme.snippet config_scheme = ( # ### include_folders + # # Directories whose name matches a glob pattern in this list will be # searched for documentation ('include_folders', config_options.Type(list, default=['*'])), - + # # ### ignore_folders + # # Directories whose name matches a glob pattern in this list will NOT be # searched for documentation. ('ignore_folders', config_options.Type(list, default=[])), - + # # ### ignore_hidden + # # Hidden directories will not be searched if this is true. ('ignore_hidden', config_options.Type(bool, default=True)), - + # # ### merge_docs_dir + # # If true, the contents of the docs directory (if any) will be merged # at the same level as all other documentation. # Otherwise, the docs directory will be retained as a subdirectory in # the result. ('merge_docs_dir', config_options.Type(bool, default=True)), - + # # ### build_docs_dir + # # If set, the directory where docs will be coallated to be build. # Otherwise, the build docs directory will be a temporary directory. ('build_docs_dir', config_options.Type(str, default='')), - + # # ### include_extensions + # # Any file in the searched directories whose name contains a string in # this list will simply be copied to the generated documentation. ('include_extensions', @@ -134,30 +142,31 @@ class SimplePlugin(BasePlugin): ".j2c", ".fpx", ".pcd", ".png", ".pdf", "CNAME", ".snippet", ".pages" ])), - + # # ### semiliterate + # # The semiliterate settings allows the extraction of markdown from # inside source files. # It is defined as a list of blocks of settings for different # filename patterns (typically matching filename extensions). # All regular expression parameters use ordinary Python `re` syntax. # - # {% include "mkdocs_simple_plugin/semiliterate.snippet" %} + # {% include "mkdocs_simple_plugin/semiliterate.snippet" %} # - # {% include "mkdocs_simple_plugin/extractionpattern.snippet" %} + # {% include "mkdocs_simple_plugin/extractionpattern.snippet" %} # /md - # md file="example.snippet" + ('semiliterate', config_options.Type( list, default=[ { - # #### Python - 'pattern': r'\.py$', + 'pattern': r'.*', + 'terminate': r'^\W*md-ignore', 'extract': [ { - # + # md file="example.snippet" # block comments starting with: `"""md` 'start': r'^\s*"""\W?md\b', 'stop': r'^\s*"""\s*$', @@ -184,13 +193,7 @@ class SimplePlugin(BasePlugin): # # /md # ``` # - } - ] - }, - { - # #### C, C++, and Javascript - 'pattern': r'\.(cpp|cc?|hh?|hpp|js|css)$', - 'extract': [ + }, { # block comments starting with: `/** md` 'start': r'^\s*/\*+\W?md\b', @@ -218,46 +221,22 @@ class SimplePlugin(BasePlugin): # // end md # ``` # + }, + { + # block comments starting with + # `` + 'start': r'\s*$', + # + # ```xml + # + # ``` + # } ] - - }, - { - # #### YAML, Dockerfiles, and shell scripts - 'pattern': r'Dockerfile$|\.(dockerfile|ya?ml|sh)$', - 'extract': [{ - # line-comment blocks starting with - # `# md` and ending with `# /md`, - 'start': r'^\s*#+\W?md\b', - 'stop': r'#\s\/md\s*$', - # stripping leading spaces and `#` - 'replace': [r'^\s*#?\s?(.*\n?)$'], - # - # ```yaml - # # md - # # This is a documentation comment. - # # /md - # ``` - # - }] - }, - { - # #### HTML and xml - 'pattern': r'\.(html?|xml)$', - 'extract': [{ - # line-comment blocks starting with - # `` - 'start': r'\s*$', - # - # ```xml - # - # ``` - # - }] - }, + } ])) ) # /md diff --git a/mkdocs_simple_plugin/semiliterate.py b/mkdocs_simple_plugin/semiliterate.py index 91ff1aaf..26ad3444 100644 --- a/mkdocs_simple_plugin/semiliterate.py +++ b/mkdocs_simple_plugin/semiliterate.py @@ -23,6 +23,7 @@ class ExtractionPattern: """An ExtractionPattern for a file.""" # md file="extractionpattern.snippet" # ##### start + # # (optional) The regex pattern to indicate the start of extraction. # # Only the first mode whose `start` expression matches is activated, so at @@ -37,6 +38,7 @@ class ExtractionPattern: # This convention allows for convenient "front-matter" extraction. # # ##### stop + # # (optional) The regex pattern to indicate the stop of extraction. # # After the extraction has stopped, the file will continue to be searched @@ -87,8 +89,8 @@ def __init__( self.replace.append((re.compile(item[0]), item[1])) # md file=inline_params.snippet - # # These parameters should be on the same line as the start block. + # # For example: # # ``` @@ -211,6 +213,11 @@ def write(self, arg: str): def close(self): """Finish the file.""" if self.file_object is not None: + utils.log.debug( + " ... extracted %s", + os.path.join( + self.file_directory, + self.file_name)) self.file_object.close() self.file_object = None @@ -256,25 +263,22 @@ def try_extract_match( def close(self) -> bool: """Returns true if something was written""" - if self.wrote_something: - utils.log.debug( - " ... extracted %s", - os.path.join( - self.output_stream.file_directory, - self.output_stream.file_name)) self.output_stream.close() return self.wrote_something - def set_output_stream(self, filename: str): + def set_output_file(self, filename: str): """Set output stream from filename.""" output_stream = self.output_stream if filename: output_stream = LazyFile( self.output_stream.file_directory, filename) + self.set_output_stream(output_stream) - if self.output_stream != output_stream: + def set_output_stream(self, stream: LazyFile): + """Set the output stream.""" + if self.output_stream != stream: self.close() - self.output_stream = output_stream + self.output_stream = stream def extract(self, **kwargs) -> bool: """Extract from file with semiliterate configuration. @@ -299,14 +303,14 @@ def extract(self, **kwargs) -> bool: if start: active_pattern = pattern active_pattern.setup(line) - self.set_output_stream(active_pattern.get_filename()) + self.set_output_file(active_pattern.get_filename()) self.try_extract_match(start) break continue # We are extracting. See if we should stop: if self.try_extract_match(get_match(active_pattern.stop, line)): active_pattern = None - self.output_stream = self.default_stream + self.set_output_stream(self.default_stream) continue # Extract all other lines in the normal way: self.extract_line(line, active_pattern) @@ -322,12 +326,13 @@ class Semiliterate: """Extract documentation from source files using regex settings.""" # md file="semiliterate.snippet" - # # #### pattern + # # Any file in the searched directories whose name contains this # required regular expression parameter will be scanned. # # #### destination + # # By default, the extracted documentation will be copied to a file # whose name is generated by removing the (last) extension from the # original filename, if any, and appending `.md`. However, if this @@ -336,6 +341,7 @@ class Semiliterate: # to produce the name of the destination file. # # #### terminate + # # If specified, all extraction from the file is terminated when # a line containing this regexp is encountered (whether or not # any extraction is currently active per the parameters below). diff --git a/tests/integration_test.bats b/tests/integration_test.bats index 3c627135..da5bbd8b 100755 --- a/tests/integration_test.bats +++ b/tests/integration_test.bats @@ -217,6 +217,7 @@ teardown() { cd ${fixturesDir}/ok-with-macros assertGen assertValidSite + assertParGrep example assertParGrep module } @@ -243,6 +244,13 @@ teardown() { assertParGrep main } +@test "ignore a file" { + cd ${fixturesDir}/ok-mkdocs-ignore-file + assertGen + assertValidSite + assertFileNotExists test_site/site/hello_world/index.html +} + @test "serve a mkdocs site" { cd ${fixturesDir}/ok-mkdocs-docs assertGen diff --git a/tests/run_integration_tests.sh b/tests/run_integration_tests.sh index 4ed42a61..b10382d6 100755 --- a/tests/run_integration_tests.sh +++ b/tests/run_integration_tests.sh @@ -3,7 +3,7 @@ set -e sudo apt-get install bats pip install -e . pip install mkdocs-macros-plugin mkdocstrings mkdocstrings-python-legacy mkdocs-material -# md file="test.snippet" +# md file="test.snippet" content="^#?\s?(.*)" # ### Integration tests # # Integration testing allows the plugin to be tested with mkdocs using example diff --git a/tests/run_linters.sh b/tests/run_linters.sh index a5d3aff5..6f2a4b62 100755 --- a/tests/run_linters.sh +++ b/tests/run_linters.sh @@ -1,7 +1,7 @@ #!/bin/bash set -e pip install flake8 pydocstyle -# md file="test.snippet" +# md file="test.snippet" content="^#?\s?(.*)" # ### Lint # # Linting helps maintain style consistency. This package follows the [google diff --git a/tests/run_tests_local.sh b/tests/run_tests_local.sh index 2a3f4569..d84c1283 100755 --- a/tests/run_tests_local.sh +++ b/tests/run_tests_local.sh @@ -1,5 +1,5 @@ #!/bin/bash -# md file="test.snippet" +# md file="test.snippet" content="^#?\s?(.*)" # ### Different Python versions # # You can even test the package with different versions of python in a container diff --git a/tests/run_unit_tests.sh b/tests/run_unit_tests.sh index d9e54a1f..afc693be 100755 --- a/tests/run_unit_tests.sh +++ b/tests/run_unit_tests.sh @@ -1,7 +1,7 @@ #!/bin/bash set -e pip install -e . -# md file="test.snippet" +# md file="test.snippet" content="^#?\s?(.*)" # ### Unit tests # # Unit tests help ensure individual functions perform as expected. Unit tests diff --git a/tests/test_semiliterate.py b/tests/test_semiliterate.py index fc413ee8..baccc51c 100755 --- a/tests/test_semiliterate.py +++ b/tests/test_semiliterate.py @@ -177,7 +177,7 @@ def test_set_output_stream_new(self): self.output_mock.file_name = "test_name" self.output_mock.file_directory = "/test/dir/" - self.test_stream.set_output_stream("new_name.snippet") + self.test_stream.set_output_file("new_name.snippet") self.output_mock.close.assert_called_once() self.assertEqual( self.test_stream.output_stream.file_name, "new_name.snippet") @@ -186,7 +186,7 @@ def test_set_output_stream_same(self): """Setting the output stream to the same file should do nothing.""" self.output_mock.file_name = "test_name" self.output_mock.file_directory = "/test/dir/" - self.test_stream.set_output_stream("test_name") + self.test_stream.set_output_file("test_name") self.output_mock.close.assert_not_called()