How to convert Json to Html in yesod? - haskell

Is there some way in yesod-0.9.3 to convert Json to Html to include it into <script/> tag?
Using Yesod.Json and Data.Aeson I can get the value of a Json type, which I want to use as the value of a variable introduced in a <script> tag, that is, not to return RepJson, but to include it as a part of RepHtml.

Using fully qualified names...
let txtVal = Data.Text.Lazy.Encoding.decodeUtf8 $ Data.Aeson.encode jsonVal
then, inside your hamlet:
<script>
var v = #{txtVal}
Note that this is a bit dangerous in that it doesn't check that the encoding was successful. Look at the Data.Text.Encoding module for more info.

Related

How to parse the only the second span tag in an HTML document using python bs4

I want to parse only one span tag in my html document. There are three sibling span tags without any class or I'd. I am targeting the second one only using BeautifulSoup 4.
Given the following html document:
<div class="adress">
<span>35456 street</span>
<span>city, state</span>
<span>zipcode</span>
</div>
I tried:
for spn in soup.findAll('span'):
data = spn[1].text
but it didn't work. The expected result is the text in the second span stored in a a variable:
data = "city, state"
and how to to get both the first and second span concatenated in one variable.
You are trying to slice an individual span (a Tag instance). Get rid of the for loop and slice the findAll response instead, i.e.
>>> soup.findAll('span')[1]
<span>city, state</span>
You can get the first and second tags together using:
>>> soup.findAll('span')[:2]
[<span>35456 street</span>, <span>city, state</span>]
or, as a string:
>>> "".join([str(tag) for tag in soup.findAll('span')[:2]])
'<span>35456 street</span><span>city, state</span>'
Another option:
data = soup.select_one('div > span:nth-of-type(2)').get_text(strip=True)
print(data)
Output:
city, state

ReportLab - Metadata, CreationDate and ModificationDate

How can I change metadata fields, CreationDate and ModificationDate, when I create a pdf with Reportlab?
Take a look at where modification and creation dates are set:
D['ModDate'] = D["CreationDate"] = \
Date(ts=document._timeStamp,dateFormatter=self._dateFormatter)
# ...
return PDFDictionary(D).format(document)
Basically, metadata is a dictionary saved at the end of binary string, start of string is file contents (document).
Inside Reportlab the workflow you ask about can be:
create canvas
draw something on it
get document from canvas
create PDFDictionary with artificial mod and create dates
format document with PDFDictionary
save to file
Change metadata of pdf file with pypdf also attempts similar goal.
The ReportLab (currently 3.5) Canvas provides public methods, like Canvas.setAuthor(), to set the /Author, /Title, and other metadata fields (called "Internal File Annotations" in the docs, section 4.5).
However, there is no method for overriding the /CreationDate or /ModDate.
If you only need to change the formatting of the dates, you can simply use the Canvas.setDateFormatter() method.
The methods described above modify a PDFInfo object, as can be seen in the source, but this is part of a private PDFDocument (as in Canvas._doc.info).
If you really do need to override the dates, you could either hack into the private parts of the canvas, or just search the content of the resulting file object for /CreationDate (...) and /ModDate (...), and replace the value between brackets.
Here's a quick-and-dirty example that does just that:
import io
import re
from reportlab.pdfgen import canvas
# write a pdf in a file-like object
file_like_obj = io.BytesIO()
p = canvas.Canvas(file_like_obj)
# set some metadata
p.setAuthor('djvg')
# ... add some content here ...
p.save()
# replace the /CreationDate (similar for /ModDate )
pdf_bytes = file_like_obj.getvalue()
pdf_bytes = re.sub(b'/CreationDate (\w*)', b'/CreationDate (D:19700101010203+01)', pdf_bytes)
# write to actual file
with open('test.pdf', 'wb') as pdf:
pdf.write(pdf_bytes)
The example above just illustrates the principle. Obviously one could use fancy regular expressions with lookaround etc.
From the pdf spec:
Date values used in a PDF shall conform to a standard date format, which closely follows that of the international standard ASN.1 (Abstract Syntax Notation One), defined in ISO/IEC 8824. A date shall be a text string of the form
( D : YYYYMMDDHHmmSSOHH' mm )

MarkLogic diacritic-insensitive snippet

For now I'm using this code to generate snippet, based on a JSON document that I'm getting from MarkLogic search.
xquery version "1.0-ml";
module namespace searchlib="http://ihs.com/lib/searchlib";
import module namespace search="http://marklogic.com/appservices/search" at "/MarkLogic/appservices/search/search.xqy";
import module namespace json="http://marklogic.com/xdmp/json" at "/MarkLogic/json/json.xqy";
declare function searchlib:get-snippet($docc,$words) {
let $doc:= json:transform-from-json($docc)
let $squery := search:parse($words)
let $result := <result>{search:snippet($doc,$squery,
<transform-results apply="snippet" xmlns="http://marklogic.com/appservices/search">
<max-snippet-chars>255</max-snippet-chars>
</transform-results>)}</result>
return $result//search:match
};
When performing search I'm using:
cts.jsonPropertyValueQuery(fieldname, values,
['case-insensitive', 'diacritic-insensitive'])
So search works diacritic-insensitive and produces good results, but in search:snippet I'm not able to pass diacritic-insensitive option as in cts.jsonPropertyValueQuery.
In documentation I can see this in description
Options to define the search grammar and control the search. See description for $options for the function search:search. Note that you cannot specify the apply attribute on the transform-results option with search:snippet; to use a different snippetting function, use search:search or search:resolve instead.
But in here it is:
search:snippet(
$result as node(),
$cts-query as schema-element(cts:query),
[$options as element(search:transform-results)?]
) as element(search:snippet)
So does it mean I can't pass other options to search:snippet? Or is there a option to do this?
I'm testing it using chávez and it is producing results, but snippets are generated properly only for documents containing exact match that means that document
Chavez did something
Will not get highligh on Chavez and
Chávez did something
Will get a highligh
Thanks in advance!
Problem was in not passing options to search:snippet, but to search:parse
xquery version "1.0-ml";
module namespace searchlib="http://ihs.com/lib/searchlib";
import module namespace search="http://marklogic.com/appservices/search" at "/MarkLogic/appservices/search/search.xqy";
import module namespace json="http://marklogic.com/xdmp/json" at "/MarkLogic/json/json.xqy";
declare function searchlib:get-snippet($docc,$words) {
let $doc:= json:transform-from-json($docc)
let $squery := search:parse($words,
<options xmlns="http://marklogic.com/appservices/search">
<term>
<term-option>case-insensitive</term-option>
<term-option>diacritic-insensitive</term-option>
</term>
</options>, "cts:query")
let $result := <result>{search:snippet($doc,$squery,
<transform-results apply="snippet" xmlns="http://marklogic.com/appservices/search">
<max-snippet-chars>255</max-snippet-chars>
</transform-results>)}</result>
return $result//search:match
};
passing
<term-option>diacritic-insensitive</term-option>
to search:parse made it work.
Here is explanation from MarkLogic:
The search:snippet() function allows you to extract matching text and
returns the matches wrapped in a containing node, with highlights
tagged. However, to allow the search:snippet to extract the correct
text, the cts:query() that is passed to the snippet should match the
sequence of values. For search:snippet, cts:query is typically a
result of a call to search:parse. The search:parse() function parses
query text according to given options and returns the appropriate
cts:query XML.

Get real bool value from YamlStream

I use YamlDotnet to parse a yaml stream to a dictionary of string object via the YamlStream.
The YamlMappingType, YamlSequenceNode and YamlScalarNode are used in order to convert the value to a dictionary, a list or a string.
But I need to get a real boolean value instead of the string equivalent, and for that I use
bool.TryParse(value.ToString(), out valueBool)
value veing a YamlNode.
Is there a better way to do that?
Perhaps another child type of YamlNode?
EDIT:
I don't know the content of the YAML file, I just want to get a dictionary with his values.
Instead of doing the parsing manually, you should use the Deserializer class, which will convert a YAML document into an object graph.
var deserializer = new Deserializer();
var parsed = deserializer.Deserialize<...>(input);
You can see a working example here

customising Pandoc's HTML output with CSS or a template

I have a Happstack program that dynamically converts Markdown documents to HTML using Text.Pandoc:
import qualified Text.Pandoc as Pandoc
...
return $ toResponse $ Pandoc.writeHtml Pandoc.def contents
I.e. Pandoc is returning a Text.Blaze.Html.Html value. (This has a ToMessage instance which means it can be used as a response to a request.)
How do I insert a custom CSS stylesheet into Pandoc's output? What if I want to customise the HTML e.g. by wrapping the <body> contents with some other elements?
When Pandoc's "standalone mode" option is enabled, it uses a template to format the output.
The template and its substitions variables can be set in the writerTemplate and writerVariables members of WriterOptions.
The command line tool has a default set of template it uses. You can see the default template for a format using e.g. pandoc -D html.
When using the library, the default is to use an empty template. You can get the default template programmatically using getDefaultTemplate.
Here's some example code:
import Text.Blaze.Html.Renderer.String
import Text.Pandoc
getHtmlOpts = do
template <- either (error . show) id
`fmap` getDefaultTemplate Nothing "html"
return $ def
{ writerStandalone = True
, writerTemplate = template
, writerVariables = [
("css", "/path/to/style.css"),
("header-includes",
"<style>p { background-color: magenta; }</style>")]
}
main = do
opts <- getHtmlOpts
putStrLn $ renderHtml $ writeHtml opts $ readMarkdown def "..."
You can also write your own template, call it for instance template.html and use the --template template.html option when calling pandoc from the command-line.
The documentation is at https://pandoc.org/MANUAL.html#templates, and the default template (for inspiration) is at https://raw.githubusercontent.com/jgm/pandoc-templates/master/default.html5.
Pandoc, when run from the command line, takes some arguments that allow you to insert something into the <head> tag (-H), before content (-B) and after content (-A). I don't know about Happstack, but surely there must be a way to pass these parameters to Pandoc.writeHtml

Resources