Assembling pages

This is the thirteenth post in the Mostly Oberon series. Mostly Oberon documents my exploration of the Oberon Language, Oberon System and the various rabbit holes I will inevitably fall into.

Pandoc and JSON

I use Pandoc to process Markdown documents. I like to keep my front matter in JSON rather than Pandoc’s YAML. Fortunately Pandoc does support working with JSON as a metadata file include. Normally I would manually split the JSON front matter and the rest of the markup into two separate files, then process with Pandoc and other tooling like LunrJS. AssemblePage automates this process.

Example shell usage:


      AssemblePage MyText.txt \
         metadata=document.json \
         document=document.md
      pandoc --from markdown --to html \
         --metadata-file document.json \
         --standalone \
         document.md >MyText.html
   

Source code for AssemblePage.Mod


   MODULE AssemblePage;
     IMPORT Out, Strings, Files, Args := extArgs;

   VAR
     srcName, metaName, docName : ARRAY 1024 OF CHAR;

   (* FrontMatter takes a "read" Rider, r, and a "write" Rider "w".
   If the first character read by r is an opening curly bracket
   (the start of the front matter) it writes it out with w, until
   it finds a matching closing curly bracket or the file ends. *)
   PROCEDURE FrontMatter*(VAR r : Files.Rider; VAR w : Files.Rider);
     VAR c : BYTE; cCnt : INTEGER;
   BEGIN
     (* Scan for opening JSON front matter *)
     cCnt := 0;
     REPEAT
       Files.Read(r, c);
       IF r.eof = FALSE THEN
         IF c = ORD("{") THEN
           cCnt := cCnt + 1;
         ELSIF c = ORD("}") THEN
           cCnt := cCnt - 1;
         END;
         Files.Write(w, c);
       END;
     UNTIL (r.eof = TRUE) OR (cCnt = 0);
     IF cCnt # 0 THEN
       Out.String("ERROR: mis matched '{' and '}' in front matter");
       ASSERT(FALSE);
     END;
   END FrontMatter;

   (* CopyIO copies the characters from a "read" Rider to a "write" Rider *)
   PROCEDURE CopyIO*(VAR r : Files.Rider; VAR w: Files.Rider);
     VAR c : BYTE;
   BEGIN
     REPEAT
       Files.Read(r, c);
       IF r.eof = FALSE THEN
         Files.Write(w, c);
       END;
     UNTIL r.eof = TRUE;
   END CopyIO;

   PROCEDURE ProcessParameters(VAR sName, mName, dName : ARRAY OF CHAR);
     VAR
       arg : ARRAY 1024 OF CHAR;
       i, res : INTEGER;
   BEGIN
     mName := "document.json";
     dName := "document.txt";
     arg := "";
     FOR i := 0 TO (Args.count - 1) DO
       Args.Get(i, arg, res);
       IF Strings.Pos("metadata=", arg, 0) = 0 THEN
         Strings.Extract(arg, 9, Strings.Length(arg), mName);
       ELSIF Strings.Pos("document=", arg, 0) = 0 THEN
         Strings.Extract(arg, 9, Strings.Length(arg), dName);
       ELSE
         Strings.Extract(arg, 0, Strings.Length(arg), sName);
       END;
     END;
   END ProcessParameters;

   PROCEDURE AssemblePage(srcName, metaName, docName : ARRAY OF CHAR);
   VAR
     src, meta, doc : Files.File;
     reader, writer : Files.Rider;
   BEGIN
     src := Files.Old(srcName);
     IF src # NIL THEN
       Files.Set(reader, src, 0);
       IF metaName # "" THEN
         meta := Files.New(metaName);
         Files.Register(meta);
         Files.Set(writer, meta, 0);
         FrontMatter(reader, writer);
         Files.Close(meta);
       END;
       IF docName # "" THEN
         doc := Files.New(docName);
         Files.Register(doc);
         Files.Set(writer, doc, 0);
         CopyIO(reader, writer);
         Files.Close(doc);
       END;
     ELSE
       Out.String("ERROR: Could not read ");Out.String(srcName);Out.Ln();
       ASSERT(FALSE);
     END;
     Files.Close(src);
   END AssemblePage;

   BEGIN
     ProcessParameters(srcName, metaName, docName);
     AssemblePage(srcName, metaName, docName);
   END AssemblePage.
   

Next, Previous