A Sonnet in Notenik: Group and Set Commands

This is a work in progress guide of sorts that covers some very useful merge commands, set and the three group commands.

I hope that if it isn’t immediately useful, at least the value of Notenik’s templating features are made evident. Please let me know if there are any code errors or typos.

— ThePrinter


Introduction

Let’s say we want to imitate a blog layout similar to John Gruber’s and Michael J. Tsai’s. On the front page, articles are grouped together by the date that they’re published, beneath a single HTML block element.

John Gruber's Daring Fireball
<h2 class="dateline">Friday,  7 July 2023</h2>
<dl class="linkedlist">
<dt>
<a href="https://www.lemonde.fr/en/france/article/2023/07/06/france-set-to-allow-police-to-spy-through-phones_6044269_7.html">Le Monde: ‘France Set to Allow Police to Spy Through Phones’</a>&nbsp;<a class="permalink" title="Permanent link to ‘Le Monde: ‘France Set to Allow Police to Spy Through Phones’’" href="https://daringfireball.net/linked/2023/07/07/france-privacy-security-police">★</a>
</dt>
<dd>
<p>Le Monde:</p>

<blockquote>
  <p>French police should be able to spy on suspects by remotely
activating the camera, microphone and GPS of their phones and
other devices, lawmakers agreed late on Wednesday, July 5. Part of
a wider justice reform bill, the spying provision has been
attacked by both the left and rights defenders as an authoritarian
snoopers’ charter, though Justice Minister Éric Dupond-Moretti
insists it would affect only “dozens of cases a year.”</p>

<p>Covering laptops, cars and other connected objects as well as
phones, the measure would allow the geolocation of suspects in
crimes punishable by at least five years’ jail. Devices could
also be remotely activated to record sound and images of people
suspected of terror offenses, as well as delinquency and
organized crime.</p>
</blockquote>

<p>It’s unclear from this article whether the law would simply allow police to <em>try</em> to do this, using security exploits to plant malware on targets’ devices, or if France is going to mandate that all devices include back doors to enable it. Either way, good luck with that. The way the article is written, it’s made to seem that the police have the technical ability to just do this. They don’t.</p>

</dd>

...

</dl>
Michael J. Tsai's Blog
<p class="day">Friday, <a href="/blog/2023/07/">July</a> <a href="/blog/2023/07/07/">7</a>, <a href="/blog/2023/">2023</a></p>
<div class="post">
<h1 id="post-39996"><a href="https://mjtsai.com/blog/2023/07/07/french-bill-to-allow-police-to-commandeer-phones/" rel="bookmark" title="Permanent Link: French Bill to Allow Police to Commandeer Phones">French Bill to Allow Police to Commandeer Phones</a></h1>
<p><a href="https://gazettengr.com/france-passes-bill-to-allow-police-remotely-activate-phone-camera-microphone-spy-on-people/">Tosin Ajuwon</a> (via <a href="https://news.ycombinator.com/item?id=36616037">Hacker News</a>, <a href="https://news.ycombinator.com/item?id=36626966">2</a>, <a href="https://news.ycombinator.com/item?id=36621757">3</a>):</p>
<blockquote cite="https://gazettengr.com/france-passes-bill-to-allow-police-remotely-activate-phone-camera-microphone-spy-on-people/">
<p>A bill that would allow police in France to spy on suspects by remotely activating cameras, microphone including GPS of their phones has been passed.</p>
<p>The bill allows the geolocation of crime suspects, covering other devices like laptops, cars and connected devices, just as it could be remotely activated to record sound and images of people suspected of terror offences, as well as delinquency and organised crime.</p>
</blockquote>

<p>I hope that Tim Cook will have a statement about whether this is possible with Apple devices. Has Apple has been asked to assist or has it been done via exploits? Edward Snowden has mentioned stuff like this <a href="https://www.bbc.com/news/uk-34444233">before</a>, but I don’t recall seeing specifics about which devices were affected.</p>

<p><a href="https://pxlnv.com/linklog/google-canadian-news-removal/">Google</a> and <a href="https://pxlnv.com/linklog/meta-c-18/">Meta</a> have proactively announced that they will block links to Canadian news sources over a <em>link tax</em>. Would Apple go to bat for privacy?</p>

...

