Iterating through a sequence of mappings with different inputs with pandoc - pandoc

I am trying to use one template to handle varying input files. I want to iterate through a specific sequence of mappings where the keys and the values in the sequence of mappings can change. I have a solution but it feels like a hack and it only works for the latest version of pandoc. Here is an example of the functionality I would like:
input1.md:
---
title: "Input 1"
links:
- Pear: "https://pear.com/"
- Banana: "https://banana.com/"
- Grape: "https://grape.com/"
- Strawberry: "https://strawberry.com/"
---
This is the body.
desired-output1.md:
Input 1
- Pear : https://pear.com/
- Banana : https://banana.com/
- Grape : https://grape.com/
- Strawberry : https://strawberry.com/
This is the body.
input2.md:
---
title: "Input 2"
links:
- Kiwi: "https://kiwi.com/"
- Lemon: "https://lemon.com/"
---
This is the body.
desired-output2.md:
Input 2
- Kiwi : https://kiwi.com/
- Lemon : https://lemon.com/
This is the body.
Here is the pandoc template I am using right now which works however it feels hacky and does not work with recent but older versions of pandoc:
template.md:
$title$
$for(links)$
$for(it/pairs)$
- $it.key$ : $it.value$
$endfor$
$endfor$
$body$
Here is the command I am using to compile the document:
pandoc -f markdown -t markdown --template=template.md input1.md
My question is: Is there a more straightforward, less of a hack way to achieve this functionality with one template file? Is there a way to ensure this works with older versions of pandoc? Thanks.

This fixed it for me in pandoc 2.7.3
In the YAML header -
---
title: "Frank Hermosillo"
image: "frank.jpg"
links:
- site: Apple
url: "https://apples.com/"
- site: Pear
url: "https://pears.com/"
- site: Orange
url: "https://oranges.com/"
There are two tabs before 'url:' and one before '- site':
And in the template:
<ul class="list-inline">
$for(links)$
<li class="list-inline-item">
<a href=$links.url$>
<button type="button" class="btn btn-outline-dark">
To $links.site$
</button>
</a>
</li>
$endfor$
</ul>

Related

Specifying parameters in yml file for Quarto

I am creating a quarto book project in RStudio to render an html document.
I need to specify some parameters in the yml file but the qmd file returns
"object 'params' not found". Using knitR.
I use the default yml file where I have added params under the book tag
project:
type: book
book:
title: "Params_TEst"
author: "Jane Doe"
date: "15/07/2022"
params:
pcn: 0.1
chapters:
- index.qmd
- intro.qmd
- summary.qmd
- references.qmd
bibliography: references.bib
format:
html:
theme: cosmo
pdf:
documentclass: scrreprt
editor: visual
and the qmd file looks like this
# Preface {.unnumbered}
This is a Quarto book.
To learn more about Quarto books visit <https://quarto.org/docs/books>.
```{r}
1 + 1
params$pcn
When I render the book, or preview the book in Rstudio the error I receive is:
Quitting from lines 8-10 (index.qmd)
Error in eval(expr, envir, enclos) : object 'params' not found
Calls: .main ... withVisible -> eval_with_user_handlers -> eval -> eval
I have experimented placing the params line in the yml in different places but nothing works so far.
Could anybody help?
For multi-page renders, e.g. quarto books, you need to add the YAML to each page, not in the _quarto.yml file
So in your case, each of the chapters that calls a parameter needs a YAML header, like index.qmd, intro.qmd, and summary.qmd, but perhaps not references.qmd.
The YAML header should look just like it does in a standard Rmd. So for example, your index.qmd would look like this:
---
params:
pcn: 0.1
---
# Preface {.unnumbered}
This is a Quarto book.
To learn more about Quarto books visit <https://quarto.org/docs/books>.
```{r}
1 + 1
params$pcn
But, what if you need to change the parameter and re-render?
Then simply pass new parameters to the quarto_render function
quarto::quarto_render(input = here::here("quarto"), #expecting a dir to render
output_format = "html", #output dir is set in _quarto.yml
cache_refresh = TRUE,
execute_params = list(pcn = 0.2))
For now, this only seems to work if you add the parameters to each individual page front-matter YAML.
If you have a large number of pages and need to keep parameters centralized, a workaround is to run a preprocessing script that replaces the parameters in all pages. To add a preprocessing script, add the key pre-render to your _quarto.yml file. The Quarto website has detailed instructions.
For example, if you have N pages named index<N>.qmd, you could have a placeholder in the YML of each page:
---
title: This is chapter N
yourparamplaceholder
---
Your pre-render script could replace yourparamplaceholder with the desired parameters. Here's an example Python script:
for filename in os.listdir(dir):
if filename.endswith(".qmd"):
with open(filename, "r") as f:
txt = f.read()
f.replace('yourparamplaceholder', 'params:\n\tpcn: 0.1\n\tother:20\n')
with open(filename, "w") as ff:
ff.write(txt)
I agree with you that being able to set parameters centrally would be a good idea.

