<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>
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 – <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’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’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’s different is that when you transclude a
+file, the search path stays the same as the “parent” 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 “parent” 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>
<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>
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 – <code>{{file}}</code> is used to
+indicate a file that needs to be transcluded. <code>{{file.*}}</code> 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.</p>
+
+<p>When you process a file with <abbr title="MultiMarkdown">MMD</abbr>, it uses that file’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’s different is that when you transclude a
+file, the search path stays the same as the “parent” 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 “parent” 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>
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:
/// 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];
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;
}
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);
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);
stack_free(parse_stack);
}
- free(folder);
+ free(search_folder);
}
/// 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
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
}
// 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
}
<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 – {{foo.txt}}</text:p>
</office:text>
</office:body>
</office:document>
<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 – {{foo.txt}}</p>
+
</body>
</html>
<p>{{transclusion/bat.*}}</p>
<p>{{transclusion/baz.txt}}</p>
+
+<p>{{transclusion/baz2.txt}}</p>
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}.
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}
{{transclusion/bat.*}}
-{{transclusion/baz.txt}}
\ No newline at end of file
+{{transclusion/baz.txt}}
+
+{{transclusion/baz2.txt}}
\ No newline at end of file
--- /dev/null
+Title: bar
+
+This text is included in `transclusion\bar.txt`.
+
+foo can no longer be found -- {{foo.txt}}
-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}}
--- /dev/null
+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}}