~subsetpark/pantagruel-web

b0e8b4a66da95fc95d311c1aac4b9cb5b835cc8d — Zach Smith 2 months ago
Initial commit
5 files changed, 226 insertions(+), 0 deletions(-)

A index.janet
A index.pant
A index.temple
A static/dore.jpg
A static/style.css
A  => index.janet +35 -0
@@ 1,35 @@
(defn render-pantagruel
  [pant]
  (defn replace-unicode
    [line]
    (->> line
         (string/replace-all "all" "∀")
         (string/replace-all "_" "-")
         (string/replace-all "=>" "⇒")
         (string/replace-all "<=" "⇐")
         (string/replace-all "->" "→")
         (string/replace-all "---" "<hr>")
         (string/replace-all ";" "<hr><hr>")))

  (defn render-line
    [line]
    (if-not (string/has-prefix? "//" line)
      (string (replace-unicode line) "<br>")
      (bagatto/markdown->html (string "> " (string/trim line "/")))))

  (as-> pant .
        (string/split "\n" .)
        (filter (complement empty?) .)
        (map render-line .)
        (string/join . "\n")))

(def data {:index {:attrs {:title "Pantagruel: An Extremely Lightweight Specification Language"}}
           :pant {:src "index.pant"
                  :attrs bagatto/parse-base}
           :static {:src (bagatto/* "static/*")
                    :attrs bagatto/parse-base}})

(def site {:index {:dest "site/index.html"
                   :out (bagatto/renderer "/index")}
           :static {:each :static
                    :dest (bagatto/path-copier "site/static")}})

A  => index.pant +44 -0
@@ 1,44 @@
Thought.
Specification <= [String].

// Pantagruel is a language for writing *system specifications*.

pantagruel thoughts: [Thought] => Specification.
---

// It's a computer language, but not as you might think of it.

// The effects of evaluating a specification are *nil*---Pantagruel has no semantics.

eval spec = Nil.

;

eval spec: Specification.
check spec: Specification => Bool.
---

// However, Pantagruel specifications can be checked to ensure that certain conditions have been met.

// For instance, that you've defined all your terms by the end of your document.
check spec = all symbol: invoked_symbols spec =>
        symbol in (head spec) -> bound_as_of? symbol (first_appearance symbol)
        symbol in (body spec) -> bound_as_of? symbol (next_chapter (first_appearance symbol)).

;

(Head, Body) <= [String].
Chapter <= [Head, Body].
Specification <= [Chapter].

// This allows a structured form of description where terms can be explained in gradually greater detail.

invoked_symbols <= {String}.
chapter head: Head, body: Body => Chapter.
first_appearance symbol: String => Nat.
bound_as_of? symbol: String, Nat => Bool.

next_chapter n: Nat => Nat.
---

invoked_symbols spec = {all s: String => s in spec}.

A  => index.temple +47 -0
@@ 1,47 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Pantagruel</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="Description" content="A useful desk calculator, including vectors and quotations.">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Alegreya:ital@1&display=swap" rel="stylesheet">

<link href="static/style.css" rel="stylesheet" />
</head>

<body>

<div class="header">
  <h1>{{ (get-in args [:index :title]) }}</h1>
</div>

<nav>
</nav>

<div class="row">
  <div class="narrow">&nbsp;</div>
  <div class="column">
    {- (render-pantagruel (get-in args [:pant :contents])) -}
  </div>
  <div class="narrow">&nbsp;</div>
</div>

<div class="row" align="center">
<h2>Learn More</h2>
  <img src="static/dore.jpg" width=300px/>
  <p>
  <a href="https://github.com/subsetpark/pantagruel">Pantagruel on GitHub</a>
  </p>
</div>

<div class="footer">
        <div class="narrow">Z. D. Smith, 2021.</div>
        <div class="column">&nbsp;</div>
        <div class="narrow">Built with <a href="https://bagatto.co">Bagatto</a>.</div>
</div>
</body>
</html>


A  => static/dore.jpg +0 -0
A  => static/style.css +100 -0
@@ 1,100 @@
* {
  box-sizing: border-box;
}

nav {
    text-align: center;
}

body {
  font-family: serif;
  background-color: #fff;
}

code {
  font-family: "Courier", monospace;
}

.ornament {
    text-align: center;
}

a:normal {
    color: 'RoyalBlue';
}

a:visited {
    color: #2F4F4F;
}

blockquote {
        color: #444;
}

/* Style the header */
.header {
  padding: 1em;
  text-align: center;
  font-size: 2em;
  font-family: "Alegreya", monospace;
  border-style: none none none none;
  background-color: beige;
}

h2 {
  font-family: "Alegreya";
}

.double-line {
  text-decoration: underline overline darkgrey;
}

.column {
  float: left;
  width: 60%;
  padding: 10px;
}

.narrow {
  float: left;
  width: 15%;
  padding: 10px;
}

.nav {
    padding: 12px;
    text-decoration: none !important;
    color: #000 !important;
    display: inline;
    width: 50%;
    font-size: 25px;
    font-family: "Courier", monospace;
    font-weight: bold;
}

/* Clear floats after the columns */
.row:after {
  content: "";
  display: table;
  clear: both;
}

/* Style the footer */
.footer {
  padding: 10px;
  text-align: center;
  background-position: center;
  background-repeat: no-repeat;
  background-size: cover;
  position: relative;
}

/* Responsive layout - makes the three columns stack on top of each other instead of next to each other */
@media (max-width: 600px) {
  .column {
    width: 100%;
  }
}