Repository: mikeckennedy/markdown-subtemplate

Issue:
Allow defining a variable to be subsequently passed to import sections
Here's what I have in mind. We have a landing page and want to specify which campaign this is about all the while reusing most of the content:

```markdown
# The landing page title

Welcome people from this campaign

[VARIABLE name=value]

[IMPORT section1] # {name: value} is added to the variables passed here.
[IMPORT section2]
[IMPORT section3]
```

Discussion:

Patch:
diff --git a/markdown_subtemplate/__init__.py b/markdown_subtemplate/__init__.py
index 82b3d4f..e1fe900 100644
--- a/markdown_subtemplate/__init__.py
+++ b/markdown_subtemplate/__init__.py
@@ -3,7 +3,7 @@ markdown_subtemplate - A template engine to render
 Markdown with external template imports and variable replacements.
 """
 
-__version__ = '0.1.20'
+__version__ = '0.2.21'
 __author__ = 'Michael Kennedy <michael@talkpython.fm>'
 __all__ = []
 
diff --git a/markdown_subtemplate/infrastructure/page.py b/markdown_subtemplate/infrastructure/page.py
index d4e8d94..0f9a67e 100644
--- a/markdown_subtemplate/infrastructure/page.py
+++ b/markdown_subtemplate/infrastructure/page.py
@@ -7,6 +7,7 @@ from markdown_subtemplate.infrastructure import markdown_transformer
 from markdown_subtemplate.exceptions import ArgumentExpectedException, TemplateNotFoundException
 from markdown_subtemplate import logging as __logging
 import markdown_subtemplate.storage as __storage
+from markdown_subtemplate.logging import SubtemplateLogger
 from markdown_subtemplate.storage import SubtemplateStorage
 
 
@@ -37,11 +38,14 @@ def get_page(template_path: str, data: Dict[str, Any]) -> str:
 
     # Get the markdown with imports and substitutions
     markdown = get_markdown(template_path)
+    inline_variables = {}
+    markdown = get_inline_variables(markdown, inline_variables, log)
     # Convert markdown to HTML
     html = get_html(markdown)
 
     cache.add_html(key, key, html)
-    html = process_variables(html, data)
+    full_data = {**data, **inline_variables}
+    html = process_variables(html, full_data)
 
     dt = datetime.datetime.now() - t0
 
@@ -174,3 +178,42 @@ def process_variables(raw_text: str, data: Dict[str, Any]) -> str:
         transformed_text = transformed_text.replace(key_placeholders[key], str(data[key]))
 
     return transformed_text
+
+
+def get_inline_variables(markdown: str, new_vars: Dict[str, str], log: SubtemplateLogger) -> str:
+    lines: List[str] = markdown.split('\n')
+    pattern = '[VARIABLE '
+
+    final_lines = []
+
+    for l in lines:
+
+        if not( l and l.upper().startswith(pattern)):
+            final_lines.append(l)
+            continue
+
+        text = l[len(pattern):].strip("]")
+        parts = text.split('=')
+        if len(parts) != 2:
+            log.error(f"Invalid variable definition in markdown: {l}.")
+            continue
+
+        name = parts[0].strip().upper()
+        value = parts[1].strip()
+        has_quotes = (
+            (value.startswith('"') or value.startswith("'")) and
+            (value.endswith('"') or value.endswith("'"))
+        )
+
+        if not has_quotes:
+            log.error(f"Invalid variable definition in markdown, missing quotes surrounding value: {l}.")
+            continue
+
+        value = value.strip('\'"').strip()
+
+        new_vars[name]=value
+
+    if new_vars:
+        return "\n".join(final_lines)
+    else:
+        return markdown


Test patch:
diff --git a/tests/page_tests.py b/tests/page_tests.py
index 419223e..403be3b 100644
--- a/tests/page_tests.py
+++ b/tests/page_tests.py
@@ -2,10 +2,10 @@ import os
 
 import pytest
 
-from markdown_subtemplate import exceptions
 from markdown_subtemplate import engine
-from markdown_subtemplate.storage.file_storage import FileStore
+from markdown_subtemplate import exceptions
 from markdown_subtemplate.infrastructure import page
+from markdown_subtemplate.storage.file_storage import FileStore
 
 FileStore.set_template_folder(
     os.path.join(os.path.dirname(__file__), 'templates'))
@@ -46,7 +46,6 @@ We have a paragraph with [a link](https://talkpython.fm).
 def test_basic_markdown_html():
     template = os.path.join('home', 'basic_markdown.md')
     html = engine.get_page(template, {'a': 1, 'b': 2})
-    print("HTML", html)
 
     text = '''
 <h1>This is the basic title</h1>
@@ -147,6 +146,23 @@ And more inline **content**.
     assert text == md.strip()
 
 
+def test_variable_definition_markdown():
+    template = os.path.join('home', 'variables.md')
+    html = page.get_page(template, {})
+
+    text = '''
+<h1>This page defines a variable.</h1>
+
+<p>We have a paragraph with <a href="https://talkpython.fm">a link</a>.</p>
+
+<h3>This page had a title set: Variables rule!</h3>
+
+<p>And more content with the word TITLE.</p>
+'''.strip()
+
+    assert text == html.strip()
+
+
 def test_no_lowercase_replacements_markdown():
     template = os.path.join('home', 'replacements_case_error.md')
     md = page.get_markdown(template, {'title': 'the title', 'link': 'The link'})
diff --git a/tests/templates/home/variables.md b/tests/templates/home/variables.md
new file mode 100644
index 0000000..afbdf24
--- /dev/null
+++ b/tests/templates/home/variables.md
@@ -0,0 +1,7 @@
+# This page defines a variable.
+
+We have a paragraph with [a link](https://talkpython.fm).
+
+[VARIABLE title="Variables rule!"]
+
+[IMPORT REPLACEMENTS]