]> granicus.if.org Git - multimarkdown/commitdiff
FIXED: Improve transclude base overriding of search paths, and explain change in...
authorFletcher T. Penney <fletcher@fletcherpenney.net>
Fri, 24 Mar 2017 18:34:37 +0000 (14:34 -0400)
committerFletcher T. Penney <fletcher@fletcherpenney.net>
Fri, 24 Mar 2017 18:34:37 +0000 (14:34 -0400)
16 files changed:
QuickStart/QuickStart.epub
QuickStart/QuickStart.fodt
QuickStart/QuickStart.html
QuickStart/QuickStart.pdf
QuickStart/QuickStart.txt
Sources/libMultiMarkdown/transclude.c
Sources/libMultiMarkdown/transclude.h
Sources/multimarkdown/main.c
tests/MMD6Tests/Transclusion.fodt
tests/MMD6Tests/Transclusion.html
tests/MMD6Tests/Transclusion.htmlc
tests/MMD6Tests/Transclusion.tex
tests/MMD6Tests/Transclusion.text
tests/MMD6Tests/transclusion/bar.txt [new file with mode: 0644]
tests/MMD6Tests/transclusion/baz.txt
tests/MMD6Tests/transclusion/baz2.txt [new file with mode: 0644]

index 8d41766ef4bd7bc412761580974a4d2ccd80b45e..640f663be65e38b9e571d42a7db7da2106b2a238 100644 (file)
Binary files a/QuickStart/QuickStart.epub and b/QuickStart/QuickStart.epub differ
index f6dca727f27df2a9319c04c50bdd5fc8de71a97f..f2c96b263b7a43c89ef37606f9c457917fb14c8e 100644 (file)
 <text:p text:style-name="TOC_Item"><text:a xlink:type="simple" xlink:href="#internationalization" text:style-name="Index_20_Link" text:visited-style-name="Index_20_Link">Internationalization  <text:tab/>1</text:a></text:p>
 <text:p text:style-name="TOC_Item"><text:a xlink:type="simple" xlink:href="#metadata" text:style-name="Index_20_Link" text:visited-style-name="Index_20_Link">Metadata  <text:tab/>1</text:a></text:p>
 <text:p text:style-name="TOC_Item"><text:a xlink:type="simple" xlink:href="#tableofcontents" text:style-name="Index_20_Link" text:visited-style-name="Index_20_Link">Table of Contents  <text:tab/>1</text:a></text:p>
+<text:p text:style-name="TOC_Item"><text:a xlink:type="simple" xlink:href="#transclusion" text:style-name="Index_20_Link" text:visited-style-name="Index_20_Link">Transclusion  <text:tab/>1</text:a></text:p>
 <text:p text:style-name="TOC_Item"><text:a xlink:type="simple" xlink:href="#futuresteps" text:style-name="Index_20_Link" text:visited-style-name="Index_20_Link">Future Steps  <text:tab/>1</text:a></text:p>
 </text:index-body>
 </text:table-of-content>
@@ -564,6 +565,93 @@ generated Table of Contents in your document. As of MMD v6, the native
 Table of Contents functionality is used when exporting to LaTeX or
 OpenDocument formats.</text:p>
 
