-
Notifications
You must be signed in to change notification settings - Fork 135
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Selective Include #338
Comments
I can see this working, I would challenge how “niche” this use case is, though. What would you be using this for in practice? |
This useage would be nice, to document in some kind, how templates can/should be used for. Another example is, to keep some cross linked documentation. I imagine autogenerated system documentation for some servers. Every server has distinct aspects hat should be described. But maybe I want some of the aspects of all the hosts summarized together in an overview page. Having the aspects marked as sections, I can pull them to different overview pages via a query. (and I see a next FeatureRequest incoming, with "parameters for templates" ;) ) |
I came across the same use-case but didn't know about this issue. My thoughts on that (see also Discord):
|
Basic implementation with Space Script: silverbullet.registerFunction("templateSection", async (link) => {
const linkregex = /\[\[(.*?)#(#*)(.*?)\]\]/
const name = link.match(linkregex)[1]
const heading = link.match(linkregex)[3]
const pageContent = await syscall("space.readPage", name);
const md = await syscall("markdown.parseMarkdown", pageContent);
const yamlAsList = await getMdAsList(md.children);
let positionOfMatchedHeader;
let positionOfEndSection;
for (let i = 0; i < yamlAsList.length; i++) {
let item = yamlAsList[i];
if (item.type) {
if (item.type.startsWith('ATXHeading')) {
if (positionOfMatchedHeader | positionOfMatchedHeader === 0) {
positionOfEndSection = item.from;
break;
}
let yamlofheadingaslist = await getMdAsList(item.children);
let textOfItem = await parseMdHeadingContent(yamlofheadingaslist);
if (textOfItem && textOfItem === heading) {
positionOfMatchedHeader = item.from;
}
}
}
}
return pageContent.substring(positionOfMatchedHeader, positionOfEndSection);
async function parseMdHeadingContent(children) {
for (let i = 0; i < children.length; i++) {
let item = children[i];
if (item.type) {
if (item.type === 'WikiLink') {
return parseMdWikiLinkContent(item.children);
}
}
}
return children[1].text.substring(1);
}
function parseMdWikiLinkContent(children) {
let indexOfContent;
for (let i = 0; i < children.length; i++) {
let item = children[i];
if (item.type) {
if (item.type === 'WikiLinkAlias') {
indexOfContent = i;
break;
}
}
}
if (!indexOfContent) {
for (let i = 0; i < children.length; i++) {
let item = children[i];
if (item.type) {
if (item.type === 'WikiLinkPage') {
indexOfContent = i;
break;
}
}
}
}
return children[indexOfContent].children[0].text;
}
async function getMdAsList(childrenYaml) {
const yaml = await syscall("yaml.stringify", childrenYaml);
const yamlAsList = await syscall("yaml.parse", yaml);
return yamlAsList;
}
}) Fetches page content after a header until the next header. (therefore also stops at subheaders). One limitation is that it will always choose the first match it finds if you are matching a header and there are two headers with the same text. Using a link for the argument, makes Silverbullet register it as a link, so that if it breaks you can see it on the maintenance page. template:
command template:
I haven't tested it much. Let me know if you find any issues. |
I have another use case for this, I'm moving my recipes to silverbullet, some recipes need another one, e.g. cannelloni would need one recipe for the pasta/pancakes and one for the filling. I could include the whole file (which is what I'm doing now) but including just parts of it would let me be more organized to for example have the page show: # Ingredients
## Pancake
\```template
{{template([[internal-template/today]], "ingredients")}}
\```
...
## Filling
* Minced Beef
# Preparation
## Pancake
\```template
{{template([[internal-template/today]], "preparation")}}
\```
## Filling
Fry the beef... I'm not entirely sure how to do the definition of the "ingredients" and "preparation", I like the idea of anchoring the header as a simple solution, but the proposed comment for start and end of a section are lot more generic so I think they're better. That being said I'm not a fan of the HTML comment syntax, and I would personally prefer a simpler syntax, e.g. # Ingredients
{% ingredients %}
* 1Kg flour
...
{% /ingredients %}
# Preparation
{% preparation %}
Mix the ingredients...
{% /preparation %} Other ideas could include |
You should be able to adapt my example to be more like what was suggested in the OP or your own suggestion. Personally, I just wanted to be able to refer to a subheading. |
Sorry, yeah, I started writing that comment before you posted that, I'll try that if it works for a header it should be easy to adapt to work with any of the syntaxes I proposed. Thanks. |
For anyone else reading, I've adapted @henrikx script to work with the silverbullet.registerFunction("pageSection", async (page, section) => {
const start_section = "{{ " + section + " }}";
const end_section = "{{ /" + section + " }}";
const start_pos = page.indexOf(start_section)+ start_section.length;
const end_pos = page.indexOf(end_section);
if (start_pos == -1 || end_pos == -1){
return `**Error**: Could not find section ${section}`;
}
return page.substring(start_pos, end_pos);
}) It's not perfect because imported blocks lose their highlight for code and the templates get reprocessed (although that might be desirable). |
Clever stuff. One syntax suggestion to consider instead of |
I still see them rendered in the page though @zefhemel but in any case I've updated mine locally to use the HTML comment syntax because the one I used there had problems when I created a template that tried to use them since they are valid syntax inside of a template. Is there any way that I can make the comments be collapsed or somewhat hidden by default on pages until I get to them with a cursor? I think that would make this even sweeter since then they're not visible by default on the page where they're defined. |
@Nibodhika: What's about this? It's toggled
|
Issue
Allow for include to only include specific parts of a page
description
Make it possible to only include specific parts of an page.
This could be made possible, by markup in the included page:
Example:
included_page.md
including_page.md
notice
include_range
then the result is the whole page (backward compatibility)include_range
without a section name, then the result is this sectioninclude_range
s with section names, then the result will be all the sections with that name in the order they appear in the included pageThe text was updated successfully, but these errors were encountered: