问题
I am building a website with Middleman. I am storing a lot of information in data files, as I am going to use the same information on multiple pages. (Partials wouldn't work for me, as same text from data can be used with different HTML tags or be slightly modified for different pages.)
I want to write markdown in data files and then use it within HAML templates for specific pages. When I try to create relative links to other pages while using a reference to other data file, resulting HTML is not what it should be.
data/pages.yaml
:
pageA:
link: /it-can-change-A.html
name: PageA name
info: Some other related info
pageB:
link: /subject-to-change-B.html
name: PageB name
info: Some other related info
pageC:
link: /some-C.html
name: PageC name
info: Some other related info
data/faq.yaml
:
testcase: Some text with [internal link to page A](ref.pageA). And *another* [internal reference](ref.pageB).
verbatim: Some text with [internal link to page A](/it-can-change-A.html). And *another* [internal reference](/subject-to-change-B.html).
While trying to find the root cause of this issue, I have tested various ways to "extract" relative links from the data file and put them in the HAML template. My end goal is to get the case (5) to work.
I commented on the results of each piece of code directly in my test.html.md.erb.haml
:
Please note that HAML has to be processed before ERB, so .haml needs to be the last extension. If .erb and .haml extensions switch places, case (3) and (4) below will produce different output.
/ Pure ERB; ERB is processed before markdown => :)
(1) This is just some text with [ERB link to first page](<%= data.pages.pageA.link %>) and *another* one [to second page](<%= data.pages.pageB.link %>).
/ ERB inside HAML tag; markdown is not processed => :|
.haml
(2) This is just some text with [ERB link to first page](<%= data.pages.pageA.link %>) and *another* one [to second page](<%= data.pages.pageB.link %>).
/ Helper used WITHOUT a tag; ERB is processed before markdown => :)
(3)
= refonly(data.faq.testcase)
/ Helper used WITH a tag; ERB is processed, but markdown is not => :|
.question1
(4)
= refonly(data.faq.testcase)
/ "Tilt-powered" helper used WITHIN a tag; trying to process markdown with Tilt results in "%=%20data.pages.pageA.link%20%" links. Expected behavior: ERB should be processed first, then Tilt should process markdown with actual relative links being the same as in .question1 above => :(
.question2
(5)
= mymarkdown(data.faq.testcase)
/ Helper with Tilt to process verbatim text; markdown is processed correctly => :)
.question3
(6)
= justmarkdown(data.faq.verbatim)
Helpers used in template above:
def refonly(text)
text.gsub(/ref\.(page[A-Z])/,"<\%= data.pages.\\1.link %>")
end
def mymarkdown(text)
newtext = refonly(text)
Tilt['markdown'].new(context: @app) { newtext }.render
end
def justmarkdown(text)
Tilt['markdown'].new(context: @app) { text }.render
end
The purpose of the first helper is to change easy-to-write reference inside data file (ref.pageName) to ERB code, same as one used in (1). The purpose of the second helper is to render markdown in the case where .md
template extension itself fails to render it automatically. The purpose of the last helper is to show that Tilt can render verbatim text properly in (6), but it when it accepts same text as a variable, it can't provide same output in (5).
A. When I use "pure ERB" (1), or refonly
helper without HAML tag (3), output is as expected: relative path is sourced from data file and then markdown is processed by default markdown engine (kramdown) thanks to .md
template extension.
B. When I try to use HAML tag, either directly with ERB code (2), or with refonly
helper (4), ERB is processed correctly and put into the output. However, markdown is not processed for some reason automatically, even though .md
extension is used directly after .html
, hence markdown should be processed after HAML and ERB bits are finished.
C. In order to "force" markdown rendering, I am using Tilt in my second helper. My intention was to pass text returned by refonly
(which has correct markdown syntax with intended link extracted from data) to Tilt. My expectation was that Tilt would simply render verbatim text passed to it in (5), just as it does in (6). Instead, resulting link points to %=%20data.pages.pageA.link%20%
, which seems to be HTML code to display ERB code verbatim. So, it looks like passing newtext
variable to Tilt somehow stops ERB processing and ERB code is passed directly to markdown.
My primary question is: how can I make sure that Tilt gets the proper text with a relative link (as returned by refonly
) and produces expected output in (5)?
My secondary question: why markdown is not processed automatically by Middleman in cases described under B.?
I assume that answer to my primary question requires knowledge of the Ruby and Tilt, while the answer to my secondary question requires knowledge of Middleman. While the solution to my primary issue would be great, answer to the secondary question might allow to skip Tilt altogether and hence solve the problem in an easier way.
回答1:
Since you already have HAML parsing correctly, and when you render verbatim links it works, try using a helper to directly inject the links without needing to go to ERB. Since HAML will already run Ruby code, I see no need to pass it through ERB too. I think eval
will allow you to get the same effect you're using ERB for. Something like this:
def refonly(text)
text.scan(/ref\.(page[A-Z])/).each do |groups|
page_name = groups[0]
text.gsub!(/ref\.#{page_name}/, eval("data.pages.#{page_name}.link"))
end
text
end
EDIT: Scanning the text will allow you to get each page_name so you can loop through each one and replace each page reference with its link.
来源:https://stackoverflow.com/questions/44797695/tilt-kramdown-preventing-erb-processing-when-rendering-markdown