+<text:h text:outline-level="4"><text:bookmark text:name="transclusion"/>Transclusion </text:h>
+
+<text:p text:style-name="Standard">File transclusion works basically the same way &#8211; <text:span text:style-name="Source_20_Text">{{file}}</text:span> is used to
+indicate a file that needs to be transcluded. <text:span text:style-name="Source_20_Text">{{file.*}}</text:span> allows for
+wildcard transclusion. What&#8217;s different is that the way search paths are
+handled is more flexible, though it may take a moment to understand.</text:p>
+
+<text:p text:style-name="Standard">When you process a file with MMD, it uses that file&#8217;s directory as the search
+path for included files. For example:</text:p>
+
+<table:table>
+<table:table-column/>
+<table:table-column/>
+<table:table-column/>
+
+<table:table-row>
+<table:table-cell>
+<text:p text:style-name="Table_20_Heading"> Directory </text:p>
+</table:table-cell>
+<table:table-cell>
+<text:p text:style-name="Table_20_Heading"> Transcluded Filename </text:p>
+</table:table-cell>
+<table:table-cell>
+<text:p text:style-name="Table_20_Heading"> Resolved Path  </text:p>
+</table:table-cell>
+</table:table-row>
+
+<table:table-row>
+<table:table-cell>
+<text:p text:style-name="MMD-Table"> <text:span text:style-name="Source_20_Text">/foo/bar/</text:span> </text:p>
+</table:table-cell>
+<table:table-cell>
+<text:p text:style-name="MMD-Table"> <text:span text:style-name="Source_20_Text">bat</text:span>    </text:p>
+</table:table-cell>
+<table:table-cell>
+<text:p text:style-name="MMD-Table"> <text:span text:style-name="Source_20_Text">/foo/bar/bat</text:span>  </text:p>
+</table:table-cell>
+</table:table-row>
+<table:table-row>
+<table:table-cell>
+<text:p text:style-name="MMD-Table"> <text:span text:style-name="Source_20_Text">/foo/bar/</text:span> </text:p>
+</table:table-cell>
+<table:table-cell>
+<text:p text:style-name="MMD-Table"> <text:span text:style-name="Source_20_Text">baz/bat</text:span>   </text:p>
+</table:table-cell>
+<table:table-cell>
+<text:p text:style-name="MMD-Table"> <text:span text:style-name="Source_20_Text">/foo/bar/baz/bat</text:span> </text:p>
+</table:table-cell>
+</table:table-row>
+<table:table-row>
+<table:table-cell>
+<text:p text:style-name="MMD-Table"> <text:span text:style-name="Source_20_Text">/foo/bar/</text:span> </text:p>
+</table:table-cell>
+<table:table-cell>
+<text:p text:style-name="MMD-Table"> <text:span text:style-name="Source_20_Text">../bat</text:span>    </text:p>
+</table:table-cell>
+<table:table-cell>
+<text:p text:style-name="MMD-Table"> <text:span text:style-name="Source_20_Text">/foo/bat</text:span>   </text:p>
+</table:table-cell>
+</table:table-row>
+
+</table:table>
+
+
+<text:p text:style-name="Standard">This is the same as MMD v 5. What&#8217;s different is that when you transclude a
+file, the search path stays the same as the &#8220;parent&#8221; file, <text:span text:style-name="MMD-Bold">UNLESS</text:span> you use
+the <text:span text:style-name="Source_20_Text">transclude base</text:span> metadata to override it. The simplest override is:</text:p>
+
+<text:p text:style-name="Preformatted Text">transclude base: .<text:line-break/></text:p>
+
+<text:p text:style-name="Standard">This means that any transclusions within the file will be calculated relative
+to the file, regardless of the original search path.</text:p>
+
+<text:p text:style-name="Standard">Alternatively you could specify that any transclusion happens inside a
+subfolder:</text:p>
+
+<text:p text:style-name="Preformatted Text">transclude base: folder/<text:line-break/></text:p>
+
+<text:p text:style-name="Standard">Or you can specify an absolute path:</text:p>
+
+<text:p text:style-name="Preformatted Text">transclude base: /some/path<text:line-break/></text:p>
+
+<text:p text:style-name="Standard">This flexibility means that you can transclude different files based on
+whether a file is being processed by itself or as part of a &#8220;parent&#8221; file.
+This can be useful when a particular file can either be a standalone document,
+or a chapter inside a larger document.</text:p>
+
 <text:h text:outline-level="3"><text:bookmark text:name="futuresteps"/>Future Steps </text:h>
 
 <text:p text:style-name="Standard">Some features I plan to implement at some point:</text:p>
index 969ae7a89bfed00e5442a5de38467bd562b4da66..7735901f8483a79721f199625b4d7999d3869afe 100644 (file)
@@ -27,6 +27,7 @@
 <li><a href="#internationalization">Internationalization </a></li>
 <li><a href="#metadata">Metadata </a></li>
 <li><a href="#tableofcontents">Table of Contents </a></li>
