[feature request] Improve Include-Page tag to pull only specific content #1832
Replies: 9 comments
-
Thanks for submitting this request. Based on how Just going to write out my thoughts so far below. I'm also not sure practically how we'd implement this from a user experience point of view. I think that the proposed feature could be more error prone for writers and editors. Right now the I personally see the atomic stub articles that |
Beta Was this translation helpful? Give feedback.
-
This is to elaborate a bit on why this would potentially be quite complex, even in a custom macro. The feature would require the at least partial rendering of the included page. Without a rendered document, we do not have any headings (html Bottom line is: yes, if there are other ways of improving your workflow, that would be much preferable. :) |
Beta Was this translation helpful? Give feedback.
-
Thank you very much for commenting back and explaining your point of view in detail. I am sorry for my noob point of view, but I was thinking you need to parse the source *.md files anyway to convert them to html. Also, I believed such parsing is required when building the TOC or dealing with the anchors. So my hope was you can re-use this feature and use it for enhancing the include tag easily. So, sorry to hear that this might not be done, but was worth a try :) Regarding my use case: I am writing documentation for more generic topics first (e.g. networking) which makes sense to read/structure in a single page to have the whole context and to understand the topic easily by reading from top to bottom. This page on its own is useful. In another part of the documentation I write how-to guides which refer and use parts of the generic documentation and I use include for that. Without the enhanced feature now I need to to the following:
The 1st step would not be required with the new functionality, but more than that there is another advantage: It's hard to edit the atomic bits and pieces, because it makes sense to read the generic documentation assembled in step 2 to understand and validate the content in the full context. When an update is required, I need to find and open the included atomic page and edit it there. Having it in one page would be easy to edit in place of the generic page, where the whole text is reviewed. |
Beta Was this translation helpful? Give feedback.
-
Thanks for explaining further! In my own career as a technical writer (which, it's worth mentioning, didn't include my writing very much generic or reusable documentation), much of the shareable pieces of writing ended up not being shared, because it was too complicated to share it across a documentation project in a sophisticated way–even when using my team's preferred documentation writing software MadCap Flare (a piece of software I would recommend no one ever use!!!). Based on what you've outlined, I think a custom macro for your project could be possible. But I don't know how we could formalize it into a proper feature yet. I would want to survey more people heavily using the That said, here is a custom macro that crudely implements what you're describing:
How does this work? If you have a page with the name "Snippets" (for me:
And then, on other pages, call the snippet macro:
On save, it loads the snippet. |
Beta Was this translation helpful? Give feedback.
-
Thank you for your approach. I believe this would be helpful and I tried to implement it. When following your example (adding the two pages, copying the content into it and activating the macro):
Update: After a second restart of Gollum the macro is not having an error anymore, but its pulling both snippets. The output on
So, the closing brackets of snippet one seem not to be recognized. Also markdown-formatting is not respected, so writing Also, on Also, if I get your example right, the name of the page to source the snippets from is hard-coded into the macro. So it's only looking on "Snippets", but not on any other pages? -> I have figured out how to make this with a variable :) |
Beta Was this translation helpful? Give feedback.
-
Yes, this was absolutely a crude example I made in five minutes. And unfortunately my regular expression failed more than I thought it would. 😞 But it sounds like you’re already tweaking this and making it more suitable for your use case? If you know what Markdown rendering gem your Gollum instance uses (the default is |
Beta Was this translation helpful? Give feedback.
-
I started to customize it a bit, but my coding knowledge is very basic and I don't have any experience with Ruby, so it will be hard for me. I added an argument for the pagename to the macro and tried to adopt the regular expression to be more generic, but this is also a challenge for me. My current version is:
Calling Example
This delivers from the 2nd level heading With this mechanism also no special patterns are required in the source text. What is now missing for me is the conversion to html. I changed the markdown engine to github, because with kramdown I had issues with tables and unfortunately have no idea how to convert to html output. So, thank you for the jumpstart with the Macro which clearly points me to the right direction and would be a suitable solution for me. Unfortunately my skills are not sufficient to develop a full solution on my own. I'll try to educate myself in Ruby, but if your time allows it and it's not too much effort for you, I would appreciate a little more help here. |
Beta Was this translation helpful? Give feedback.
-
Conveniently, there is one handy file in the It sounds like you're using the module Gollum
class Macro
class Snippet < Gollum::Macro
def render(page_name, snippet_name, head_level)
find_snippet(page_name, snippet_name, head_level)
end
private
def find_snippet(page_name, snippet_name, head_level)
snippet_body_regex = /^#{snippet_name}(.*)\#{#{head_level}}/m
if (match = snippets(page_name).match(snippet_body_regex))
render_html(match.captures.first)
else
"[ERR] include not found!"
end
end
def render_html(match)
GitHub::Markdown.render(match)
end
def snippets(page_name)
@wiki.pages.detect { |page| page.name == "#{page_name}" }.text_data
end
end
end
end Perhaps there is another set of arguments that are more ergonomic for you than Because there is no special patterns required in the source text, it means if you ever come up with a different macro, or maybe would like a suite of macros that all do slightly different things, you're in luck. |
Beta Was this translation helpful? Give feedback.
-
A big thank you from my side. I have managed to find a good solution with your helping hand. At the end I came up with the following Macro, which I will test now in my real world scenarios: # Purpose of this macro:
# Include a section from another page in place where the macro is called
# Limitations:
# Only working with GitHub::Markdown gem
#
# page_name = Name of the Page without suffix (no .md)
# search_start = A string to search for in the unrendered document
# search_end = A string to stop searching or "" (empty) to continue until the end of the page
# include_start = render the search_text (true) or exclude (false)
#
# The search strings need to be at the beginning of a line
#
# Example 1: <<IncludeSection("myPage", "# Introduction", "##", true)>>
# This will include from myPage the 1st level Heading "Introduction" and stops, when a 2nd level heading is found
#
# Example 2: <<IncludeSection("myPage", "## Epilog", "", false)>>
# This will include from myPage after the 2nd level Heading "Epilog" (but not rendering the heading) until the end of the page
module Gollum
class Macro
class IncludeSection < Gollum::Macro
def render(page_name, search_start, search_end="", include_start=false)
find(page_name, search_start, search_end, include_start)
end
private
def find(page_name, search_start, search_end, include_start)
if include_start
regex = "(^#{search_start}"
else
regex = "^#{search_start}("
end
if search_end != ""
regex += ".*?)(^#{search_end}\s)"
else
regex += ".*)"
end
rx = /#{regex}/mi
if get_data(page_name) =~ rx
render_html($1)
else
"[ERR] include not found with pattern<br>#{regex}"
end
end
def render_html(match)
GitHub::Markdown.render(match)
end
def get_data(page_name)
@wiki.pages.detect { |page| page.name == "#{page_name}" }.text_data
end
end
end
end How does it work? The user specifies a name of the page to look for as well as a start string and an end string. Everything between these two strings will be included. By default the start string is not included, but when it's a heading (like in many of my use case), it can be rendered by setting a parameter to true. With this I can select to include the original heading or define my own and just take the running text. Also, if an empty end string is given, the page is rendered until the end of the page. Function wise the magic is in the I am sure there is a more elegant solution. Also, I think it's not bulletproof. But for my needs it seem to work and if I find any improvements I will update it here. |
Beta Was this translation helpful? Give feedback.
-
I love Gollum for the include-tag feature (https://github.com/gollum/gollum/wiki#include-tag), because it allows me to assemble and re-use information I have already written down somehwere else. When updating the source of the included information, automatically all other pages using that information are up-to-date immediately 👍
To be flexible and make full use of that feature, a lot of pages with only small content need to be created and then included in larger pages (in my case setup guides). So, I end up with many atomic pages and little content on each page. Many information blocks build-up on previous ones and would be good to have them on one page together (for editing, review). But, it makes not always sense to include all of it in another page. An improved include-tag with a parameter to select only a block of the page would be a great improvement.
My proposal:
The content is identified either from bookmark to the next bookmark or from the level of the heading to the next same level.
Beta Was this translation helpful? Give feedback.
All reactions