jekyll blog new line (minimal-mistake)

jekyll blog(minimal-mistakes thema) has a space to introduce myself.
I want to write on two lines in this space.
For example
hello
world
I know that to edit this page, i need to touch the _config.yml file.
# Site Author
author:
name : "Choi Young-jin"
avatar : "/assets/images/images/avatar.png"
bio : "**^^**" <-----------Parts to change
42 intra ID: yochoi
location : "Seoul"
email : "amateur.toss#gmail.com"
links:
- label: "Email"
icon: "fas fa-fw fa-envelope-square"
# url: "amateur.toss#gmail.com"
- label: "GitHub"
icon: "fab fa-fw fa-github"
url: "https://github.com/amateurtoss"
The escape character does not work.
bio: "hello\nworld"
What if I want to show the string in two lines?
Well it's markdown, so you should do
bio: |-
hello
world
(That's a YAML block scalar, which is interpreted literally and ends with the next item on the same or lesser indentation level as bio)
You can of course also do
bio: "hello\n\nworld"
But it's less obvious what happens here.
You can use HTML in the bio string, so you can simply use a HTML linebreak:
bio: "hello<br>world"
The above is the only way in which I managed to have a single line break. All other options lead to either no line break or an empty line between the two lines.

Typo3/CKEditor: Allow definition list (dl, dt, dd)

this question is driving me crazy. I'm using typo3 (8.7.13) with CKEditor as the RTE. Now I want to allow to use <dl>, <dt> and <dd> in the source code view mode. But every time I leave the source code view those tags become modified to <p>
<dl>, <dt> and <dd> are lsited in the yaml file under
processing:
allowTags:
- dl
- dt
- dd
And within the template constants i set:
styles.content.allowTags := addToList(dd)
styles.content.allowTags := addToList(dt)
styles.content.allowTags := addToList(dl)
What more is necessary?
fins wimmer
Yeah, I finaly found the solution based on this topic.
This needs to be inserted in the yaml config:
editor:
config:
extraAllowedContent:
- dd
- dl
- dt
fin swimmer
I've found a plugin for ckeditor (which not only allows <dl> tags and so forth but also provides custom buttons for the editor) and created a simple wrapper extension to easily integrate that into TYPO3. In case anyone's interested it's on github as rte_ckeditor_dl.
Does this work ?
RTE.default {
allowTags < RTE.default.proc.allowTags
proc {
allowTagsOutside := addToList(dd,dt,dl)
}
}
documentation
Do your own configuration for CKEditor as YAML and add
processing:
# Tags that are allowed in the content in general
allowTags:
- dd
- dl
- dt
## Tags that are allowed outside of paragraphs
allowTagsOutside: [dd, dl, dt]
editor:
config:
allowedContent: true
[..]
processing
allowTags:
- dl
- dt
- dd

Best approach to create recursive treeview dynamically from data API

I'm learning Angular 2, trying to build an expandable tree-view from a (potentially very large) third-party API. The API has an underlying structure like this:
- Home (id: 1053)
- - Rugby League (id: 1054)
- - - Super League (id: 1103)
- - - - Castleford Tigers (id: 1111)
- - - - Catalans Dragons (id: 1110)
- - - - Huddersfield Giants (id: 1116)
- - - - Hull FC (id: 1108)
- - - Championship (id: 1104)
- - - - Batley Bulldogs (id: 1120)
- - - - Bradford Bulls (id: 1118)
- - - - Dewsbury Rams (id: 1124)
- - - - Featherstone Rovers (id: 1121)
- - Football (id: 1056)
- - - Premier League (id: 1057)
- - - - AFC Bournemouth (id: 1059)
- - - - etc
- - - - etc
The API is set up such that I pass an id and it returns a simple JSON array of the children (only) of that node. So, for example I call: http://www.example.com/api/contentNodes/?parentId=1053 and it returns:
[
{"Id":1054,"Name":"Rugby League","HasChildren":true},
{"Id":1056,"Name":"Football","HasChildren":true}
]
(HasChildren represents whether or not the node has child nodes.)
Note, because the data-set will eventually be large I want to 'pull in' more data from the API progressively as the tree branches are opened, rather than dumping the entire data-set in there and rendering that out in my app.
I've set up an Angular 2 app which can be seen here: http://plnkr.co/edit/QQ1OKCbd4pDptpSVbWch?p=preview
The key component is the `app/content-list.component.ts' file:
import {Component, OnInit} from 'angular2/core';
import {ContentNode} from './content-node';
import {ContentService} from './content.service';
#Component({
selector: 'content-list',
template: `
<ol class="tree">
<li *ngFor="#contentNode of contentNodes" class="tree__branch" [ngClass]="{'tree__branch--has-children': contentNode.HasChildren}">
<a *ngIf="contentNode.HasChildren" (click)="toggleBranch(contentNode.Id)" class="toggle">+</a> {{ contentNode.Name }}
</li>
</ol>
<div class="error" *ngIf="errorMessage">{{errorMessage}}</div>
`
})
export class ContentListComponent implements OnInit {
constructor (private _contentService: ContentService) {}
errorMessage: string;
private _startNodeId: number = 1053;
contentNodes: ContentNode[];
ngOnInit() {
this.getContentNodes();
}
getContentNodes() {
this._contentService.getContentNodes(this._startNodeId)
.subscribe(
contentNodes => this.contentNodes = contentNodes,
error => this.errorMessage = <any>error
);
}
toggleBranch(branchId:number){
console.log('branchId: ' + branchId);
}
}
You'll see here that I'm calling my service which returns the JSON as above, by being passed a parentId of 1053.
I've now hit a wall in being able to progressively load the child nodes of the treeview when the + button is clicked, into the nested HTML list (<ol>).
What would be the best approach here, to achieve this in a really neat way?
My next step will be to ensure that the app doesn't make excessive API calls, but my immediate concern is just to get a running treeview hooked up and working.
I've seen this example of a recursive treeview but it seems (a) a little buggy (in that there are empty <ol></ol> elements rendered in the HTML when child nodes are empty etc); and (b) it seems to be set up in a very 'hard-coded' kind of a way and I'm not experienced enough to confidently refactor it.
Many thanks.
Note, for security reasons I can't open up the API to public requests unfortunately, which makes testing this on Plunkr a little difficult, I realise. For the moment my example uses just a static, single level JSON data-set.
in Angular2 you can render directives recursively. This makes rendering the tree very easy.
I've modified your Plunker a little bit just to show the point. It's not the ideal implementation but it works as expected :).
Example:
#Component({
selector: 'tree-view',
template: `
<div *ngFor="#dir of dirs">
<tree-view [dirs]="dir.dirs"></tree-view>
<div>
`,
directives: [TreeView]
})
export class TreeView {
#Input()
private dirs: Array<Directory>;
}
I hope you will like it.
Cheers!

How can I apply basic html formatting to a sublime text syntax definition only within

Ok so by the following yaml definition, shouldn't only what's in between {blah} and {!blah} get text.html.basic syntax highlighting? And the {blah} tags themselves take the highlighting of a comment? Unfortunately it's not happening that way. HTML highlighting is anywhere in the document, and {blah} doesn't get comment highlighting.
# [PackageDev] target_format: plist, ext: tmLanguage
---
name: Test
scopeName: source.test
fileTypes: [test]
uuid: 3631aac6-ee25-4ec1-ab08-39f156235363
patterns:
- name: comment.number-sign
begin: \{blah\}
end: \{\!blah\}
patterns:
- include: text.html.basic
match: .
...
Sample Code:
{blah}
<input type="text"/>
{!blah} <----- these are not styled according to comment.number-sign
<input type="text"/> <----- this also has HTML highlighting and I don't want it to
This should get you started:
# [PackageDev] target_format: plist, ext: tmLanguage
name: Test
scopeName: source.test
fileTypes: [test]
uuid: 3631aac6-ee25-4ec1-ab08-39f156235363
patterns:
- name: html.test
begin: (\{blah\})
beginCaptures:
'1': {name: comment.blah.test}
end: (\{!blah\})
endCaptures:
'1': {name: comment.blah.test}
patterns:
- include: text.html.basic
The name is the base scope for the entire selector. beginCaptures and endCaptures assign the comment.blah.test scope to the {blah} tags, while the include rule assigns HTML highlighting to whatever is between the begin and end tags.
Using the Neon Color Scheme (full disclosure: I'm its maintainer), a sample file looks like this:
As you can see, {blah} and {!blah} are in gray italics, the comment scope. Markup outside the {blah} tags is not highlighted at all, while that enclosed in the {blah} tags is highlighted as HTML.
For more on syntax definitions, check the tutorial and the reference at the unofficial docs.

Resources