<div class="post">
<h1 id="post-39994"><a href="https://mjtsai.com/blog/2023/07/07/ethernet-at-50/" rel="bookmark" title="Permanent Link: Ethernet at 50">Ethernet at 50</a></h1>
<p><a href="https://arstechnica.com/gadgets/2023/06/speed-matters-how-ethernet-went-from-3mbps-to-100gbps-and-beyond/">Iljitsch Van Beijnum</a> (via <a href="https://mas.to/@dnanian/110640186154705501">Dave Nanian</a>):</p>
<blockquote cite="https://arstechnica.com/gadgets/2023/06/speed-matters-how-ethernet-went-from-3mbps-to-100gbps-and-beyond/"><p>But in the end it was Ethernet that won the battle for LAN standardization through a combination of standards body politics and a clever, minimalist—and thus cheap to implement—design. It went on to obliterate the competition by seeking out and assimilating higher bitrate protocols and adding their technological distinctiveness to its own. Decades later, it had become ubiquitous.</p><p>If you’ve ever looked at the network cable protruding from your computer and wondered how Ethernet got started, how it has lasted so long, and how it works, wonder no more: here’s the story.</p></blockquote>

<p><a href="https://om.co/2023/07/03/ethernet-is-50/">Om Malik</a>:</p>
<blockquote cite="https://om.co/2023/07/03/ethernet-is-50/"><p>There must be something to this whole notion that “time flies!” I distinctly remember writing a <a href="https://om.co/gigaom/ethernet-everywhere/">short essay about the incredible adaptability of the Ethernet</a>, the technology protocol, on the 31st birthday of the technology that came from Bob Metcalfe’s work at Xerox PARC in the early 1970s. Metcalfe and David Boggs (who passed away in 2022) invented the Ethernet. It was inspired by ALOHANet, a packet radio network used to communicate among the Hawaiian Islands. </p><p><a href="https://ethernetalliance.org/blog/2023/05/22/celebrating-50-years-of-ethernet/">It just turned 50 years old</a> — remarkably, it still powers our networks into the future. That is some serious resilience and longevity — no wonder (belatedly, in my opinion) Metcalfe <a href="https://news.mit.edu/2023/bob-metcalfe-wins-acm-turing-award-0322">got the 2022 Turing Award</a>. In 1973, Metcalfe wrote a memo on a “broadcast communication network” linking personal computers (PARC Altos) to create a local network that moved data at 2.94 Mbps per second. In 1976, the follow-up work on the memo led to the publication of the seminal paper <a href="https://dl.acm.org/doi/10.1145/360248.360253">“Ethernet: Distributed Packet Switching for Local Computer Networks.”</a></p></blockquote>

</div>

We want to achieve something similar on web page of our own. This is what our HTML merge template fragment looks like without any merge commands:

<p class="metadata">=$date&MMMM dd, yyyy$=</p>
<article>
	<h2>
		<a href="=$date&yyyy$=/=$date&MM$=/=$title&f$=.html">=$title$=</a>
	</h2>
	=$body&w1o$=
</article>

In order to achieve the style of the two blogs shown above, we need to use the group merge commands. With these commands we can monitor a single variable ( =$date$=) for any changes and generate output (the contents of the <article> element) that corresponds to the matching =$date$= variable in our Notenik collection. In other words, every note in our collection that is read and written by this template will be grouped by the date provided in the Date field of each note.

Garupa [1]

Here’s what the merge template looks like with the group merge commands and other necessary commands.

<?output "../includes-gen/recent-posts.html" ?>
<?nextrec?>
<?definegroup 1 "=$date$=" ?>
<?ifendgroup 1 ?>
<?ifnewgroup 1 ?>
<p class="metadata">=$date&MMMM dd, yyyy$=</p>
<?endif?>
<article>
	<h2>
		<a href="/=$date&yyyy$=/=$date&MM$=/=$title&f$=.html">=$title$=</a>
	</h2>
	=$body&w1o$=
</article>
<?endif?>
<?loop?>

This results in something like the following HTML fragment:

<p class="metadata" April 26, 2023</p>
<article>
	<h2>
		<a href="/2023/04/doc1.html">Doc 1</a>
	</h2>
	<blockquote>
        <p>Some text in a blockquote.</p>
        </blockquote>
</article>

<p class="metadata">April 02, 2023</p>
<article>
	<h2>
		<a href="/2023/04/doc2.html">Doc 2</a>
	</h2>
        <p>An HTML paragraph.</p>
        <p>A second paragraph.</p>
        <p><strong>A very serious paragraph.</p>
</article>

<article>
	<h2>
		<a href="/2023/04/doc3.html">Doc 3</a>
	</h2>
        <p>An HTML paragraph.</p>
        <p>A second paragraph.</p>
        <p><strong>A very serious paragraph.</p>
</article>

This is just an example fragment. Normally all of the notes in a collection would be output by the merge template above. What if we don’t want that to happen? Our intention is not to have every note output to the HTML fragment, only the most recent ones, i.e. within a certain number of dates.

If we wanted to have one week’s worth of posts displayed in this fragment, then we would like the merge template to only write notes that correspond with the last seven date variables. To do this, we need to know how the set commands operate in conjunction with the if command, while retaining what we’ve already achieved with the group commands.

Corralling, wrangling…angling

Our goal here is to have seven <p class="metadata">... tags written by this merge template. These are the lines of HTML that denote the date above the articles published, which in turn will be grouped together if they are posted on the same day.

