Tabbed Code blocks in Hakyll
Posted on October 2, 2012
Tags: hacksoft
Hakyll Setup Series
- Setup Mathjax
- Setup PlantUML
- Setup autobuild Hakyll site Git action CI
- Very Simple Hakyll Pandoc Filtering Example
- Add Railroad Syntax to Hakyll
- Table Of Content in Hakyll
- Hakyll Access on LAN server
1 Showcase
<< "bleh" cout
print("bleh")
echo "bleh"
2 Instruction
Add the below javascript to your one of your templates like default.html
- Structure
- Codeblock < datagroup < Grouplabels < Allblocks
AllBlocks
: All blocks of code regardless if they are tabbed or notgrouplabels
is the set of all unique group names in the documentdatagroup
is the set of codeblocks associated with a SINGLE grouplabelcodeblock
is one of the codeblock within adatagroup
const AllBlocksPre = document.querySelectorAll("[data-group]");
const AllBlocks = [...AllBlocksPre]; //gets all codeblocks w/ and w/o group label
const getUniqueSet = (TargetSet,dataAttr) => {
//gets the set of attributes of an array of codeblocks aka TargetSet
const temp = TargetSet.map((e) => (e.getAttribute(dataAttr)));
const temp2 = temp.filter((a)=>a); //remove nulls
return [...new Set(temp2)];
} const datagroupSet = getUniqueSet(AllBlocks,"data-group") //remove nulls
const getCodeBlocks = (datagroup) => {
//return list of glabels CodeBlocks associated to a single group
return AllBlocks.filter((dataglabelBlock)=>(dataglabelBlock.getAttribute("data-group") === datagroup));
}
const showBlocks = (dataglabeltxt,datagroupCodeBlocks) => {
const selectedglabelGroup = datagroupCodeBlocks.filter((SingleBlock)=>(SingleBlock.getAttribute("data-glabel") === dataglabeltxt))
const NONselectedglabelGroup = datagroupCodeBlocks.filter((SingleBlock)=>(SingleBlock.getAttribute("data-glabel") !== dataglabeltxt))
.map((SingleBlock) => (SingleBlock.style.display="block"));
selectedglabelGroup|| []).map((SingleBlock) => (SingleBlock.style.display="none"));
(NONselectedglabelGroup
}const mkBtn = (dataglabeltxt,datagroupCodeBlocks,showfunc) => {
const newbutton = document.createElement("button");
.textContent = dataglabeltxt;
newbutton.addEventListener('click', ()=>{
newbuttonshowfunc(dataglabeltxt,datagroupCodeBlocks);
;
})return newbutton;
}const showAll = (datagroup) => {
//make all codeblocks visible
.map((e)=>(e.style.display="block"));
datagroup
}
const buildCodeTab = (datagroupCodeBlocks) => {
const leader = datagroupCodeBlocks[0]; //get the leader codeblock of a group of codeblock
const setglabelstxt = getUniqueSet(datagroupCodeBlocks,"data-glabel");
.map((singleglabeltxt)=>{
setglabelstxtconst btn = mkBtn(singleglabeltxt,datagroupCodeBlocks,showBlocks)
.insertAdjacentElement("beforebegin",btn);
leader
})
//make showAll button START
const btnShowAll = document.createElement("button");
.textContent = "All";
btnShowAll.addEventListener('click',(e)=>(showAll(datagroupCodeBlocks)));
btnShowAll.insertAdjacentElement('beforebegin', btnShowAll);
leader//make showAllbutton END
}
//below code is performing actual behavior, the above code are just functions
.map((datagroup) => {
datagroupSetconst groupOfCodeblocks = getCodeBlocks(datagroup);
buildCodeTab(groupOfCodeblocks);
const firsttab = groupOfCodeblocks[0]
showBlocks(firsttab.getAttribute("data-glabel"),groupOfCodeblocks);
})
//Structure:
// Codeblock < Group/Grouplabel/datagroup < grouplabels < allblocks
const AllBlocksPre = document.querySelectorAll("[data-group]");
const AllBlocks = [...AllBlocksPre]; //gets all codeblocks w/ and w/o group label
const rawgrouplabels = AllBlocks.map((e)=>(e.getAttribute("data-group"))); //group label w/ repeats
const grouplabelsPre = [...new Set(rawgrouplabels)]; //get set of unique group labels
const grouplabels = grouplabelsPre.filter((a)=>a); //remove nulls
const getCodeBlocks = (datagroup) => {
//return list of codeblocks associated to a single group label
return AllBlocks.filter((dataglabel)=>(dataglabel.getAttribute("data-group") === datagroup));
}
const showSingleCode = (dataglabel,datagroup) => {
//make single codeblock visible
.style.display="block";
dataglabelconst nonChosen = datagroup.filter((e)=>(e!=dataglabel));
.map((e)=>(e.style.display="none"));
nonChosen
}
const makeBtn = (dataglabel,datagroup,showfunc) => {
//make button for a single codeblock
const newbutton = document.createElement("button");
.textContent=dataglabel.getAttribute("data-glabel");
newbutton.addEventListener('click', ()=>{
newbuttonshowfunc(dataglabel,datagroup);
;
})return newbutton;
}
const showAll = (datagroup) => {
//make all codeblocks visible
.map((e)=>(e.style.display="block"));
datagroup
}
const buildCodeTab = (datagroup) => {
const leader = datagroup[0]; //get the leader codeblock of a group of codeblock
const btngrp =datagroup.map((dataglabel)=>(makeBtn(dataglabel,datagroup,showSingleCode)));
.map((dataglabel)=>{
btngrp.insertAdjacentElement('beforebegin',dataglabel);
leader;
})
//make showAll button START
const btnShowAll = document.createElement("button");
.textContent = "All";
btnShowAll.addEventListener('click',(e)=>(showAll(datagroup)));
btnShowAll.insertAdjacentElement('beforebegin', btnShowAll);
leader//make showAllbutton END
}
//below code is performing actual behavior, the above code are just functions
.map((datagroup) => {
grouplabelsconst groupOfCodeblocks = getCodeBlocks(datagroup);
buildCodeTab(groupOfCodeblocks);
showSingleCode(groupOfCodeblocks[0],groupOfCodeblocks) //default select the first block
})
3 Usage
- To create a tabbed codeblock add a
group
parameter andglabel
parameter.group
parameter aggregates the codeblocks to be grouped- if you have multiple tabbed groups of codeblocks then the
group
parameter must be unique for each.
- if you have multiple tabbed groups of codeblocks then the
glabel
is the text shown on the tab
3.1 Codeblocks
<< "bleh" cout
print("bleh")
echo "bleh"
<!-- fenced codeblocks should use triple backticks ```
instead of single quotes ''' which is used here for presentation purposes -->
'''{.c group="bleh" glabel="C++"}
cout << "bleh"
'''
'''{.py group="bleh" glabel="py"}
print("bleh")
'''
'''{.bash group="bleh" glabel="bash"}
echo "bleh" '''
3.2 Fenced divs
Helol
Goodbye
Begin section
End section
This also works with fenced divs
::: {.hobbies group="hi" glabel="do"}
hafe
:::
::: {.hobbies group="hi" glabel="do"}
Begin section
:::
::: {.hobbies group="hi" glabel="do"}
''' plantuml
@startuml
Carl->Dan : Hi
@enduml
'''
:::
::: {.hobbies group="hi" glabel="do2"}
End section
:::
::: {.hobbies group="hi" glabel="do2"}
''' plantuml
@startuml
Alice->Bob : I am using hex
@enduml
'''
:::
::: {.hobbies group="hi" glabel="do2"}
hafe :::