+<li><a href="#transclusion">Transclusion </a></li>
 </ul>
 </li>
 <li><a href="#futuresteps">Future Steps </a></li>
@@ -281,6 +282,76 @@ generated Table of Contents in your document. As of <abbr title="MultiMarkdown">
 Table of Contents functionality is used when exporting to LaTeX or
 OpenDocument formats.</p>
 
+<h4 id="transclusion">Transclusion </h4>
+
+<p>File transclusion works basically the same way &#8211; <code>{{file}}</code> is used to
+indicate a file that needs to be transcluded. <code>{{file.*}}</code> allows for
+wildcard transclusion. What&#8217;s different is that the way search paths are
+handled is more flexible, though it may take a moment to understand.</p>
+
+<p>When you process a file with <abbr title="MultiMarkdown">MMD</abbr>, it uses that file&#8217;s directory as the search
+path for included files. For example:</p>
+
+<table>
+<colgroup>
+<col />
+<col />
+<col />
+</colgroup>
+
+<thead>
+<tr>
+       <th> Directory </th>
+       <th> Transcluded Filename </th>
+       <th> Resolved Path  </th>
+</tr>
+</thead>
+
+<tbody>
+<tr>
+       <td> <code>/foo/bar/</code> </td>
+       <td> <code>bat</code>    </td>
+       <td> <code>/foo/bar/bat</code>  </td>
+</tr>
+<tr>
+       <td> <code>/foo/bar/</code> </td>
+       <td> <code>baz/bat</code>   </td>
+       <td> <code>/foo/bar/baz/bat</code> </td>
+</tr>
+<tr>
+       <td> <code>/foo/bar/</code> </td>
+       <td> <code>../bat</code>    </td>
+       <td> <code>/foo/bat</code>   </td>
+</tr>
+</tbody>
+</table>
+
+<p>This is the same as <abbr title="MultiMarkdown">MMD</abbr> v 5. What&#8217;s different is that when you transclude a
+file, the search path stays the same as the &#8220;parent&#8221; file, <strong>UNLESS</strong> you use
+the <code>transclude base</code> metadata to override it. The simplest override is:</p>
+
+<pre><code>transclude base: .
+</code></pre>
+
+<p>This means that any transclusions within the file will be calculated relative
+to the file, regardless of the original search path.</p>
+
+<p>Alternatively you could specify that any transclusion happens inside a
+subfolder:</p>
+
+<pre><code>transclude base: folder/
+</code></pre>
+
+<p>Or you can specify an absolute path:</p>
+
+<pre><code>transclude base: /some/path
+</code></pre>
+
+<p>This flexibility means that you can transclude different files based on
+whether a file is being processed by itself or as part of a &#8220;parent&#8221; file.
+This can be useful when a particular file can either be a standalone document,
+or a chapter inside a larger document.</p>
+
 <h3 id="futuresteps">Future Steps </h3>
 
 <p>Some features I plan to implement at some point:</p>
index 00d00e838234522aac1af57b527cb3f089c41857..3472980dc8cd7779bf4682405fe69e31e251aee7 100644 (file)
Binary files a/QuickStart/QuickStart.pdf and b/QuickStart/QuickStart.pdf differ
index 0021f60320d59cefc9b8f4e6db58211d0aa61538..550f911556432df4282cccdf45038c8082a4ce89 100644 (file)
@@ -271,6 +271,47 @@ Table of Contents functionality is used when exporting to LaTeX or
 OpenDocument formats.
 
 