The set command

This command can define a global variable and set its value. This command would normally have three operands: the name of the global variable, an operator, and a value.

One intended use for the set command is to support a line counter. By initializing the value to 0, and then adding to it whenever an output line is generated, the IF command can be used to check for page overflow (in a table column, for example), and then start a new page or column, resetting the counter to 0 again.

Notenik Knowledge Base

What we want to achieve is similar to the line counter example given in the Notenik Knowledge Base.

Our global variable is going to be a generic one: count. The first thing that we need to do is “set” the global variable “count” to a value of zero[2].

<?set count = 0 ?>

The set merge command is typically placed above the <?nextrec?> command that determines when a merge template should start reading and writing most commands (with the exception of output and if commands, which can be placed ahead of <?nextrec?> if necessary).

With the value of the count variable set to zero, we need to make it so that our count variable increases by one whenever a =$date$= variable is written to our document fragment. This can be achieved by placing the command <?set counter ++ ?>. The ++ operand increases the value of the variable counter by one. We can also use the operand += and increase the variable manually by setting the corresponding value to 1 for a command <?set counter += 1 ?>, but the purpose of the ++ operand is specifically for increments of one.

The command <?set counter ++ ?> should be placed in the line immediately following the <?ifnewgroup 1?> command. This is so that whenever a new date variable group is written the count variable will increase by one.

Next, an if command needs to be placed immediately after our set command in order to watch for when the count value reaches seven. When this occurs, we want the <p class="metadata">... line of HTML from earlier to be written.

You should have something like this:

<?ifnewgroup 1 ?>
<?set count ++  ?>
<?if =$count$= le 7 ?>
<p class="metadata">=$date&MMMM dd, yyyy$=</p>
<?endif?>
<?endif?>

Now, when a new group with the variable =$date$= is read and the total number of writeable =$date$= variables are less than or equal to seven then the line <p class="metadata">=$date&MMMM dd, yyyy$=</p> will be written seven times.[^3] These lines of HTML will accomodate for one week’s worth of content, or “posts”, that will be group appropriately beneath the corresponding dates.

The last thing left for us to figure out is how to get rid of the posts that fall beyond the seven date limit we’re applying. As is, this template would generate an HTML document fragment with <p class="metadata">... lines above one week’s worth of posts starting from the top of the page and display posts outside of this seven day range without these lines. We need to get rid of them. This calls for another count command.

To review, our merge template as of right now should look like this:

<?output "../includes-gen/recent-posts.html" ?>
<?nextrec?>
<?definegroup 1 "=$date$=" ?>
<?ifendgroup 1 ?>
<?ifnewgroup 1 ?>
<?set count ++  ?>
<?if =$count$= le 7 ?>
<p class="metadata">=$date&MMMM dd, yyyy$=</p>
<?endif?>
<?endif?>
<article>
	<h2>
		<a href="/=$date&yyyy$=/=$date&MM$=/=$title&f$=.html">=$title$=</a>
	</h2>
	=$body&w1o$=
</article>
<?endif?>
<?loop?>

What we want to do is suppress the writing of the <article> element and its contents to our document fragment after seven date variables are written. This is very simple to achieve. All we have to do is place an additional if command immediately before the <article> element.

<?if =$count$= le 7 ?>
<article>
	<h2>
		<a href="/=$date&yyyy$=/=$date&MM$=/=$title&f$=.html">=$title$=</a>
	</h2>
	=$body&w1o$=
</article>
<?endif?>

This will ensure that the only content displayed at the command of this template will be what is within the 7-day range instituted by the count variable.

Altogether, the complete merge template should look like this:

<?output "../includes-gen/recent-posts.html" ?>
<?nextrec?>
<?definegroup 1 "=$date$=" ?>
<?ifendgroup 1 ?>
<?ifnewgroup 1 ?>
<?set count ++  ?>
<?if =$count$= le 7 ?>
<p class="metadata">=$date&MMMM dd, yyyy$=</p>
<?endif?>
<?endif?>
<?if =$count$= le 7 ?>
<article>
	<h2>
		<a href="/=$date&yyyy$=/=$date&MM$=/=$title&f$=.html">=$title$=</a>
	</h2>
	=$body&w1o$=
</article>
<?endif?>
<?endif?>
<?loop?>

  1. Groupertype of fish, 1690s, from Portuguese garupa, of unknown origin, probably from a South American Indian language, perhaps Tupi.” https://www.etymonline.com/word/grouper ↩︎

  2. “The global variable name, when used as the object of a set command, should not be enclosed within the normal variable delimiters, since this would cause the variable name to be replaced by its current value. (On the other hand, you may include a variable name within the global variable name if you’d like to vary the global variable name based on another variable.)” — Notenik Knowledge Base ↩︎

2 Likes