Pass variable from content to layout in Nanoc using Slim - ruby-on-rails

I basically want to know the easiest way to pass a ruby variable from a content page to its layout using Nanoc and Slim. I am thinking of something like this:
content/content.slim:
---
title: Writeups
layout: /layout.slim
---
- age = get_age
layout/layout.slim:
doctype html
html
head
== yield
p I am #{#item[:title]} and am #{#item[:age]} years old
I know how to access values via frontmatter, but frontmatter values are fixed and what I want is a ruby function to find that value for me.

Nanoc provides a capturing helper, which makes it possible to “capture” content in one place and use it somewhere else.
content/content.slim:
---
title: Mister Tree
---
p Hello there!
- content_for :age
| hundreds of years
layout/layout.slim:
doctype html
html
body
== yield
p I am #{#item[:title]} and am #{content_for(#item, :age)} years old
lib/default.rb (or any file in lib/ of your choosing):
use_helper Nanoc::Helpers::Capturing
This generates the following output:
<!DOCTYPE html>
<html>
<body>
<p>Hello there!</p>
<p>I am Mister Tree and am hundreds of years years old</p>
</body>
</html>

Related

How to use HTML tags in Groovy

I am trying to include HTML tags in groovy code, My requirement is to add something like -- thanks and regards (in one line), in next line a image, followed by name (in new line), kindly let me know how I can achieve this.
I have tried below and it didn't worked.
​body: """
Approval is required. Please provide acceptance \n
Visit the below link to approval/decline \n\n
Note This is system generated email
""" + ''' </p><p Regards,</p>src="<image path>" alt="yes"><br><br><b><span
Cloud></b></span><br>myname<br></p>'''​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​, mimeType: 'text/html'
Are you aware of the Groovy MarkupBuilder (https://docs.groovy-lang.org/latest/html/api/groovy/xml/MarkupBuilder.html)?
I would solve your question like:
def writer = new StringWriter()
def markup = new groovy.xml.MarkupBuilder(writer)
markup.html {
head {
title('Approval')
}
body {
mkp.yieldUnescaped('Approval is required. Please provide acceptance<br/>Visit the below link to approval/decline<br/><br/>Note This is system generated email')
p ('Regards,')
img(alt: 'your alt text', src: 'your image url')
p ('YamunaS')
}
}
writer.toString()
​
Which would result in:
<html>
<head>
<title>Approval</title>
</head>
<body>Approval is required. Please provide acceptance<br/>Visit the below link to approval/decline<br/><br/>Note This is system generated email
<p>Regards,</p>
<img alt='your alt text' src='your image url' />
<p>YamunaS</p>
</body>
</html>
And then rendered:
If you want to put the first sentences/lines into a paragraph or div container as well, just follow above way. A div-container would open a new closure again. For a full example including some stylesheets you can also have a look in one of my examples. It generates html dynamically and uses it in context of Springboot (which is probably too much for you now)

How to parse HTML?

I have a table
id txt
1 <html> ... a lot of different html tags
2 <html> ... a lot of different html tags
3 <html> ... a lot of different html tags
How can I parse txt so that I get plain text without all these tags?
If you're on TD14 you might use REGEXP_REPLACE.
REGEXP_REPLACE(txt, '<[^>]*>', ' ', 1, 0, 'i')
This will return wrong results if you got '<' and '>' within, you should search for a better RegExp then.
You can use the REPLACE UDF which can be downloaded from https://downloads.teradata.com/download/extensibility/teradata-udfs-for-popular-oracle-functions
If you are on TD 14, then it has an inbuilt REPLACE function for the same purpose. (www.info.teradata.com/eDownload.cfm?itemid=113480017)

BeautifulSoup: parse only part of the page

I want to parse a part of html page, say
my_string = """
<p>Some text. Some text. Some text. Some text. Some text. Some text.
Link1
Link2
</p>
<img src="image.png" />
<p>One more paragraph</p>
"""
I pass this string to BeautifulSoup:
soup = BeautifulSoup(my_string)
# add rel="nofollow" to <a> tags
# return comment to the template
But during parsing BeautifulSoup adds <html>,<head> and <body> tags (if using lxml or html5lib parsers), and I don't need those in my code. The only way I've found up to now to avoid this is to use html.parser.
I wonder if there is a way to get rid of redundant tags using lxml - the quickest parser.
UPDATE
Originally my question was asked incorrectly. Now I removed <div> wrapper from my example, since common user does not use this tag. For this reason we cannot use .extract() method to get rid of <html>, <head> and <body> tags.
Use
soup.body.renderContents()
lxml will always add those tags, but you can use Tag.extract() to remove your <div> tag from inside them:
comment = soup.body.div.extract()
I could solve the problem using .contents property:
try:
children = soup.body.contents
string = ''
for child in children:
string += str(item)
return string
except AttributeError:
return str(soup)
I think that ''.join(soup.body.contents) would be more neat list to string converting, but this does not work and I get
TypeError: sequence item 0: expected string, Tag found

How keep groovy/XMLSlurper from stripping html tags from a node?

I'm reading an HTML file from a POST response and parsing it with XMLSlurper. The textarea node on the page has some HTML code put into it (non-urlencoded - not my choice) and when I read that value, Groovy strips all the tags.
Example:
<html>
<body>
<textarea><html><body>This has html code for some reason</body></html></textarea>
</body>
</html>
When I parse the above and then find(...) the "textarea" node, it returns to me:
This has html code for some reason
and none of the tags. How do I keep the tags?
I think you're getting the right data, but printing it out wrong... Can you try using StreamingMarkupBuilder to convert the node back to a piece of xml?
def xml = '''<html>
| <body>
| <textarea><html><body>This has html code for some reason</body></html></textarea>
| </body>
|</html>'''
def ta = new XmlSlurper().parseText( xml ).body.textarea
String content = new groovy.xml.StreamingMarkupBuilder().bind {
mkp.yield ta.children()
}
assert content == '<html><body>This has html code for some reason</body></html>'

How to add headers in specific pages pdfkit generated pdfs

I'm currently using pdfkit in a 3.0.5 rails application to generate reports of user activity.
The pdf document is simple, first page it has some details about the user, a summary then
it has a table containing all the user's activity of the selected period.
First page is ok, but when I show the table the next pages must start with that header column titles in every page with the activity table header. (it remind a bank statement)
Something like this:
|user |action | source | destination |date-time |
xxx 1 1 2 2011-04-01 hh:mm:ss
....
====================page break=================================
#after page break the column titles must be printed again
|user |action | source | destination |date-time |
xxx 5 4 5 2011-04-05 hh:mm:ss
Does anybody know how could I can do that?
You should be able to use some javascript to alter the contents of the header, but only on certain pages.
in your header html have a hidden div with your table headers, but your first page header by default. Then with a javascript onload function do something like this:
<html>
<head>
<script type='text/javascript'>
function swap_header() {
var pages = document.getElementsByClassName('header');
for (var i=0; i<pages.length; ++i) {
if ( i > 0 ) {
pages[i].innerHTML = '<table><thead><th>user</th><th>action</th></thead></table>';
}
}
}
</script>
</head>
<body onload='swap_header()'>
<div class='header'>Normal 1st page header</div>
<table>
<tr><td>foo</td><td>bar</td></tr>
</table>
</body>
</html>
You could also render out 2 different pdfs, and combine them programmatically with pdftk.

Resources