+## Transclusion ##
+
+File transclusion works basically the same way -- `{{file}}` is used to
+indicate a file that needs to be transcluded.  `{{file.*}}` allows for
+wildcard transclusion.  What's different is that the way search paths are
+handled is more flexible, though it may take a moment to understand.
+
+When you process a file with MMD, it uses that file's directory as the search
+path for included files. For example:
+
+| Directory   | Transcluded Filename | Resolved Path      |  
+| ----------- | -------------------- | ------------------ |  
+| `/foo/bar/` | `bat`                | `/foo/bar/bat`     |  
+| `/foo/bar/` | `baz/bat`            | `/foo/bar/baz/bat` |  
+| `/foo/bar/` | `../bat`             | `/foo/bat`         |  
+
+
+This is the same as MMD v 5.  What's different is that when you transclude a
+file, the search path stays the same as the "parent" file, **UNLESS** you use
+the `transclude base` metadata to override it.  The simplest override is:
+
+       transclude base: .
+
+This means that any transclusions within the file will be calculated relative
+to the file, regardless of the original search path.  
+
+Alternatively you could specify that any transclusion happens inside a
+subfolder:
+
+       transclude base: folder/
+
+Or you can specify an absolute path:
+
+       transclude base: /some/path
+
+This flexibility means that you can transclude different files based on
+whether a file is being processed by itself or as part of a "parent" file.
+This can be useful when a particular file can either be a standalone document,
+or a chapter inside a larger document.
+
+
 # Future Steps #
 
 Some features I plan to implement at some point:
