diff options
-rw-r--r-- | Makefile | 3 | ||||
-rw-r--r-- | README.md | 6 | ||||
-rw-r--r-- | spec.txt | 66 | ||||
-rwxr-xr-x | tools/makespec.py | 50 | ||||
-rwxr-xr-x | tools/specfilter.hs | 9 | ||||
-rw-r--r-- | tools/template.tex | 47 |
6 files changed, 107 insertions, 74 deletions
@@ -15,6 +15,7 @@ spec.html: spec.txt tools/template.html spec.pdf: spec.md tools/template.tex tools/specfilter.hs pandoc -s $< --template tools/template.tex \ --filter tools/specfilter.hs -o $@ --latex-engine=xelatex --toc \ - --number-sections -V documentclass=report -V tocdepth=2 \ + --number-sections --toc-depth=2 --no-highlight \ + -V documentclass=report \ -V classoption=twosides @@ -53,9 +53,9 @@ file, with code examples written in a shorthand form: . To build an HTML version of the spec, do `make spec.html`. To build a -PDF version, do `make spec.pdf`. (Creating a PDF requires [pandoc] -and a LaTeX installation. Creating the HTML version requires only -`libcmark` and `python3`.) +PDF version, do `make spec.pdf`. (Creating the HTML version requires +that [cmark](https://github.com/jgm/cmark) and `python3` be installed +and in your path. Creating a PDF also requires [pandoc] and LaTeX.) The spec is written from the point of view of the human writer, not the computer reader. It is not an algorithm---an English translation of @@ -1660,16 +1660,17 @@ followed by one of the strings (case-insensitive) `address`, `dir`, `div`, `dl`, `dt`, `fieldset`, `figcaption`, `figure`, `footer`, `form`, `frame`, `frameset`, `h1`, `head`, `header`, `hr`, `html`, `legend`, `li`, `link`, `main`, `menu`, `menuitem`, `meta`, -`nav`, `noframes`, `ol`, `optgroup`, `option`, `p`, `param`, `pre`, -`section`, `source`, `title`, `summary`, `table`, `tbody`, `td`, +`nav`, `noframes`, `ol`, `optgroup`, `option`, `p`, `param`, +`section`, `source`, `summary`, `table`, `tbody`, `td`, `tfoot`, `th`, `thead`, `title`, `tr`, `track`, `ul`, followed by [whitespace], the end of the line, the string `>`, or the string `/>`.\ **End condition:** line is followed by a [blank line]. -7. **Start condition:** line begins with an [open tag] -(with any [tag name]) followed only by [whitespace] or the end -of the line.\ +7. **Start condition:** line begins with a complete [open tag] +or [closing tag] (with any [tag name] other than `script`, +`style`, or `pre`) followed only by [whitespace] +or the end of the line.\ **End condition:** line is followed by a [blank line]. All types of [HTML blocks] except type 7 may interrupt @@ -1874,6 +1875,14 @@ In type 7 blocks, the [tag name] can be anything: </i> . +. +</ins> +*bar* +. +</ins> +*bar* +. + These rules are designed to allow us to work with tags that can function as either block-level or inline-level tags. The `<del>` tag is a nice example. We can surround content with @@ -2844,8 +2853,8 @@ foo</p> . Laziness only applies to lines that would have been continuations of -paragraphs had they been prepended with `>`. For example, the -`>` cannot be omitted in the second line of +paragraphs had they been prepended with [block quote marker]s. +For example, the `> ` cannot be omitted in the second line of ``` markdown > foo @@ -2864,7 +2873,7 @@ without changing the meaning: <hr /> . -Similarly, if we omit the `>` in the second line of +Similarly, if we omit the `> ` in the second line of ``` markdown > - foo @@ -2887,7 +2896,7 @@ then the block quote ends after the first line: </ul> . -For the same reason, we can't omit the `>` in front of +For the same reason, we can't omit the `> ` in front of subsequent lines of an indented or fenced code block: . @@ -2914,6 +2923,30 @@ foo <pre><code></code></pre> . +Note that in the following case, we have a paragraph +continuation line: + +. +> foo + - bar +. +<blockquote> +<p>foo +- bar</p> +</blockquote> +. + +To see why, note that in + +```markdown +> foo +> - bar +``` + +the `- bar` is indented too far to start a list, and can't +be an indented code block because indented code blocks cannot +interrupt paragraphs, so it is a [paragraph continuation line]. + A block quote can be empty: . @@ -3618,6 +3651,21 @@ Here are some list items that start with a blank line but are not empty: </ul> . +A list item can begin with at most one blank line. +In the following example, `foo` is not part of the list +item: + +. +- + + foo +. +<ul> +<li></li> +</ul> +<p>foo</p> +. + Here is an empty bullet list item: . diff --git a/tools/makespec.py b/tools/makespec.py index b2b8ab2..925f23c 100755 --- a/tools/makespec.py +++ b/tools/makespec.py @@ -1,16 +1,24 @@ #!/usr/bin/env python3 +# -*- coding: utf-8 -*- + import re import sys from subprocess import * from string import Template +def out(str): + sys.stdout.buffer.write(str.encode('utf-8')) + +def err(str): + sys.stderr.buffer.write(str.encode('utf-8')) + if len(sys.argv) == 2: specformat = sys.argv[1] if not (specformat in ["html", "markdown"]): - sys.stderr.write("Format must be html or markdown\n") + err("Format must be html or markdown\n") exit(1) else: - sys.stderr.write("Usage: makespec.py [html|markdown]\n") + err("Usage: makespec.py [html|markdown]\n") exit(1) def toIdentifier(s): @@ -29,9 +37,8 @@ def parseYaml(yaml): return metadata def pipe_through_prog(prog, text): - p1 = Popen(prog.split(), stdout=PIPE, stdin=PIPE, stderr=PIPE) - [result, err] = p1.communicate(input=text.encode('utf-8')) - return [p1.returncode, result.decode('utf-8'), err] + result = check_output(prog.split(), input=text.encode('utf-8')) + return result.decode('utf-8') def replaceAnchor(match): refs.append("[{0}]: #{1}".format(match.group(1), match.group(2))) @@ -60,7 +67,10 @@ with open('spec.txt', 'r', encoding='utf-8') as spec: if stage == 0: example += 1 mdlines.append("\n<div class=\"example\" id=\"example-{0}\" data-section=\"{1}\">\n".format(example, section)) - mdlines.append("<div class=\"examplenum\"><a href=\"#example-{0}\">Example {0}</a> <a class=\"dingus\" title=\"open in interactive dingus\">(interact)</a></div>\n\n".format(example)) + mdlines.append("<div class=\"examplenum\"><a href=\"#example-{0}\">Example {0}</a>".format(example)) + if specformat == "html": + mdlines.append(" <a class=\"dingus\" title=\"open in interactive dingus\">(interact)</a>") + mdlines.append("</div>\n\n") mdlines.append("````````````````````````````````````````````````````````` markdown\n") stage = 1 elif stage == 1: @@ -97,13 +107,13 @@ with open('spec.txt', 'r', encoding='utf-8') as spec: lastnum[level - 1] = lastnum[level - 1] + 1 number = '.'.join([str(x) for x in lastnum]) ident = toIdentifier(section) - ln = re.sub(r' ', ' ' + number + ' ', ln, count=1) + ln = re.sub(r' ', ' <span class="number">' + number + '</span> ', ln, count=1) sections.append(dict(level=level, contents=section, ident=ident, number=number)) refs.append("[{0}]: #{1}".format(section, ident)) - ln = re.sub(r'# +', '# <a id="{0}"></a> '.format(ident), + ln = re.sub(r'# +', '# <a id="{0}"></a>'.format(ident), ln, count=1) else: ln = re.sub(r'\[([^]]*)\]\(@([^)]*)\)', replaceAnchor, ln) @@ -116,7 +126,7 @@ yaml = ''.join(yamllines) metadata = parseYaml(yaml) if specformat == "markdown": - sys.stdout.write(yaml + '\n\n' + mdtext) + out(yaml + '\n\n' + mdtext) elif specformat == "html": with open("tools/template.html", "r", encoding="utf-8") as templatefile: template = Template(templatefile.read()) @@ -127,39 +137,35 @@ elif specformat == "html": section['contents'] + '](#' + section['ident'] + ')') toc = '<div id="TOC">\n\n' + '\n'.join(toclines) + '\n\n</div>\n\n' prog = "cmark --smart" - [retcode, result, err] = pipe_through_prog(prog, toc + mdtext) - if retcode == 0: + result = pipe_through_prog(prog, toc + mdtext) + if result == '': + err("Error converting markdown version of spec to HTML.\n") + exit(1) + else: result = re.sub(r'␣', '<span class="space"> </span>', result) result = re.sub(r'<h([1-6])><a id="([^\"]*)"><\/a> ', "<h\\1 id=\"\\2\">", result) # put plural s inside links for better visuals: result = re.sub(r'<\/a>s', "s</a>", result) - sys.stdout.write(template.substitute(metadata, body=result)) + out(template.substitute(metadata, body=result)) # check for errors: idents = [] for ident in re.findall(r'id="([^"]*)"', result): if ident in idents: - sys.stderr.write("WARNING: duplicate identifier '" + ident + - "'\n") + err("WARNING: duplicate identifier '" + ident + "'\n") else: idents.append(ident) for href in re.findall(r'href="#([^"]*)"', result): if not (href in idents): - sys.stderr.write("WARNING: internal link with no anchor '" + - href + "'\n") + err("WARNING: internal link with no anchor '" + href + "'\n") reftexts = [] for ref in refs: ref = re.sub('].*',']',ref).upper() if ref in reftexts: - sys.stderr.write("WARNING: duplicate reference link '" + - ref + "'\n") + err("WARNING: duplicate reference link '" + ref + "'\n") else: reftexts.append(ref) - else: - sys.stderr.write("Error converting markdown version of spec:\n") - sys.stderr.write(err) - exit(1) exit(0) diff --git a/tools/specfilter.hs b/tools/specfilter.hs index 7a7676b..7f4df9f 100755 --- a/tools/specfilter.hs +++ b/tools/specfilter.hs @@ -15,12 +15,12 @@ exampleDivs (Div (ident, ["example"], kvs) ]) = Div (ident, ["example"], kvs) [ rawtex "\\begin{minipage}[t]{\\textwidth}\n{\\scriptsize " , d - , rawtex "\\vspace{-1em}}" - , rawtex "\\begin{minipage}[t]{0.49\\textwidth}\n\\definecolor{shadecolor}{gray}{0.85}\n" + , rawtex "}\\vspace{-0.4em}\n" + , rawtex "\\begin{minipage}[t]{0.49\\textwidth}\n\\definecolor{shadecolor}{gray}{0.85}\n\\begin{snugshade}\\small\n" , addBreaks c1 - , rawtex "\\end{minipage}\n\\hfill\n\\begin{minipage}[t]{0.49\\textwidth}\n\\definecolor{shadecolor}{gray}{0.95}\n" + , rawtex "\\end{snugshade}\n\\end{minipage}\n\\hfill\n\\begin{minipage}[t]{0.49\\textwidth}\n\\definecolor{shadecolor}{gray}{0.95}\n\\begin{snugshade}\\small\n" , addBreaks c2 - , rawtex "\\end{minipage}\n\\end{minipage}" + , rawtex "\\end{snugshade}\n\\end{minipage}\n\\end{minipage}" ] where rawtex = RawBlock (Format "latex") addBreaks (CodeBlock attrs code) = CodeBlock attrs $ addBreaks' code @@ -33,4 +33,5 @@ exampleDivs x = x anchors :: Inline -> [Inline] anchors (Link text ('@':lab,_)) = [RawInline (Format "latex") ("\\hyperdef{}{" ++ lab ++ "}{\\label{" ++ lab ++ "}}"), Strong text] +anchors (Span ("",["number"],[]) xs) = [] -- remove sect numbers anchors x = [x] diff --git a/tools/template.tex b/tools/template.tex index d083b72..64893c2 100644 --- a/tools/template.tex +++ b/tools/template.tex @@ -44,6 +44,8 @@ $endif$ % use microtype if available \IfFileExists{microtype.sty}{\usepackage{microtype}}{} \usepackage[margin=1in]{geometry} +\providecommand{\tightlist}{% + \setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}} $if(natbib)$ \usepackage{natbib} \bibliographystyle{$if(biblio-style)$$biblio-style$$else$plainnat$endif$} @@ -61,40 +63,10 @@ $if(lhs)$ \lstnewenvironment{code}{\lstset{language=Haskell,basicstyle=\small\ttfamily}}{} $endif$ \usepackage{fancyvrb} +$if(highlighting-macros)$ +$highlighting-macros$ +$endif$ \usepackage{color,framed} -\newcommand{\VerbBar}{|} -\newcommand{\VERB}{\Verb[commandchars=\\\{\}]} -\DefineVerbatimEnvironment{Highlighting}{Verbatim}{commandchars=\\\{\},fontsize=\small} -% Add ',fontsize=\small' for more characters per line -\definecolor{shadecolor}{gray}{1} -\newenvironment{Shaded}{\begin{snugshade}}{\end{snugshade}} -\newcommand{\NormalTok}[1]{{#1}} -\let\KeywordTok\NormalTok -\let\DataTypeTok\NormalTok -\let\DecValTok\NormalTok -\let\BaseNTok\NormalTok -\let\FloatTok\NormalTok -\let\CharTok\NormalTok -\let\StringTok\NormalTok -\let\CommentTok\NormalTok -\let\OtherTok\NormalTok -\let\AlertTok\NormalTok -\let\FunctionTok\NormalTok -\let\RegionMarkerTok\NormalTok -\let\ErrorTok\NormalTok -%\newcommand{\KeywordTok}[1]{\textcolor[rgb]{0.00,0.44,0.13}{\textbf{{#1}}}} -%\newcommand{\DataTypeTok}[1]{\textcolor[rgb]{0.56,0.13,0.00}{{#1}}} -%\newcommand{\DecValTok}[1]{\textcolor[rgb]{0.25,0.63,0.44}{{#1}}} -%\newcommand{\BaseNTok}[1]{\textcolor[rgb]{0.25,0.63,0.44}{{#1}}} -%\newcommand{\FloatTok}[1]{\textcolor[rgb]{0.25,0.63,0.44}{{#1}}} -%\newcommand{\CharTok}[1]{\textcolor[rgb]{0.25,0.44,0.63}{{#1}}} -%\newcommand{\StringTok}[1]{\textcolor[rgb]{0.25,0.44,0.63}{{#1}}} -%\newcommand{\CommentTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textit{{#1}}}} -%\newcommand{\OtherTok}[1]{\textcolor[rgb]{0.00,0.44,0.13}{{#1}}} -%\newcommand{\AlertTok}[1]{\textcolor[rgb]{1.00,0.00,0.00}{\textbf{{#1}}}} -%\newcommand{\FunctionTok}[1]{\textcolor[rgb]{0.02,0.16,0.49}{{#1}}} -%\newcommand{\RegionMarkerTok}[1]{{#1}} -%\newcommand{\ErrorTok}[1]{\textcolor[rgb]{1.00,0.00,0.00}{\textbf{{#1}}}} $if(verbatim-in-note)$ \usepackage{fancyvrb} $endif$ @@ -158,8 +130,13 @@ $if(lang)$ \fi $endif$ -\usepackage{titlesec} -\titleformat{\chapter}[hang]{\Huge\bfseries}{\thechapter\ }{0pt}{\Huge\bfseries} +\usepackage[small]{titlesec} +\titleformat{\chapter} + {\Large\bfseries} % format + {\Large\thechapter} % label + {0pt} % sep + {\Large} % before-code + \usepackage{fancyhdr} \pagestyle{fancy} |