index 53f0f5ddd9e58211fe4627853d6612eae2f1d289..e64724152f2e9b31279a743a9868e2b4bfd11617 100644 (file)
@@ -274,12 +274,12 @@ DString * scan_file(const char * fname) {
 
 /// Recursively transclude source text, given a search directory.
 /// Track files to prevent infinite recursive loops
-void transclude_source(DString * source, const char * dir, short format, stack * parsed, stack * manifest) {
+void transclude_source(DString * source, const char * search_path, const char * source_path, short format, stack * parsed, stack * manifest) {
        DString * file_path;
        DString * buffer;
 
-       // Ensure folder is tidied up
-       char * folder = path_from_dir_base(dir, NULL);
+       // Ensure search_folder is tidied up
+       char * search_folder = path_from_dir_base(search_path, NULL);
 
        char * start, * stop;
        char text[1100];
@@ -289,22 +289,28 @@ void transclude_source(DString * source, const char * dir, short format, stack *
        size_t offset;
        size_t last_match;
 
-       // TODO: Does this source have metadata that overrides the search directory?
        mmd_engine * e = mmd_engine_create_with_dstring(source, EXT_TRANSCLUDE);
        if (mmd_has_metadata(e, &offset)) {
 
                temp = metavalue_for_key(e, "transclude base");
 
                if (temp) {
-                       free(folder);
+                       // The new file overrides the search path
+                       free(search_folder);
 
-                       folder = path_from_dir_base(dir, temp);
+                       // First, calculate path to this source file
+                       char * temp_path = path_from_dir_base(search_path, source_path);
+
+                       // Then, calculate new search path relative to source
+                       search_folder = path_from_dir_base(temp_path, temp);
+
+                       free(temp_path);
                }
        }
 
        mmd_engine_free(e, false);
 
-       if (folder == NULL) {
+       if (search_folder == NULL) {
                // We don't have anywhere to search, so nothing to do
                goto exit;
        }
@@ -348,9 +354,9 @@ void transclude_source(DString * source, const char * dir, short format, stack *
                                file_path = d_string_new(text);
                        } else {
                                // Relative path
-                               file_path = d_string_new(folder);
+                               file_path = d_string_new(search_folder);
 
-                               // Ensure that folder ends in separator
+                               // Ensure that search_folder ends in separator
                                add_trailing_sep(file_path);
 
                                d_string_append(file_path, text);
@@ -419,8 +425,15 @@ void transclude_source(DString * source, const char * dir, short format, stack *
                                d_string_erase(source, start - source->str, 2 + stop - start);
 
                                // Recursively check this file for transclusions
-                               transclude_source(buffer, folder, format, parse_stack, manifest);
+                               char * new_search_path;
+                               char * source_filename;
+                               split_path_file(&new_search_path, &source_filename, file_path->str);
 
+                               transclude_source(buffer, search_folder, new_search_path, format, parse_stack, manifest);
+
+                               free(new_search_path);
+                               free(source_filename);
+                               
                                // Strip metadata from buffer now that we have parsed it
                                e = mmd_engine_create_with_dstring(buffer, EXT_TRANSCLUDE);
                                
@@ -469,7 +482,7 @@ void transclude_source(DString * source, const char * dir, short format, stack *
                stack_free(parse_stack);
        }
 
-       free(folder);
+       free(search_folder);
 }
 
 
index 612cb3ee70dcc28029e196c257148446bb94010a..9dda79aa8eb3a50b257a2082c8b478ba4084047f 100644 (file)
@@ -73,7 +73,7 @@ DString * scan_file(const char * fname);
 
 /// Recursively transclude source text, given a search directory.
 /// Track files to prevent infinite recursive loops
-void transclude_source(DString * source, const char * dir, short format, stack * parsed, stack * manifest);
+void transclude_source(DString * source, const char * search_path, const char * source_path, short format, stack * parsed, stack * manifest);
 
 
 #endif
index ec379c9f9eb5340eabd2ec8a08345e67755ed8e7..9eda9eab8811394437cf0609efdd875266dedb1d 100644 (file)
@@ -340,7 +340,7 @@ int main(int argc, char** argv) {
 
                        if (extensions & EXT_TRANSCLUDE) {
 
-                               transclude_source(buffer, folder, format, NULL, NULL);
+                               transclude_source(buffer, folder, "", format, NULL, NULL);
        
                                // Don't free folder -- owned by dirname
                        }
@@ -417,7 +417,7 @@ int main(int argc, char** argv) {
                        // Perform transclusion(s)
                        char * folder = dirname((char *) a_file->filename[0]);
 
-                       transclude_source(buffer, folder, format, NULL, NULL);
+                       transclude_source(buffer, folder, "", format, NULL, NULL);
 
                        // Don't free folder -- owned by dirname
                }
index 28a5809ed1c13a86ae9bf50dee2af27ab810a561..ea2ac6bbcc9bfa6da7f4d4841796413742682b62 100644 (file)
 
 <text:p text:style-name="Standard">This text is included in <text:span text:style-name="Source_20_Text">transclusion/baz.txt</text:span>.</text:p>
 
-<text:p text:style-name="Standard">This should pull in <text:span text:style-name="Source_20_Text">bar.txt</text:span>, <text:span text:style-name="MMD-Italic">if</text:span> run from the parent directory.</text:p>
+<text:p text:style-name="Standard">This should pull in <text:span text:style-name="Source_20_Text">bar.txt</text:span>, <text:span text:style-name="MMD-Italic">if</text:span> run from the parent directory, since it
+does <text:span text:style-name="MMD-Italic">not</text:span> override the <text:span text:style-name="Source_20_Text">transclude base</text:span> metadata.</text:p>
 
 <text:p text:style-name="Standard">This text is included in <text:span text:style-name="Source_20_Text">bar.txt</text:span>.</text:p>
 
 <text:p text:style-name="Preformatted Text">This is a file with no metadata.<text:line-break/></text:p>
 
 <text:p text:style-name="Preformatted Text">This is a file with no metadata.<text:line-break/></text:p>
+
+<text:p text:style-name="Standard">This text is included in <text:span text:style-name="Source_20_Text">transclusion/baz2.txt</text:span>.</text:p>
+
+<text:p text:style-name="Standard">This should pull in <text:span text:style-name="Source_20_Text">transclusion/bar.txt</text:span>, <text:span text:style-name="MMD-Italic">even if</text:span> run from the parent
+directory, since it overrides the <text:span text:style-name="Source_20_Text">transclude base</text:span> metadata.</text:p>
+
+<text:p text:style-name="Standard">This text is included in <text:span text:style-name="Source_20_Text">transclusion\bar.txt</text:span>.</text:p>
+
+<text:p text:style-name="Standard">foo can no longer be found &#8211; {{foo.txt}}</text:p>
 </office:text>
 </office:body>
 </office:document>
index 27b38194b35818c821476a65c1336994e8300662..2f380d42930e642cbe356876a367b19481c6b265 100644 (file)
@@ -24,7 +24,8 @@
 
 <p>This text is included in <code>transclusion/baz.txt</code>.</p>
 
-<p>This should pull in <code>bar.txt</code>, <em>if</em> run from the parent directory.</p>
+<p>This should pull in <code>bar.txt</code>, <em>if</em> run from the parent directory, since it
+does <em>not</em> override the <code>transclude base</code> metadata.</p>
 
 <p>This text is included in <code>bar.txt</code>.</p>
 
 <pre><code>This is a file with no metadata.
 </code></pre>
 
+<p>This text is included in <code>transclusion/baz2.txt</code>.</p>
+
+<p>This should pull in <code>transclusion/bar.txt</code>, <em>even if</em> run from the parent
+directory, since it overrides the <code>transclude base</code> metadata.</p>
+
+<p>This text is included in <code>transclusion\bar.txt</code>.</p>
+
+<p>foo can no longer be found &#8211; {{foo.txt}}</p>
+
 </body>
 </html>
 
index bdf892dd8a31f55c9892d0031d309fc92a45d572..42523971fb85f6ac29d7a69e94f45b6dc1c1f247 100644 (file)
@@ -8,3 +8,5 @@ latex config:   article</p>
 <p>{{transclusion/bat.*}}</p>
 
 <p>{{transclusion/baz.txt}}</p>
+
+<p>{{transclusion/baz2.txt}}</p>
index d476cd384a08928b96a2e79f1e3644031b580f33..9c2dc64ad3814eab241e0140e0b60e265d730b37 100644 (file)
@@ -22,7 +22,8 @@ This is a file with no metadata.
 
 This text is included in \texttt{transclusion\slash baz.txt}.
 
-This should pull in \texttt{bar.txt}, \emph{if} run from the parent directory.
+This should pull in \texttt{bar.txt}, \emph{if} run from the parent directory, since it
+does \emph{not} override the \texttt{transclude base} metadata.
 
 This text is included in \texttt{bar.txt}.
 
@@ -36,5 +37,14 @@ This is a file with no metadata.
 This is a file with no metadata.
 \end{verbatim}
 
+This text is included in \texttt{transclusion\slash baz2.txt}.
+
+This should pull in \texttt{transclusion\slash bar.txt}, \emph{even if} run from the parent
+directory, since it overrides the \texttt{transclude base} metadata.
+
+This text is included in \texttt{transclusion\textbackslash{}bar.txt}.
+
+foo can no longer be found -- \{\{foo.txt\}\}
+
 \input{mmd6-article-footer}
 \end{document}
index 8b668bcbe8a362c2108787dacf09eed07b69ca85..ca8621962fb0a1a22ffabc1363d9d1ddf570a322 100644 (file)
@@ -7,4 +7,6 @@ latex config:   article
 
 {{transclusion/bat.*}}
 
-{{transclusion/baz.txt}}
\ No newline at end of file
+{{transclusion/baz.txt}}
+
+{{transclusion/baz2.txt}}
\ No newline at end of file
diff --git a/tests/MMD6Tests/transclusion/bar.txt b/tests/MMD6Tests/transclusion/bar.txt
new file mode 100644 (file)
index 0000000..f997d2c
--- /dev/null
@@ -0,0 +1,5 @@
+Title:  bar
+
+This text is included in `transclusion\bar.txt`.
+
+foo can no longer be found -- {{foo.txt}}
index dda0612996d535702ae1c97aa27de7b37c91c082..9eaca8152e57a72c97c5234958c41043603cabba 100644 (file)
@@ -1,7 +1,8 @@
-Title:  bar
+Title:  baz
 
 This text is included in `transclusion/baz.txt`.
 
-This should pull in `bar.txt`, *if* run from the parent directory.
+This should pull in `bar.txt`, *if* run from the parent directory, since it
+does *not* override the `transclude base` metadata.
 
 {{bar.txt}}
diff --git a/tests/MMD6Tests/transclusion/baz2.txt b/tests/MMD6Tests/transclusion/baz2.txt
new file mode 100644 (file)
index 0000000..d3354fd
--- /dev/null
@@ -0,0 +1,9 @@
+Title:  baz
+transclude base: .
+
+This text is included in `transclusion/baz2.txt`.
+
+This should pull in `transclusion/bar.txt`, *even if* run from the parent
+directory, since it overrides the `transclude base` metadata.
+
+{{bar.txt}}