fork
This commit is contained in:
parent
4b5d05166b
commit
7de6920e44
30
COPYRIGHT
Normal file
30
COPYRIGHT
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
->Copyright (C) 2007-2024 Jessica Loren Parsons.
|
||||||
|
All rights reserved.<-
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions
|
||||||
|
are met:
|
||||||
|
|
||||||
|
1. Redistributions of works must retain the original copyright notice,
|
||||||
|
this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the original copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. Neither my name (Jessica L Parsons) nor the names of contributors to
|
||||||
|
this code may be used to endorse or promote products derived
|
||||||
|
from this work without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||||
|
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
|
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||||
|
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
|
||||||
35
CREDITS
Normal file
35
CREDITS
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
Discount is primarily my work, but it has only reached the point
|
||||||
|
where it is via contributions, critiques, and bug reports from a
|
||||||
|
host of other people, some of which are listed before. If your
|
||||||
|
name isn't on this list, please remind me
|
||||||
|
-david parsons (orc@pell.portland.or.us)
|
||||||
|
|
||||||
|
|
||||||
|
Josh Wood -- Plan9 support.
|
||||||
|
Mike Schiraldi -- Reddit style automatic links, MANY MANY MANY
|
||||||
|
bug reports about boundary conditions and
|
||||||
|
places where I didn't get it right.
|
||||||
|
Jjgod Jiang -- Table of contents support.
|
||||||
|
Petite Abeille -- Many bug reports about places where I didn't
|
||||||
|
get it right.
|
||||||
|
Tim Channon -- inspiration for the `mkd_xhtmlpage()` function
|
||||||
|
Christian Herenz-- Many bug reports regarding my implementation of
|
||||||
|
`[]()` and `![]()`
|
||||||
|
A.S.Bradbury -- Portability bug reports for 64 bit systems.
|
||||||
|
Joyent -- Loan of a solaris box so I could get discount
|
||||||
|
working under solaris.
|
||||||
|
Ryan Tomayko -- Portability requests (and the rdiscount ruby
|
||||||
|
binding.)
|
||||||
|
yidabu -- feedback on the documentation, bug reports
|
||||||
|
against utf-8 support.
|
||||||
|
Pierre Joye -- bug reports, php discount binding.
|
||||||
|
Masayoshi Sekimura- perl discount binding.
|
||||||
|
Jeremy Hinegardner- bug reports about list handling.
|
||||||
|
Andrew White -- bug reports about the format of generated urls.
|
||||||
|
Steve Huff -- bug reports about Makefile portability (for Fink)
|
||||||
|
Ignacio Burgue?o-- bug reports about `>%class%`
|
||||||
|
Henrik Nyh -- bug reports about embedded html handling.
|
||||||
|
John J. Foerch -- bug reports about incorrect `–` and `—`
|
||||||
|
translations.
|
||||||
|
|
||||||
|
|
||||||
62
Csio.c
Normal file
62
Csio.c
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include "cstring.h"
|
||||||
|
#include "markdown.h"
|
||||||
|
#include "amalloc.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* putc() into a cstring
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
Csputc(int c, Cstring *iot)
|
||||||
|
{
|
||||||
|
EXPAND(*iot) = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* printf() into a cstring
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
Csprintf(Cstring *iot, char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list ptr;
|
||||||
|
int siz=100;
|
||||||
|
|
||||||
|
do {
|
||||||
|
RESERVE(*iot, siz);
|
||||||
|
va_start(ptr, fmt);
|
||||||
|
siz = vsnprintf(T(*iot)+S(*iot), ALLOCATED(*iot)-S(*iot), fmt, ptr);
|
||||||
|
va_end(ptr);
|
||||||
|
} while ( siz > (ALLOCATED(*iot)-S(*iot)) );
|
||||||
|
|
||||||
|
S(*iot) += siz;
|
||||||
|
return siz;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* write() into a cstring
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
Cswrite(Cstring *iot, char *bfr, int size)
|
||||||
|
{
|
||||||
|
RESERVE(*iot, size);
|
||||||
|
memcpy(T(*iot)+S(*iot), bfr, size);
|
||||||
|
S(*iot) += size;
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* reparse() into a cstring
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
Csreparse(Cstring *iot, char *buf, int size, mkd_flag_t* flags)
|
||||||
|
{
|
||||||
|
MMIOT f;
|
||||||
|
___mkd_initmmiot(&f, 0, flags);
|
||||||
|
|
||||||
|
___mkd_reparse(buf, size, flags, &f, 0);
|
||||||
|
___mkd_emblock(&f);
|
||||||
|
SUFFIX(*iot, T(f.out), S(f.out));
|
||||||
|
___mkd_freemmiot(&f, 0);
|
||||||
|
}
|
||||||
67
INSTALL
Normal file
67
INSTALL
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
|
||||||
|
HOW TO BUILD AND INSTALL DISCOUNT
|
||||||
|
|
||||||
|
1) Unpacking the distribution
|
||||||
|
|
||||||
|
The DISCOUNT sources are distributed in tarballs. After extracting from
|
||||||
|
the tarball, you should end up with all the source and build files in the
|
||||||
|
directory
|
||||||
|
discount-(version)
|
||||||
|
|
||||||
|
2) Installing the distribution
|
||||||
|
|
||||||
|
DISCOUNT uses configure.sh to set itself up for compilation. To run
|
||||||
|
configure, just do ``./configure.sh'' and it will check your system for
|
||||||
|
build dependencies and build makefiles for you. If configure.sh finishes
|
||||||
|
without complaint, you can then do a ``make'' to compile everything and a
|
||||||
|
``make install'' to install the binaries.
|
||||||
|
|
||||||
|
Configure.sh has a few options that can be set:
|
||||||
|
|
||||||
|
--src=DIR where the source lives (.)
|
||||||
|
--prefix=DIR where to install the final product (/usr/local)
|
||||||
|
--execdir=DIR where to put executables (prefix/bin)
|
||||||
|
--sbindir=DIR where to put static executables (prefix/sbin)
|
||||||
|
--confdir=DIR where to put configuration information (/etc)
|
||||||
|
--libdir=DIR where to put libraries (prefix/lib)
|
||||||
|
--libexecdir=DIR where to put private executables
|
||||||
|
--mandir=DIR where to put manpages
|
||||||
|
--with-amalloc Use my paranoid malloc library to catch memory leaks
|
||||||
|
--shared Build shared libraries
|
||||||
|
--debian-glitch When mangling email addresses, do them deterministically
|
||||||
|
so the Debian regression tester won't complain
|
||||||
|
--pkg-config Build & install a pkg-config(1) .pc file for
|
||||||
|
the discount library.
|
||||||
|
--h1-title Have theme & mkd2html use the first h1 in a document
|
||||||
|
as the title if there's no pandoc header or title
|
||||||
|
specified on the command line.
|
||||||
|
--cxx-binding Wrap mkdio.h with (conditional) 'extern "C"' for c++
|
||||||
|
binding.
|
||||||
|
|
||||||
|
3) Testing
|
||||||
|
|
||||||
|
``make test'' runs discount against a collection of test cases.
|
||||||
|
|
||||||
|
|
||||||
|
4) Installing sample programs and manpages
|
||||||
|
|
||||||
|
The standard ``make install'' rule just installs the binaries. If you
|
||||||
|
want to install the sample programs, they are installed with
|
||||||
|
``make install.samples''; to install manpages, ``make install.man''.
|
||||||
|
A shortcut to install everything is ``make install.everything''
|
||||||
|
|
||||||
|
|
||||||
|
5) Assorted platform gotchas
|
||||||
|
|
||||||
|
1. On NetBSD (version 8 for certain) running configure.sh by
|
||||||
|
itself will result in logging output being mixed in with diagnostic
|
||||||
|
output on the screen instead of having it written to config.log.
|
||||||
|
If, instead, you do `ksh ./configure.sh`, it will be much less
|
||||||
|
garbled (the shell defaults all fds > stderr to close on exec,
|
||||||
|
so my redirecting stdout fails after the first subprocess.)
|
||||||
|
2. On 9Front (and maybe every other extant plan9 variant) the
|
||||||
|
system mkfile sets the `T' flag in CFLAGS; there are several
|
||||||
|
places where I typedef voids to opaque structure pointers and
|
||||||
|
this makes the build die when it attempts to link anything.
|
||||||
|
This was fixed by explicitly setting CFLAGS in Plan9/mkfile in
|
||||||
|
<https://github.com/Orc/discount/commit/311b33218f60ffd342264e97faee8cf7b7853044>.
|
||||||
208
Makefile.in
Normal file
208
Makefile.in
Normal file
@ -0,0 +1,208 @@
|
|||||||
|
CC=@CC@
|
||||||
|
CPPFLAGS=@CPPFLAGS@
|
||||||
|
CFLAGS=@CFLAGS@
|
||||||
|
LDFLAGS=@LDFLAGS@
|
||||||
|
AR=@AR@
|
||||||
|
RANLIB=@RANLIB@
|
||||||
|
INSTALL_PROGRAM=@INSTALL_PROGRAM@
|
||||||
|
INSTALL_DIR=@INSTALL_DIR@
|
||||||
|
INSTALL_DATA=@INSTALL_DATA@
|
||||||
|
|
||||||
|
BUILD=$(CC) -fPIC -I. $(CPPFLAGS) $(CFLAGS)
|
||||||
|
LINK=$(CC) -fPIC -L. $(LDFLAGS)
|
||||||
|
|
||||||
|
.c.o:
|
||||||
|
$(BUILD) -c -o $@ $<
|
||||||
|
|
||||||
|
|
||||||
|
BINDIR=@exedir@
|
||||||
|
MANDIR=@mandir@
|
||||||
|
LIBDIR=@libdir@
|
||||||
|
INCDIR=@prefix@/include
|
||||||
|
@MK_PKGCONFIG@PKGDIR=$(LIBDIR)/pkgconfig
|
||||||
|
|
||||||
|
PGMS=markdown
|
||||||
|
SAMPLE_PGMS=mkd2html makepage
|
||||||
|
@THEME@SAMPLE_PGMS+= theme
|
||||||
|
MKDLIB=libmarkdown
|
||||||
|
OBJS=mkdio.o markdown.o dumptree.o generate.o \
|
||||||
|
resource.o docheader.o version.o toc.o css.o \
|
||||||
|
xml.o Csio.o xmlpage.o basename.o emmatch.o \
|
||||||
|
github_flavoured.o setup.o tags.o html5.o \
|
||||||
|
pgm_options.o flags.o v2compat.o flagprocs.o \
|
||||||
|
@AMALLOC@ @H1TITLE@
|
||||||
|
TESTFRAMEWORK=rep echo cols branch pandoc_headers space2nl
|
||||||
|
|
||||||
|
# modules that markdown, makepage, mkd2html, &tc use
|
||||||
|
COMMON=gethopt.o notspecial.o
|
||||||
|
|
||||||
|
MAN3PAGES=mkd-callbacks.3 mkd-functions.3 markdown.3 mkd-line.3
|
||||||
|
|
||||||
|
all: $(PGMS) $(SAMPLE_PGMS) $(TESTFRAMEWORK) all_subdirs
|
||||||
|
|
||||||
|
install: $(PGMS) $(DESTDIR)$(BINDIR) $(DESTDIR)$(LIBDIR) $(DESTDIR)$(INCDIR) $(DESTDIR)$(PKGDIR)
|
||||||
|
$(INSTALL_PROGRAM) $(PGMS) $(DESTDIR)$(BINDIR)
|
||||||
|
./librarian.sh install libmarkdown VERSION $(DESTDIR)$(LIBDIR)
|
||||||
|
$(INSTALL_DATA) mkdio.h $(DESTDIR)$(INCDIR)
|
||||||
|
@MK_PKGCONFIG@$(INSTALL_DATA) $(MKDLIB).pc $(DESTDIR)$(PKGDIR)
|
||||||
|
|
||||||
|
install.everything: install install.samples install.man
|
||||||
|
|
||||||
|
install.samples: $(SAMPLE_PGMS) install $(DESTDIR)$(BINDIR)
|
||||||
|
$(INSTALL_DIR) $(DESTDIR)$(MANDIR)/man1
|
||||||
|
for x in $(SAMPLE_PGMS); do \
|
||||||
|
$(INSTALL_PROGRAM) $$x $(DESTDIR)$(BINDIR)/$(SAMPLE_PFX)$$x; \
|
||||||
|
$(INSTALL_DATA) $$x.1 $(DESTDIR)$(MANDIR)/man1/$(SAMPLE_PFX)$$x.1; \
|
||||||
|
done
|
||||||
|
|
||||||
|
install.man:
|
||||||
|
$(INSTALL_DIR) $(DESTDIR)$(MANDIR)/man3
|
||||||
|
$(INSTALL_DATA) $(MAN3PAGES) $(DESTDIR)$(MANDIR)/man3
|
||||||
|
for x in mkd_line mkd_generateline; do \
|
||||||
|
( echo '.\"' ; echo ".so man3/mkd-line.3" ) > $(DESTDIR)$(MANDIR)/man3/$$x.3;\
|
||||||
|
done
|
||||||
|
for x in mkd_in mkd_string; do \
|
||||||
|
( echo '.\"' ; echo ".so man3/markdown.3" ) > $(DESTDIR)$(MANDIR)/man3/$$x.3;\
|
||||||
|
done
|
||||||
|
for x in mkd_compile mkd_css mkd_generatecss mkd_generatehtml mkd_cleanup mkd_doc_title mkd_doc_author mkd_doc_date; do \
|
||||||
|
( echo '.\"' ; echo ".so man3/mkd-functions.3" ) > $(DESTDIR)$(MANDIR)/man3/$$x.3; \
|
||||||
|
done
|
||||||
|
$(INSTALL_DIR) $(DESTDIR)$(MANDIR)/man7
|
||||||
|
$(INSTALL_DATA) markdown.7 mkd-extensions.7 $(DESTDIR)$(MANDIR)/man7
|
||||||
|
$(INSTALL_DIR) $(DESTDIR)$(MANDIR)/man1
|
||||||
|
$(INSTALL_DATA) markdown.1 $(DESTDIR)$(MANDIR)/man1
|
||||||
|
|
||||||
|
install.everything: install install.man
|
||||||
|
|
||||||
|
$(DESTDIR)$(BINDIR):
|
||||||
|
$(INSTALL_DIR) $(DESTDIR)$(BINDIR)
|
||||||
|
|
||||||
|
$(DESTDIR)$(INCDIR):
|
||||||
|
$(INSTALL_DIR) $(DESTDIR)$(INCDIR)
|
||||||
|
|
||||||
|
$(DESTDIR)$(LIBDIR):
|
||||||
|
$(INSTALL_DIR) $(DESTDIR)$(LIBDIR)
|
||||||
|
|
||||||
|
@MK_PKGCONFIG@$(DESTDIR)$(PKGDIR):
|
||||||
|
@MK_PKGCONFIG@ $(INSTALL_DIR) $(DESTDIR)$(PKGDIR)
|
||||||
|
|
||||||
|
version.o: version.c VERSION branch
|
||||||
|
$(BUILD) -DBRANCH=`./branch` -DVERSION=\"`cat VERSION`\" -c version.c
|
||||||
|
|
||||||
|
VERSION:
|
||||||
|
@true
|
||||||
|
|
||||||
|
tags.o: tags.c cstring.h tags.h blocktags
|
||||||
|
|
||||||
|
blocktags: mktags
|
||||||
|
./mktags > blocktags
|
||||||
|
|
||||||
|
mktags: mktags.o
|
||||||
|
$(LINK) -o mktags mktags.o
|
||||||
|
|
||||||
|
# example programs
|
||||||
|
@THEME@theme: theme.o $(COMMON) $(MKDLIB) mkdio.h
|
||||||
|
@THEME@ $(LINK) -o theme theme.o $(COMMON) -lmarkdown @LIBS@
|
||||||
|
|
||||||
|
|
||||||
|
mkd2html: mkd2html.o $(MKDLIB) mkdio.h gethopt.h $(COMMON)
|
||||||
|
$(LINK) -o mkd2html mkd2html.o $(COMMON) -lmarkdown @LIBS@
|
||||||
|
|
||||||
|
markdown: main.o $(COMMON) $(MKDLIB)
|
||||||
|
$(LINK) -o markdown main.o $(COMMON) -lmarkdown @LIBS@
|
||||||
|
|
||||||
|
makepage.o: makepage.c mkdio.h
|
||||||
|
$(BUILD) -c makepage.c
|
||||||
|
makepage: makepage.o $(COMMON) $(MKDLIB)
|
||||||
|
$(LINK) -o makepage makepage.o $(COMMON) -lmarkdown @LIBS@
|
||||||
|
|
||||||
|
pgm_options.o: pgm_options.c mkdio.h config.h
|
||||||
|
$(BUILD) -c pgm_options.c
|
||||||
|
|
||||||
|
notspecial.o: notspecial.c
|
||||||
|
$(BUILD) -c notspecial.c
|
||||||
|
|
||||||
|
gethopt.o: gethopt.c
|
||||||
|
$(BUILD) -c gethopt.c
|
||||||
|
|
||||||
|
main.o: main.c mkdio.h config.h
|
||||||
|
$(BUILD) -c main.c
|
||||||
|
|
||||||
|
$(MKDLIB): $(OBJS) .libmarkdown
|
||||||
|
./librarian.sh make $(MKDLIB) VERSION $(OBJS)
|
||||||
|
|
||||||
|
.libmarkdown: $(OBJS)
|
||||||
|
touch $@
|
||||||
|
|
||||||
|
verify: echo tools/checkbits.sh verify_subdirs
|
||||||
|
@./echo -n "headers ... "; tools/checkbits.sh && echo "GOOD"
|
||||||
|
|
||||||
|
test: $(PGMS) $(TESTFRAMEWORK) verify
|
||||||
|
@for x in $${TESTS:-tests/*.t}; do \
|
||||||
|
@LD_LIBRARY_PATH@=. sh $$x || exit 1; \
|
||||||
|
done
|
||||||
|
|
||||||
|
pandoc_headers.o: tools/pandoc_headers.c config.h
|
||||||
|
$(BUILD) -c -o pandoc_headers.o tools/pandoc_headers.c
|
||||||
|
pandoc_headers: pandoc_headers.o $(COMMON) $(MKDLIB)
|
||||||
|
$(LINK) -o pandoc_headers pandoc_headers.o $(COMMON) -lmarkdown
|
||||||
|
|
||||||
|
rep.o : tools/rep.c
|
||||||
|
$(BUILD) -c -o rep.o tools/rep.c
|
||||||
|
rep: rep.o
|
||||||
|
$(LINK) -o rep rep.o
|
||||||
|
|
||||||
|
branch.o: tools/branch.c config.h
|
||||||
|
$(BUILD) -c -o branch.o tools/branch.c
|
||||||
|
branch: branch.o
|
||||||
|
$(LINK) -o branch branch.o
|
||||||
|
|
||||||
|
cols.o: tools/cols.c config.h
|
||||||
|
$(BUILD) -c -o cols.o tools/cols.c
|
||||||
|
cols: cols.o
|
||||||
|
$(LINK) -o cols cols.o
|
||||||
|
space2nl.o: tools/space2nl.c config.h
|
||||||
|
$(BUILD) -c -o space2nl.o tools/space2nl.c
|
||||||
|
space2nl: space2nl.o
|
||||||
|
$(LINK) -o space2nl space2nl.o
|
||||||
|
echo.o: tools/echo.c config.h
|
||||||
|
$(BUILD) -c -o echo.o tools/echo.c
|
||||||
|
echo: echo.o
|
||||||
|
$(LINK) -o echo echo.o
|
||||||
|
|
||||||
|
clean: clean_subdirs
|
||||||
|
rm -f $(PGMS) $(TESTFRAMEWORK) $(SAMPLE_PGMS) *.o
|
||||||
|
rm -f $(MKDLIB) `./librarian.sh files $(MKDLIB) VERSION`
|
||||||
|
|
||||||
|
distclean spotless: clean
|
||||||
|
@DISTCLEAN@ @GENERATED_FILES@ @CONFIGURE_FILES@ ./mktags ./blocktags
|
||||||
|
|
||||||
|
include tests/exercisers/make.include
|
||||||
|
|
||||||
|
Csio.o: Csio.c cstring.h amalloc.h config.h markdown.h
|
||||||
|
amalloc.o: amalloc.c
|
||||||
|
basename.o: basename.c config.h cstring.h amalloc.h markdown.h
|
||||||
|
css.o: css.c config.h cstring.h amalloc.h markdown.h
|
||||||
|
docheader.o: docheader.c config.h cstring.h amalloc.h markdown.h
|
||||||
|
dumptree.o: dumptree.c markdown.h cstring.h amalloc.h config.h
|
||||||
|
emmatch.o: emmatch.c config.h cstring.h amalloc.h markdown.h
|
||||||
|
generate.o: generate.c config.h cstring.h amalloc.h markdown.h
|
||||||
|
main.o: main.c config.h amalloc.h
|
||||||
|
pgm_options.o: pgm_options.c pgm_options.h config.h amalloc.h
|
||||||
|
flagprocs.o: flagprocs.c pgm_options.h markdown.h config.h amalloc.h
|
||||||
|
makepage.o: makepage.c
|
||||||
|
markdown.o: markdown.c config.h cstring.h amalloc.h markdown.h
|
||||||
|
mkd2html.o: mkd2html.c config.h mkdio.h cstring.h amalloc.h
|
||||||
|
mkdio.o: mkdio.c config.h cstring.h amalloc.h markdown.h
|
||||||
|
resource.o: resource.c config.h cstring.h amalloc.h markdown.h
|
||||||
|
theme.o: theme.c config.h mkdio.h cstring.h amalloc.h
|
||||||
|
toc.o: toc.c config.h cstring.h amalloc.h markdown.h
|
||||||
|
version.o: version.c config.h
|
||||||
|
xml.o: xml.c config.h cstring.h amalloc.h markdown.h
|
||||||
|
xmlpage.o: xmlpage.c config.h cstring.h amalloc.h markdown.h
|
||||||
|
setup.o: setup.c config.h cstring.h amalloc.h markdown.h
|
||||||
|
github_flavoured.o: github_flavoured.c config.h cstring.h amalloc.h markdown.h
|
||||||
|
v2compat.o: v2compat.c config.h cstring.h amalloc.h markdown.h
|
||||||
|
gethopt.o: gethopt.c gethopt.h
|
||||||
|
h1title.o: h1title.c markdown.h
|
||||||
|
notspecial.o: notspecial.c config.h
|
||||||
44
Plan9/README.md
Normal file
44
Plan9/README.md
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
# *Discount* Markdown compiler on Plan 9
|
||||||
|
|
||||||
|
## Build
|
||||||
|
|
||||||
|
### One line
|
||||||
|
|
||||||
|
% mk install
|
||||||
|
% markdown -V
|
||||||
|
markdown: discount X.Y.Z GHC=INPUT
|
||||||
|
|
||||||
|
### Stepwise
|
||||||
|
|
||||||
|
% CONFIG='--with-tabstops=7' mk config
|
||||||
|
% mk
|
||||||
|
% mk test
|
||||||
|
% mk install
|
||||||
|
% markdown -V
|
||||||
|
markdown: discount X.Y.Z TAB=7 GHC=INPUT
|
||||||
|
|
||||||
|
See `../configure.sh` and `../pgm_options.c` for other config options.
|
||||||
|
|
||||||
|
### Other *mk*(1) targets
|
||||||
|
|
||||||
|
* `clean`: Delete built objects from source directory.
|
||||||
|
* `nuke`: Delete built objects and generated configuration.
|
||||||
|
* `install.libs`: Discount includes a C library and header.
|
||||||
|
Installation is optional. Plan 9 binaries are statically linked.
|
||||||
|
* `install.man`: Add *markdown* in manual sections 1, 2, and 6.
|
||||||
|
* `install.progs`: Extra programs. *makepage* writes complete
|
||||||
|
XHTML documents, rather than fragments. *mkd2html* is similar,
|
||||||
|
but produces HTML.
|
||||||
|
* `installall`: Do all `install*` targets above.
|
||||||
|
* `uninstall`: Remove anything added by `install*` targets above.
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
This is not a port from POSIX to native Plan 9 APIs. The supplied
|
||||||
|
`mkfile` drives Discount's own `../configure.sh` and the `../Makefile`
|
||||||
|
it generates through [Plan 9's ANSI/POSIX Environment (APE)][ape-paper]
|
||||||
|
(in [*pcc*(1)][pcc-man]) to build the Discount source, then copies
|
||||||
|
the results to locations appropriate for system-wide use on Plan 9.
|
||||||
|
|
||||||
|
[ape-paper]: https://plan9.io/sys/doc/ape.html
|
||||||
|
[pcc-man]: https://plan9.io/magic/man2html/1/pcc
|
||||||
169
Plan9/markdown.1
Normal file
169
Plan9/markdown.1
Normal file
@ -0,0 +1,169 @@
|
|||||||
|
.TH MARKDOWN 1
|
||||||
|
.SH NAME
|
||||||
|
markdown \- convert Markdown text to HTML
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.B markdown
|
||||||
|
[
|
||||||
|
.B -dTV
|
||||||
|
]
|
||||||
|
[
|
||||||
|
.BI -b " url-base
|
||||||
|
]
|
||||||
|
[
|
||||||
|
.BI -F " bitmap
|
||||||
|
]
|
||||||
|
[
|
||||||
|
.BI -f " flags
|
||||||
|
]
|
||||||
|
[
|
||||||
|
.BI -o " ofile
|
||||||
|
]
|
||||||
|
[
|
||||||
|
.BI -s " text
|
||||||
|
]
|
||||||
|
[
|
||||||
|
.BI -t " text
|
||||||
|
]
|
||||||
|
[
|
||||||
|
.I file
|
||||||
|
]
|
||||||
|
.SH DESCRIPTION
|
||||||
|
The
|
||||||
|
.I markdown
|
||||||
|
utility reads the
|
||||||
|
.IR Markdown (6)-formatted
|
||||||
|
.I file
|
||||||
|
(or standard input) and writes its
|
||||||
|
.SM HTML
|
||||||
|
fragment representation on standard output.
|
||||||
|
.PP
|
||||||
|
The options are:
|
||||||
|
.TF dfdoptions
|
||||||
|
.TP
|
||||||
|
.BI -b " url-base
|
||||||
|
Links in source begining with
|
||||||
|
.B /
|
||||||
|
will be prefixed with
|
||||||
|
.I url-base
|
||||||
|
in the output.
|
||||||
|
.TP
|
||||||
|
.B -d
|
||||||
|
Instead of printing an
|
||||||
|
.SM HTML
|
||||||
|
fragment, print a parse tree.
|
||||||
|
.TP
|
||||||
|
.BI -F " bitmap
|
||||||
|
Set translation flags.
|
||||||
|
.I Bitmap
|
||||||
|
is a bit map of the various configuration options described in
|
||||||
|
.IR markdown (2).
|
||||||
|
.TP
|
||||||
|
.BI -f " flags
|
||||||
|
Set or clear various translation
|
||||||
|
.IR flags ,
|
||||||
|
described below.
|
||||||
|
.I Flags
|
||||||
|
are in a comma-delimited list, with an optional
|
||||||
|
.B +
|
||||||
|
(set) prefix on each flag.
|
||||||
|
.TP
|
||||||
|
.BI -o " ofile
|
||||||
|
Write the generated
|
||||||
|
.SM HTML
|
||||||
|
to
|
||||||
|
.IR ofile .
|
||||||
|
.TP
|
||||||
|
.BI -s " text
|
||||||
|
Use the
|
||||||
|
.IR markdown (2)
|
||||||
|
function to format the
|
||||||
|
.I text
|
||||||
|
on standard input.
|
||||||
|
.TP
|
||||||
|
.B -T
|
||||||
|
Under
|
||||||
|
.B -f
|
||||||
|
.BR toc ,
|
||||||
|
print the table of contents as an unordered list before the usual
|
||||||
|
.SM HTML
|
||||||
|
output.
|
||||||
|
.TP
|
||||||
|
.BI -t " text
|
||||||
|
Use
|
||||||
|
.IR mkd_text
|
||||||
|
(in
|
||||||
|
.IR markdown (2))
|
||||||
|
to format
|
||||||
|
.I text
|
||||||
|
instead of processing standard input with
|
||||||
|
.IR markdown .
|
||||||
|
.TP
|
||||||
|
.B -V
|
||||||
|
Show version number and configuration. If the version includes the string
|
||||||
|
.BR DL_TAG ,
|
||||||
|
.I markdown
|
||||||
|
was configured with definition list support. If the version includes the string
|
||||||
|
.BR HEADER ,
|
||||||
|
.I markdown
|
||||||
|
was configured to support pandoc header blocks.
|
||||||
|
.PD
|
||||||
|
.SS TRANSLATION FLAGS
|
||||||
|
The translation flags understood by
|
||||||
|
.B -f
|
||||||
|
are:
|
||||||
|
.TF \ noheader
|
||||||
|
.TP
|
||||||
|
.B noimage
|
||||||
|
Don't allow image tags.
|
||||||
|
.TP
|
||||||
|
.B nolinks
|
||||||
|
Don't allow links.
|
||||||
|
.TP
|
||||||
|
.B nohtml
|
||||||
|
Don't allow any embedded HTML.
|
||||||
|
.TP
|
||||||
|
.B cdata
|
||||||
|
Generate valid XML output.
|
||||||
|
.TP
|
||||||
|
.B noheader
|
||||||
|
Do not process pandoc headers.
|
||||||
|
.TP
|
||||||
|
.B notables
|
||||||
|
Do not process the syntax extension for tables.
|
||||||
|
.TP
|
||||||
|
.B tabstops
|
||||||
|
Use Markdown-standard 4-space tabstops.
|
||||||
|
.TP
|
||||||
|
.B strict
|
||||||
|
Disable superscript and relaxed emphasis.
|
||||||
|
.TP
|
||||||
|
.B relax
|
||||||
|
Enable superscript and relaxed emphasis (the default).
|
||||||
|
.TP
|
||||||
|
.B toc
|
||||||
|
Enable table of contents support, generated from headings (in
|
||||||
|
.IR markdown (6))
|
||||||
|
in the source.
|
||||||
|
.TP
|
||||||
|
.B 1.0
|
||||||
|
Revert to Markdown 1.0 compatibility.
|
||||||
|
.PD
|
||||||
|
.PP
|
||||||
|
For example,
|
||||||
|
.B -f nolinks,quot
|
||||||
|
tells
|
||||||
|
.I markdown
|
||||||
|
not to allow
|
||||||
|
.B <a>
|
||||||
|
tags, and to expand double quotes.
|
||||||
|
.SH SOURCE
|
||||||
|
.B /sys/src/cmd/discount
|
||||||
|
.SH SEE ALSO
|
||||||
|
.IR markdown (2),
|
||||||
|
.IR markdown (6)
|
||||||
|
.PP
|
||||||
|
http://daringfireball.net/projects/markdown/,
|
||||||
|
``Markdown''.
|
||||||
|
.SH DIAGNOSTICS
|
||||||
|
.I Markdown
|
||||||
|
exits 0 on success and >0 if an error occurs.
|
||||||
332
Plan9/markdown.2
Normal file
332
Plan9/markdown.2
Normal file
@ -0,0 +1,332 @@
|
|||||||
|
.TH MARKDOWN 2
|
||||||
|
.SH NAME
|
||||||
|
mkd_in, mkd_string, markdown, mkd_compile, mkd_css, mkd_generatecss,
|
||||||
|
mkd_document, mkd_generatehtml, mkd_xhtmlpage, mkd_toc, mkd_generatetoc,
|
||||||
|
mkd_cleanup, mkd_doc_title, mkd_doc_author, mkd_doc_date, mkd_line,
|
||||||
|
mkd_generateline \- convert Markdown text to HTML
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.ta \w'MMIOT* 'u
|
||||||
|
.B #include <mkdio.h>
|
||||||
|
.PP
|
||||||
|
.B
|
||||||
|
MMIOT* mkd_in(FILE *input, int flags)
|
||||||
|
.PP
|
||||||
|
.B
|
||||||
|
MMIOT* mkd_string(char *buf, int size, int flags)
|
||||||
|
.PP
|
||||||
|
.B
|
||||||
|
int markdown(MMIOT *doc, FILE *output, int flags)
|
||||||
|
.PP
|
||||||
|
.B
|
||||||
|
int mkd_compile(MMIOT *document, int flags)
|
||||||
|
.PP
|
||||||
|
.B
|
||||||
|
int mkd_css(MMIOT *document, char **doc)
|
||||||
|
.PP
|
||||||
|
.B
|
||||||
|
int mkd_generatecss(MMIOT *document, FILE *output)
|
||||||
|
.PP
|
||||||
|
.B
|
||||||
|
int mkd_document(MMIOT *document, char **doc)
|
||||||
|
.PP
|
||||||
|
.B
|
||||||
|
int mkd_generatehtml(MMIOT *document, FILE *output)
|
||||||
|
.PP
|
||||||
|
.B
|
||||||
|
int mkd_xhtmlpage(MMIOT *document, int flags, FILE *output)
|
||||||
|
.PP
|
||||||
|
.B
|
||||||
|
int mkd_toc(MMIOT *document, char **doc)
|
||||||
|
.PP
|
||||||
|
.B
|
||||||
|
int mkd_generatetoc(MMIOT *document, FILE *output)
|
||||||
|
.PP
|
||||||
|
.B
|
||||||
|
void mkd_cleanup(MMIOT*);
|
||||||
|
.PP
|
||||||
|
.B
|
||||||
|
char* mkd_doc_title(MMIOT*)
|
||||||
|
.PP
|
||||||
|
.B
|
||||||
|
char* mkd_doc_author(MMIOT*)
|
||||||
|
.PP
|
||||||
|
.B
|
||||||
|
char* mkd_doc_date(MMIOT*)
|
||||||
|
.PP
|
||||||
|
.B
|
||||||
|
int mkd_line(char *string, int size, char **doc, int flags)
|
||||||
|
.PP
|
||||||
|
.B
|
||||||
|
int mkd_generateline(char *string, int size, FILE *output, int flags)
|
||||||
|
.PD
|
||||||
|
.PP
|
||||||
|
.SH DESCRIPTION
|
||||||
|
These functions convert
|
||||||
|
.IR Markdown (6)
|
||||||
|
text into
|
||||||
|
.SM HTML
|
||||||
|
markup.
|
||||||
|
.PP
|
||||||
|
.I Mkd_in
|
||||||
|
reads the text referenced by pointer to
|
||||||
|
.B FILE
|
||||||
|
.I input
|
||||||
|
and returns a pointer to an
|
||||||
|
.B MMIOT
|
||||||
|
structure of the form expected by
|
||||||
|
.I markdown
|
||||||
|
and the other converters.
|
||||||
|
.I Mkd_string
|
||||||
|
accepts one
|
||||||
|
.I string
|
||||||
|
and returns a pointer to
|
||||||
|
.BR MMIOT .
|
||||||
|
.PP
|
||||||
|
After such preparation,
|
||||||
|
.I markdown
|
||||||
|
converts
|
||||||
|
.I doc
|
||||||
|
and writes the result to
|
||||||
|
.IR output ,
|
||||||
|
while
|
||||||
|
.I mkd_compile
|
||||||
|
transforms
|
||||||
|
.I document
|
||||||
|
in-place.
|
||||||
|
.PP
|
||||||
|
One or more of the following
|
||||||
|
.I flags
|
||||||
|
(combined with
|
||||||
|
.BR OR )
|
||||||
|
control
|
||||||
|
.IR markdown 's
|
||||||
|
processing of
|
||||||
|
.IR doc :
|
||||||
|
.TF MKD_NOIMAGE
|
||||||
|
.TP
|
||||||
|
.B MKD_NOIMAGE
|
||||||
|
Do not process
|
||||||
|
.B ![]
|
||||||
|
and remove
|
||||||
|
.B <img>
|
||||||
|
tags from the output.
|
||||||
|
.TP
|
||||||
|
.B MKD_NOLINKS
|
||||||
|
Do not process
|
||||||
|
.B []
|
||||||
|
and remove
|
||||||
|
.B <a>
|
||||||
|
tags from the output.
|
||||||
|
.TP
|
||||||
|
.B MKD_NOPANTS
|
||||||
|
Suppress Smartypants-style replacement of quotes, dashes, or ellipses.
|
||||||
|
.TP
|
||||||
|
.B MKD_STRICT
|
||||||
|
Disable superscript and relaxed emphasis processing.
|
||||||
|
.TP
|
||||||
|
.B MKD_TAGTEXT
|
||||||
|
Process as inside an
|
||||||
|
.SM HTML
|
||||||
|
tag: no
|
||||||
|
.BR <em> ,
|
||||||
|
no
|
||||||
|
.BR <bold> ,
|
||||||
|
no
|
||||||
|
.SM HTML
|
||||||
|
or
|
||||||
|
.B []
|
||||||
|
expansion.
|
||||||
|
.TP
|
||||||
|
.B MKD_NO_EXT
|
||||||
|
Don't process pseudo-protocols (in
|
||||||
|
.IR markdown (6)).
|
||||||
|
.TP
|
||||||
|
.B MKD_CDATA
|
||||||
|
Generate code for
|
||||||
|
.SM XML
|
||||||
|
.B ![CDATA[...]]
|
||||||
|
element.
|
||||||
|
.TP
|
||||||
|
.B MKD_NOHEADER
|
||||||
|
Don't process Pandoc-style headers.
|
||||||
|
.TP
|
||||||
|
.B MKD_TABSTOP
|
||||||
|
When reading documents, expand tabs to 4 spaces, overriding any compile-time configuration.
|
||||||
|
.TP
|
||||||
|
.B MKD_TOC
|
||||||
|
Label headings for use with the
|
||||||
|
.I mkd_generatetoc
|
||||||
|
and
|
||||||
|
.I mkd_toc
|
||||||
|
functions.
|
||||||
|
.TP
|
||||||
|
.B MKD_1_COMPAT
|
||||||
|
MarkdownTest_1.0 compatibility. Trim trailing spaces from first line of code blocks and disable implicit reference links (in
|
||||||
|
.IR markdown (6)).
|
||||||
|
.TP
|
||||||
|
.B MKD_AUTOLINK
|
||||||
|
Greedy
|
||||||
|
.SM URL
|
||||||
|
generation. When set, any
|
||||||
|
.SM URL
|
||||||
|
is converted to a hyperlink, even those not encased in
|
||||||
|
.BR <> .
|
||||||
|
.TP
|
||||||
|
.B MKD_SAFELINK
|
||||||
|
Don't make hyperlinks from
|
||||||
|
.B [][]
|
||||||
|
links that have unknown
|
||||||
|
.SM URL
|
||||||
|
protocol types.
|
||||||
|
.TP
|
||||||
|
.B MKD_NOTABLES
|
||||||
|
Do not process the syntax extension for tables (in
|
||||||
|
.IR markdown (6)).
|
||||||
|
.TP
|
||||||
|
.B MKD_EMBED
|
||||||
|
All of
|
||||||
|
.BR MKD_NOLINKS ,
|
||||||
|
.BR MKD_NOIMAGE ,
|
||||||
|
and
|
||||||
|
.BR MKD_TAGTEXT .
|
||||||
|
.PD
|
||||||
|
.PP
|
||||||
|
This implementation supports
|
||||||
|
Pandoc-style
|
||||||
|
headers and inline
|
||||||
|
.SM CSS
|
||||||
|
.B <style>
|
||||||
|
blocks, but
|
||||||
|
.I markdown
|
||||||
|
does not access the data provided by these extensions.
|
||||||
|
The following functions do, and allow other manipulations.
|
||||||
|
.PP
|
||||||
|
Given a pointer to
|
||||||
|
.B MMIOT
|
||||||
|
prepared by
|
||||||
|
.I mkd_in
|
||||||
|
or
|
||||||
|
.IR mkd_string ,
|
||||||
|
.I mkd_compile
|
||||||
|
compiles the
|
||||||
|
.I document
|
||||||
|
into
|
||||||
|
.BR <style> ,
|
||||||
|
Pandoc, and
|
||||||
|
.SM HTML
|
||||||
|
sections. It accepts the
|
||||||
|
.I flags
|
||||||
|
described for
|
||||||
|
.IR markdown ,
|
||||||
|
above.
|
||||||
|
.PP
|
||||||
|
Once compiled, the document particulars can be read and written:
|
||||||
|
.PP
|
||||||
|
.I Mkd_css
|
||||||
|
allocates a string and populates it with any
|
||||||
|
.B <style>
|
||||||
|
sections from the document.
|
||||||
|
.I Mkd_generatecss
|
||||||
|
writes any
|
||||||
|
.B <style>
|
||||||
|
sections to
|
||||||
|
.IR output .
|
||||||
|
.PP
|
||||||
|
.I Mkd_document
|
||||||
|
points
|
||||||
|
.I doc
|
||||||
|
to the
|
||||||
|
.B MMIOT
|
||||||
|
.IR document ,
|
||||||
|
returning
|
||||||
|
.IR document 's
|
||||||
|
size.
|
||||||
|
.PP
|
||||||
|
.I Mkd_generatehtml
|
||||||
|
writes the rest of the
|
||||||
|
.I document
|
||||||
|
to the
|
||||||
|
.IR output .
|
||||||
|
.PP
|
||||||
|
.IR Mkd_doc_title ,
|
||||||
|
.IR mkd_doc_author ,
|
||||||
|
and
|
||||||
|
.I mkd_doc_date
|
||||||
|
read the contents of any Pandoc header.
|
||||||
|
.PP
|
||||||
|
.I Mkd_xhtmlpage
|
||||||
|
writes an
|
||||||
|
.SM XHTML
|
||||||
|
page representation of the document.
|
||||||
|
It accepts the
|
||||||
|
.I flags
|
||||||
|
described for
|
||||||
|
.IR markdown ,
|
||||||
|
above.
|
||||||
|
.PP
|
||||||
|
.I Mkd_toc
|
||||||
|
.IR malloc s
|
||||||
|
a buffer into which it writes an outline, in the form of a
|
||||||
|
.B <ul>
|
||||||
|
element populated with
|
||||||
|
.BR <li> s
|
||||||
|
each containing a link to successive headings in the
|
||||||
|
.IR document .
|
||||||
|
It returns the size of that string.
|
||||||
|
.I Mkd_generatetoc
|
||||||
|
is similar,
|
||||||
|
but writes the outline to the
|
||||||
|
.I output
|
||||||
|
referenced by a pointer to
|
||||||
|
.BR FILE .
|
||||||
|
.PP
|
||||||
|
.I Mkd_cleanup
|
||||||
|
deletes a processed
|
||||||
|
.BR MMIOT .
|
||||||
|
.PP
|
||||||
|
The last two functions convert a single line of markdown source, for example a page title or a signature.
|
||||||
|
.I Mkd_line
|
||||||
|
allocates a buffer into which it writes an
|
||||||
|
.SM HTML
|
||||||
|
fragment representation of the
|
||||||
|
.IR string .
|
||||||
|
.I Mkd_generateline
|
||||||
|
writes the result to
|
||||||
|
.IR output .
|
||||||
|
.SH SOURCE
|
||||||
|
.B /sys/src/cmd/discount
|
||||||
|
.SH SEE ALSO
|
||||||
|
.IR markdown (1),
|
||||||
|
.IR markdown (6)
|
||||||
|
.SH DIAGNOSTICS
|
||||||
|
The
|
||||||
|
.I mkd_in
|
||||||
|
and
|
||||||
|
.I mkd_string
|
||||||
|
functions return a pointer to
|
||||||
|
.B MMIOT
|
||||||
|
on success, null on failure.
|
||||||
|
.IR Markdown ,
|
||||||
|
.IR mkd_compile ,
|
||||||
|
.IR mkd_style ,
|
||||||
|
and
|
||||||
|
.I mkd_generatehtml
|
||||||
|
return
|
||||||
|
.B 0
|
||||||
|
on success,
|
||||||
|
.B -1
|
||||||
|
otherwise.
|
||||||
|
.SH BUGS
|
||||||
|
Error handling is minimal at best.
|
||||||
|
.PP
|
||||||
|
The
|
||||||
|
.B MMIOT
|
||||||
|
created by
|
||||||
|
.I mkd_string
|
||||||
|
is deleted by the
|
||||||
|
.I markdown
|
||||||
|
function.
|
||||||
|
.PP
|
||||||
|
This is an
|
||||||
|
.SM APE
|
||||||
|
library.
|
||||||
541
Plan9/markdown.6
Normal file
541
Plan9/markdown.6
Normal file
@ -0,0 +1,541 @@
|
|||||||
|
.TH MARKDOWN 6
|
||||||
|
.SH NAME
|
||||||
|
Markdown \- text formatting syntax
|
||||||
|
.SH DESCRIPTION
|
||||||
|
Markdown
|
||||||
|
is a text markup syntax for machine conversion to
|
||||||
|
the more complex
|
||||||
|
.SM HTML
|
||||||
|
or
|
||||||
|
.SM XHTML
|
||||||
|
markup languages.
|
||||||
|
It is intended to be easy to read and to write, with
|
||||||
|
emphasis on readability.
|
||||||
|
A Markdown-formatted document should be publishable as-is,
|
||||||
|
in plain text, without the formatting distracting the reader.
|
||||||
|
.PP
|
||||||
|
The biggest source of inspiration for Markdown's
|
||||||
|
syntax is the format of plain text email. The markup is comprised entirely
|
||||||
|
of punctuation characters, chosen so as to look like what they mean.
|
||||||
|
Asterisks around a word look like
|
||||||
|
.IR *emphasis* .
|
||||||
|
Markdown lists look like lists. Even
|
||||||
|
blockquotes look like quoted passages of text, assuming the reader has
|
||||||
|
used email.
|
||||||
|
.PP
|
||||||
|
.SS Block Elements
|
||||||
|
.TF W
|
||||||
|
.PD
|
||||||
|
.TP
|
||||||
|
Paragraphs and Line Breaks
|
||||||
|
A paragraph is one or more consecutive lines of text, separated
|
||||||
|
by one or more blank lines. (A blank line is any line that looks like a
|
||||||
|
blank line -- a line containing nothing but spaces or tabs is considered
|
||||||
|
blank.) Normal paragraphs should not be indented with spaces or tabs.
|
||||||
|
.IP
|
||||||
|
Lines may be freely broken for readability; Markdown
|
||||||
|
does not translate source line breaks to
|
||||||
|
.B <br />
|
||||||
|
tags. To request generation of
|
||||||
|
.B <br />
|
||||||
|
in the output, end a line with two or more spaces, then a newline.
|
||||||
|
.TP
|
||||||
|
Headings
|
||||||
|
Headings can be marked in two ways, called
|
||||||
|
.I setext
|
||||||
|
and
|
||||||
|
.IR atx .
|
||||||
|
.IP
|
||||||
|
Setext-style headings are
|
||||||
|
``underlined'' using equal signs (for first-level
|
||||||
|
headings) and dashes (for second-level headings).
|
||||||
|
.IP
|
||||||
|
Atx-style headings use 1-6 hash characters at the start of the line,
|
||||||
|
corresponding to
|
||||||
|
.SM HTML
|
||||||
|
.BR <h^(1-6)^> .
|
||||||
|
Optional closing hashes may follow
|
||||||
|
the heading text.
|
||||||
|
.TP
|
||||||
|
Blockquotes
|
||||||
|
Lines beginning with
|
||||||
|
.B >
|
||||||
|
are output in blockquotes.
|
||||||
|
Blockquotes can be nested
|
||||||
|
by multiple levels of
|
||||||
|
.BR >> .
|
||||||
|
Blockquotes can contain other Markdown elements, including
|
||||||
|
headings, lists, and code blocks.
|
||||||
|
.TP
|
||||||
|
Lists
|
||||||
|
Markdown supports ordered (numbered) and unordered (bulleted) lists.
|
||||||
|
List markers typically start at the left margin, but may be indented by
|
||||||
|
up to three spaces.
|
||||||
|
List markers must be followed by one or more spaces
|
||||||
|
or a tab, then the list item text.
|
||||||
|
A newline terminates each list item.
|
||||||
|
.IP
|
||||||
|
Unordered lists use asterisks, pluses, and hyphens interchangeably as
|
||||||
|
list markers.
|
||||||
|
.IP
|
||||||
|
Ordered lists use integers followed by periods as list markers.
|
||||||
|
The order of the integers is not interpreted,
|
||||||
|
but the list should begin with
|
||||||
|
.BR 1 .
|
||||||
|
.IP
|
||||||
|
If list items are separated by blank lines, Markdown will wrap each list
|
||||||
|
item in
|
||||||
|
.B <p>
|
||||||
|
tags in the
|
||||||
|
.SM HTML
|
||||||
|
output.
|
||||||
|
.IP
|
||||||
|
List items may consist of multiple paragraphs.
|
||||||
|
Each subsequent
|
||||||
|
paragraph within a list item must be indented by either 4 spaces
|
||||||
|
or one tab.
|
||||||
|
To put a blockquote within a list item, the blockquote's
|
||||||
|
.B >
|
||||||
|
marker needs to be indented.
|
||||||
|
To put a code block within a list item, the code block needs
|
||||||
|
to be indented
|
||||||
|
.I twice
|
||||||
|
-- 8 spaces or two tabs.
|
||||||
|
.TP
|
||||||
|
Code Blocks
|
||||||
|
To produce a code block, indent every line of the
|
||||||
|
block by at least 4 spaces or 1 tab.
|
||||||
|
A code block continues until it reaches a line that is not indented.
|
||||||
|
.IP
|
||||||
|
Rather than forming normal paragraphs, the lines
|
||||||
|
of a code block are interpreted literally.
|
||||||
|
Regular Markdown syntax is not processed within code blocks.
|
||||||
|
Markdown wraps a code block in both
|
||||||
|
.B <pre>
|
||||||
|
and
|
||||||
|
.B <code>
|
||||||
|
tags.
|
||||||
|
One level of indentation -- 4
|
||||||
|
spaces or 1 tab -- is removed from each line of the code block in
|
||||||
|
the output.
|
||||||
|
.TP
|
||||||
|
Horizontal Rules
|
||||||
|
Produce a horizontal rule tag
|
||||||
|
.RB ( <hr\ /> )
|
||||||
|
by placing three or
|
||||||
|
more hyphens, asterisks, or underscores on a line by themselves.
|
||||||
|
.SS Span Elements
|
||||||
|
.TF W
|
||||||
|
.PD
|
||||||
|
.TP
|
||||||
|
Links
|
||||||
|
Markdown supports two styles of links:
|
||||||
|
.I inline
|
||||||
|
and
|
||||||
|
.IR reference .
|
||||||
|
In both styles, the link text is delimited by square brackets
|
||||||
|
.RB ( [] ).
|
||||||
|
To create an inline link, use a set of regular parentheses immediately
|
||||||
|
after the link text's closing square bracket.
|
||||||
|
Inside the parentheses,
|
||||||
|
put the link URL, along with an optional
|
||||||
|
title for the link surrounded in double quotes.
|
||||||
|
For example:
|
||||||
|
.IP
|
||||||
|
.EX
|
||||||
|
An [example](http://example.com/ "Title") inline link.
|
||||||
|
.EE
|
||||||
|
.IP
|
||||||
|
Reference-style links use a second set of square brackets, inside
|
||||||
|
which you place a label of your choosing to identify the link:
|
||||||
|
.IP
|
||||||
|
.EX
|
||||||
|
An [example][id] reference-style link.
|
||||||
|
.EE
|
||||||
|
.IP
|
||||||
|
The label is then assigned a value on its own line, anywhere in the document:
|
||||||
|
.IP
|
||||||
|
.EX
|
||||||
|
[id]: http://example.com/ "Optional Title"
|
||||||
|
.EE
|
||||||
|
.IP
|
||||||
|
Link label names may consist of letters, numbers, spaces, and
|
||||||
|
punctuation.
|
||||||
|
Labels are not case sensitive.
|
||||||
|
An empty label bracket
|
||||||
|
set after a reference-style link implies the link label is equivalent to
|
||||||
|
the link text.
|
||||||
|
A URL value can then be assigned to the link by referencing
|
||||||
|
the link text as the label name.
|
||||||
|
.TP
|
||||||
|
Emphasis
|
||||||
|
Markdown treats asterisks
|
||||||
|
.RB ( * )
|
||||||
|
and underscores
|
||||||
|
.RB ( _ )
|
||||||
|
as indicators of emphasis.
|
||||||
|
Text surrounded with single asterisks or underscores
|
||||||
|
will be wrapped with an
|
||||||
|
.SM HTML
|
||||||
|
.B <em>
|
||||||
|
tag.
|
||||||
|
Double asterisks or underscores generate an
|
||||||
|
.SM HTML
|
||||||
|
.B <strong>
|
||||||
|
tag.
|
||||||
|
.TP
|
||||||
|
Code
|
||||||
|
To indicate a span of code, wrap it with backtick quotes
|
||||||
|
.RB ( ` ).
|
||||||
|
Unlike a code block, a code span indicates code within a
|
||||||
|
normal paragraph.
|
||||||
|
To include a literal backtick character within a code span, you can use
|
||||||
|
multiple backticks as the opening and closing delimiters:
|
||||||
|
.IP
|
||||||
|
.EX
|
||||||
|
``There is a literal backtick (`) here.``
|
||||||
|
.EE
|
||||||
|
.TP
|
||||||
|
Images
|
||||||
|
Markdown image syntax is intended to resemble that
|
||||||
|
for links, allowing for two styles, once again
|
||||||
|
.I inline
|
||||||
|
and
|
||||||
|
.IR reference .
|
||||||
|
The syntax is as for each respective style of link, described above, but
|
||||||
|
prefixed with an exclamation mark character
|
||||||
|
.RB ( ! ).
|
||||||
|
Inline image syntax looks like this:
|
||||||
|
.IP
|
||||||
|
.EX
|
||||||
|

|
||||||
|
.EE
|
||||||
|
.IP
|
||||||
|
That is:
|
||||||
|
An exclamation mark;
|
||||||
|
followed by a set of square brackets containing the `alt'
|
||||||
|
attribute text for the image;
|
||||||
|
followed by a set of parentheses containing the URL or path to
|
||||||
|
the image, and an optional `title' attribute enclosed in double
|
||||||
|
or single quotes.
|
||||||
|
.IP
|
||||||
|
Reference-style image syntax looks like this:
|
||||||
|
.IP
|
||||||
|
.EX
|
||||||
|
![Alt text][id]
|
||||||
|
.EE
|
||||||
|
.IP
|
||||||
|
Where
|
||||||
|
.I id
|
||||||
|
is a label used as for reference-style URL links, described above.
|
||||||
|
.SS Convenience
|
||||||
|
.TF W
|
||||||
|
.PD
|
||||||
|
.TP
|
||||||
|
Automatic Links
|
||||||
|
There is a shortcut style for creating ``automatic''
|
||||||
|
links for URLs and email addresses.
|
||||||
|
Surround the URL
|
||||||
|
or address with angle brackets.
|
||||||
|
.TP
|
||||||
|
Backslash Escapes
|
||||||
|
Use backslash escapes to generate literal
|
||||||
|
characters which would otherwise have special meaning in Markdown's
|
||||||
|
formatting syntax.
|
||||||
|
.TP
|
||||||
|
Inline HTML
|
||||||
|
For markup that is not covered by Markdown's
|
||||||
|
syntax, simply use the
|
||||||
|
.SM HTML
|
||||||
|
directly.
|
||||||
|
The only restrictions are that block-level
|
||||||
|
.SM HTML
|
||||||
|
elements --
|
||||||
|
.BR <div> ,
|
||||||
|
.BR <table> ,
|
||||||
|
.BR <pre> ,
|
||||||
|
.BR <p> ,
|
||||||
|
etc. -- must be separated from surrounding
|
||||||
|
content by blank lines, and the start and end tags of the block should
|
||||||
|
not be indented with tabs or spaces. Markdown formatting syntax is
|
||||||
|
not processed within block-level
|
||||||
|
.SM HTML
|
||||||
|
tags.
|
||||||
|
.IP
|
||||||
|
Span-level
|
||||||
|
.SM HTML
|
||||||
|
tags -- e.g.
|
||||||
|
.BR <span> ,
|
||||||
|
.BR <cite> ,
|
||||||
|
or
|
||||||
|
.B <del>
|
||||||
|
-- can be
|
||||||
|
used anywhere in a Markdown
|
||||||
|
paragraph, list item, or heading.
|
||||||
|
It is permitted to use
|
||||||
|
.SM HTML
|
||||||
|
tags instead of Markdown formatting; e.g.
|
||||||
|
.SM HTML
|
||||||
|
.B <a>
|
||||||
|
or
|
||||||
|
.B <img>
|
||||||
|
tags instead of Markdown's
|
||||||
|
link or image syntax.
|
||||||
|
Unlike block-level
|
||||||
|
.SM HTML
|
||||||
|
tags, Markdown
|
||||||
|
syntax
|
||||||
|
.I is
|
||||||
|
processed within the elements of span-level tags.
|
||||||
|
.TP
|
||||||
|
Automatic Special Character Escapes
|
||||||
|
To be displayed literally in a user agent, the characters
|
||||||
|
.B <
|
||||||
|
and
|
||||||
|
.B &
|
||||||
|
must appear as escaped entities in
|
||||||
|
.SM HTML
|
||||||
|
source, e.g.
|
||||||
|
.B <
|
||||||
|
and
|
||||||
|
.BR & .
|
||||||
|
Markdown
|
||||||
|
allows natural use of these characters, taking care of
|
||||||
|
the necessary escaping.
|
||||||
|
The ampersand part of a directly-used
|
||||||
|
.SM HTML
|
||||||
|
entity remains unchanged; otherwise it will be translated
|
||||||
|
into
|
||||||
|
.BR & .
|
||||||
|
Inside code spans and blocks, angle brackets and
|
||||||
|
ampersands are always encoded automatically.
|
||||||
|
This makes it easy to use Markdown to write about
|
||||||
|
.SM HTML
|
||||||
|
code.
|
||||||
|
.PP
|
||||||
|
.SS Smarty Pants
|
||||||
|
The
|
||||||
|
.IR markdown (1)
|
||||||
|
utility transforms a few plain text symbols into their typographically-fancier
|
||||||
|
.SM HTML
|
||||||
|
entity equivalents.
|
||||||
|
These are extensions to the standard Markdown syntax.
|
||||||
|
.TF W
|
||||||
|
.PD
|
||||||
|
.TP
|
||||||
|
Punctuation
|
||||||
|
Input single- and double-quotes are transformed
|
||||||
|
into ``curly'' quote entities in the output (e.g.,
|
||||||
|
.B 'text'
|
||||||
|
becomes
|
||||||
|
.BR ‘text’ ).
|
||||||
|
Input double-dashes
|
||||||
|
.RB ( -- )
|
||||||
|
and triple-dashes become en- and em-dashes, respectively,
|
||||||
|
while a series of three dots
|
||||||
|
.RB ( ... )
|
||||||
|
in the input becomes an ellipsis entity
|
||||||
|
.RB ( … )
|
||||||
|
in the
|
||||||
|
.SM HTML
|
||||||
|
output.
|
||||||
|
.TP
|
||||||
|
Symbols
|
||||||
|
Three other transformations replace the common plain-text shorthands
|
||||||
|
.BR (c) ,
|
||||||
|
.BR (r) ,
|
||||||
|
and
|
||||||
|
.BR (tm)
|
||||||
|
from the input with their respective
|
||||||
|
.SM HTML
|
||||||
|
entities. (As in
|
||||||
|
.B (c)
|
||||||
|
becoming
|
||||||
|
.BR © ,
|
||||||
|
the Copyright symbol entity.)
|
||||||
|
.TP
|
||||||
|
Fractions
|
||||||
|
A small set of plain-text shorthands for fractions is recognized.
|
||||||
|
.B 1/4
|
||||||
|
becomes
|
||||||
|
.BR ¼ ,
|
||||||
|
for example. These fraction notations are replaced with their
|
||||||
|
.SM HTML
|
||||||
|
entity equivalents:
|
||||||
|
.BR 1/4 ,
|
||||||
|
.BR 1/2 ,
|
||||||
|
.BR 3/4 .
|
||||||
|
.B 1/4th
|
||||||
|
and
|
||||||
|
.B 3/4ths
|
||||||
|
are replaced with their entity and the indicated ordinal suffix letters.
|
||||||
|
.PP
|
||||||
|
Like the basic Markdown syntax, none of the ``Smarty Pants'' extensions are processed
|
||||||
|
inside code blocks or spans.
|
||||||
|
.PP
|
||||||
|
.SS Discount Extensions
|
||||||
|
.IR Markdown (1)
|
||||||
|
recognizes some extensions to the Markdown format,
|
||||||
|
many of them adopted or adapted from other Markdown
|
||||||
|
interpreters or document formatting systems.
|
||||||
|
.TF W
|
||||||
|
.PD
|
||||||
|
.TP
|
||||||
|
Pandoc Headers
|
||||||
|
If
|
||||||
|
.I markdown
|
||||||
|
was configured with
|
||||||
|
.BR --enable-pandoc-header ,
|
||||||
|
the markdown source can have a 3-line Pandoc header in the format of
|
||||||
|
.IP
|
||||||
|
.EX
|
||||||
|
% Title
|
||||||
|
% Author
|
||||||
|
% Date
|
||||||
|
.EE
|
||||||
|
.IP
|
||||||
|
whose data is available to the
|
||||||
|
.IR mkd_doc_title ,
|
||||||
|
.IR mkd_doc_author ,
|
||||||
|
and
|
||||||
|
.I mkd_doc_date
|
||||||
|
(in
|
||||||
|
.IR markdown (2))
|
||||||
|
functions.
|
||||||
|
.TP
|
||||||
|
Embedded Stylesheets
|
||||||
|
Stylesheets may be defined and modified in a
|
||||||
|
.B <style>
|
||||||
|
block. A style block is parsed like any other block-level
|
||||||
|
.SM HTML;
|
||||||
|
.B <style>
|
||||||
|
starting on column 1, raw
|
||||||
|
.SM HTML
|
||||||
|
(or, in this case,
|
||||||
|
.SM CSS \)
|
||||||
|
following it, and either ending with a
|
||||||
|
.B </style>
|
||||||
|
at the end of the line or at the beginning of a subsequent line.
|
||||||
|
.IP
|
||||||
|
Style blocks apply to the entire document regardless of where they are defined.
|
||||||
|
.TP
|
||||||
|
Image Dimensions
|
||||||
|
Image specification has been extended with an argument describing image dimensions:
|
||||||
|
.BI = height x width.
|
||||||
|
For an image 400 pixels high and 300 wide, the new syntax is:
|
||||||
|
.IP
|
||||||
|
.EX
|
||||||
|

|
||||||
|
.EE
|
||||||
|
.TP
|
||||||
|
Pseudo-Protocols
|
||||||
|
Pseudo-protocols that may replace the common
|
||||||
|
.B http:
|
||||||
|
or
|
||||||
|
.B mailto:
|
||||||
|
have been added to the link syntax described above.
|
||||||
|
.IP
|
||||||
|
.BR abbr :
|
||||||
|
Text following is used as the
|
||||||
|
.B title
|
||||||
|
attribute of an
|
||||||
|
.B abbr
|
||||||
|
tag wrapping the link text. So
|
||||||
|
.B [LT](abbr:Link Text)
|
||||||
|
gives
|
||||||
|
.B <abbr title="Link Text">LT</abbr>.
|
||||||
|
.IP
|
||||||
|
.BR id :
|
||||||
|
The link text is marked up and written to the output, wrapped with
|
||||||
|
.B <a id=text following>
|
||||||
|
and
|
||||||
|
.BR </a> .
|
||||||
|
.IP
|
||||||
|
.BR class :
|
||||||
|
The link text is marked up and written to the output, wrapped with
|
||||||
|
.B <span class=text following>
|
||||||
|
and
|
||||||
|
.BR </span> .
|
||||||
|
.IP
|
||||||
|
.BR raw :
|
||||||
|
Text following is written to the output with no further processing.
|
||||||
|
The link text is discarded.
|
||||||
|
.TP
|
||||||
|
Alphabetic Lists
|
||||||
|
If
|
||||||
|
.I markdown
|
||||||
|
was configured with
|
||||||
|
.BR --enable-alpha-list ,
|
||||||
|
.IP
|
||||||
|
.EX
|
||||||
|
a. this
|
||||||
|
b. is
|
||||||
|
c. an alphabetic
|
||||||
|
d. list
|
||||||
|
.EE
|
||||||
|
.IP
|
||||||
|
yields an
|
||||||
|
.SM HTML
|
||||||
|
.B ol
|
||||||
|
ordered list.
|
||||||
|
.TP
|
||||||
|
Definition Lists
|
||||||
|
If configured with
|
||||||
|
.BR --enable-dl-tag ,
|
||||||
|
markup for definition lists is enabled. A definition list item is defined as
|
||||||
|
.IP
|
||||||
|
.EX
|
||||||
|
=term=
|
||||||
|
definition
|
||||||
|
.EE
|
||||||
|
.TP
|
||||||
|
Tables
|
||||||
|
Tables are specified with a pipe
|
||||||
|
.RB ( | )
|
||||||
|
and dash
|
||||||
|
.RB ( - )
|
||||||
|
marking. The markdown text
|
||||||
|
.IP
|
||||||
|
.EX
|
||||||
|
header0|header1
|
||||||
|
-------|-------
|
||||||
|
textA|textB
|
||||||
|
textC|textD
|
||||||
|
.EE
|
||||||
|
.IP
|
||||||
|
will produce an
|
||||||
|
.SM HTML
|
||||||
|
.B table
|
||||||
|
of two columns and three rows.
|
||||||
|
A header row is designated by ``underlining'' with dashes.
|
||||||
|
Declare a column's alignment by affixing a colon
|
||||||
|
.RB ( : )
|
||||||
|
to the left or right end of the dashes underlining its header.
|
||||||
|
In the output, this
|
||||||
|
yields the corresponding value for the
|
||||||
|
.B align
|
||||||
|
attribute on each
|
||||||
|
.B td
|
||||||
|
cell in the column.
|
||||||
|
A colon at both ends of a column's header dashes indicates center alignment.
|
||||||
|
.TP
|
||||||
|
Relaxed Emphasis
|
||||||
|
The rules for emphasis are changed so that a single
|
||||||
|
.B _
|
||||||
|
will not count as an emphasis character in the middle of a word.
|
||||||
|
This is useful for documenting some code where
|
||||||
|
.B _
|
||||||
|
appears frequently, and would normally require a backslash escape.
|
||||||
|
.PD
|
||||||
|
.SH SEE ALSO
|
||||||
|
.IR markdown (1),
|
||||||
|
.IR markdown (2)
|
||||||
|
.PP
|
||||||
|
http://daringfireball.net/projects/markdown/syntax/,
|
||||||
|
``Markdown: Syntax''.
|
||||||
|
.PP
|
||||||
|
http://daringfireball.net/projects/smartypants/,
|
||||||
|
``Smarty Pants''.
|
||||||
|
.PP
|
||||||
|
http://michelf.com/projects/php-markdown/extra/#table,
|
||||||
|
``PHP Markdown Extra: Tables''.
|
||||||
45
Plan9/mkfile
Normal file
45
Plan9/mkfile
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
BIN=/$objtype/bin
|
||||||
|
CC='cc'
|
||||||
|
CFLAGS='-D_BSD_EXTENSION -D_C99_SNPRINTF_EXTENSION'
|
||||||
|
|
||||||
|
markdown:V: ../markdown
|
||||||
|
|
||||||
|
../markdown: ../config.h
|
||||||
|
ape/psh -c 'cd .. && make'
|
||||||
|
|
||||||
|
test: markdown
|
||||||
|
ape/psh -c 'cd .. && make test'
|
||||||
|
|
||||||
|
install:V: ../markdown
|
||||||
|
cp ../markdown $BIN/markdown
|
||||||
|
|
||||||
|
install.progs:V: install
|
||||||
|
cp ../makepage $BIN/makepage
|
||||||
|
cp ../mkd2html $BIN/mkd2html
|
||||||
|
|
||||||
|
install.libs:V: install
|
||||||
|
cp ../mkdio.h /sys/include/ape/mkdio.h
|
||||||
|
cp ../libmarkdown.a /$objtype/lib/ape/libmarkdown.a
|
||||||
|
|
||||||
|
install.man:V: install
|
||||||
|
cp markdown.1 /sys/man/1/markdown
|
||||||
|
cp markdown.2 /sys/man/2/markdown
|
||||||
|
cp markdown.6 /sys/man/6/markdown
|
||||||
|
|
||||||
|
installall:V: install.libs install.man install.progs
|
||||||
|
|
||||||
|
uninstall:V:
|
||||||
|
rm -f $BIN/markdown $BIN/makepage $BIN/mkd2html
|
||||||
|
rm -f /sys/include/ape/mkdio.h /$objtype/lib/ape/libmarkdown.a
|
||||||
|
rm -f /sys/man/1/markdown /sys/man/2/markdown /sys/man/6/markdown
|
||||||
|
|
||||||
|
../config.h:
|
||||||
|
ape/psh -c 'cd .. && ./configure.sh $CONFIG'
|
||||||
|
|
||||||
|
config:V: ../config.h
|
||||||
|
|
||||||
|
clean:V:
|
||||||
|
ape/psh -c 'cd .. && make clean'
|
||||||
|
|
||||||
|
nuke:V:
|
||||||
|
ape/psh -c 'cd .. && make distclean'
|
||||||
16
README
Normal file
16
README
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
DISCOUNT is a implementation of John Gruber & Aaron Swartz's
|
||||||
|
Markdown markup language. It implements, as far as I can tell,
|
||||||
|
all of the language as described in
|
||||||
|
<http://daringfireball.net/projects/markdown/syntax>
|
||||||
|
and passes the Markdown test suite at
|
||||||
|
<http://daringfireball.net/projects/downloads/MarkdownTest_1.0.zip>
|
||||||
|
|
||||||
|
DISCOUNT is free software written by Jessica L. Parsons
|
||||||
|
<orc@pell.portland.or.us>; it is released under a BSD-style license
|
||||||
|
that allows you to do as you wish with it as long as you don't
|
||||||
|
attempt to claim it as your own work.
|
||||||
|
|
||||||
|
Most of the programs included in the DISCOUNT distribution have
|
||||||
|
manual pages describing how they work.
|
||||||
|
|
||||||
|
The file INSTALL describes how to build and install discount
|
||||||
44
README.md
44
README.md
@ -1,3 +1,43 @@
|
|||||||
# discount
|
# Discount v3 shared library
|
||||||
|
|
||||||
|
It's fork of Jessica (ex- David) L. Parsons's Clang implementation of John Gruber & Aaron Swartz's Markdown markup language: https://github.com/Orc/discount
|
||||||
|
|
||||||
|
Download page - https://www.pell.portland.or.us/~orc/Code/discount/downloads.html
|
||||||
|
|
||||||
|
By default, discount v3 compiled as static library, but using the lib's API requires shared library.
|
||||||
|
|
||||||
|
Here is the solution:
|
||||||
|
|
||||||
|
1. Clone this repo
|
||||||
|
|
||||||
|
```
|
||||||
|
git clone https://gitlabor.ru/Datenlabor/discount
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Run configure
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
./configure.sh
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
3. If you are already have discount installed, clean it
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
sudo make clean
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
4. Run make and make install
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
make
|
||||||
|
|
||||||
|
make install
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
Discount v3 Markdown lib as shared library
|
|
||||||
142
amalloc.c
Normal file
142
amalloc.c
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
/*
|
||||||
|
* debugging malloc()/realloc()/calloc()/free() that attempts
|
||||||
|
* to keep track of just what's been allocated today.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#define MAGIC 0x1f2e3d4c
|
||||||
|
|
||||||
|
struct alist { int magic, size, index; int *end; struct alist *next, *last; };
|
||||||
|
|
||||||
|
static struct alist list = { 0, 0, 0, 0 };
|
||||||
|
|
||||||
|
static int mallocs=0;
|
||||||
|
static int reallocs=0;
|
||||||
|
static int frees=0;
|
||||||
|
|
||||||
|
static int index = 0;
|
||||||
|
|
||||||
|
static void
|
||||||
|
die(char *msg, int index)
|
||||||
|
{
|
||||||
|
fprintf(stderr, msg, index);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void *
|
||||||
|
acalloc(int count, int size)
|
||||||
|
{
|
||||||
|
struct alist *ret;
|
||||||
|
|
||||||
|
if ( size > 1 ) {
|
||||||
|
count *= size;
|
||||||
|
size = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ret = calloc(count + sizeof(struct alist) + sizeof(int), size) ) {
|
||||||
|
ret->magic = MAGIC;
|
||||||
|
ret->size = size * count;
|
||||||
|
ret->index = index ++;
|
||||||
|
ret->end = (int*)(count + (char*) (ret + 1));
|
||||||
|
*(ret->end) = ~MAGIC;
|
||||||
|
if ( list.next ) {
|
||||||
|
ret->next = list.next;
|
||||||
|
ret->last = &list;
|
||||||
|
ret->next->last = ret;
|
||||||
|
list.next = ret;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ret->last = ret->next = &list;
|
||||||
|
list.next = list.last = ret;
|
||||||
|
}
|
||||||
|
++mallocs;
|
||||||
|
return ret+1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void*
|
||||||
|
amalloc(int size)
|
||||||
|
{
|
||||||
|
void *ret = acalloc(1, size);
|
||||||
|
|
||||||
|
if ( ret ) {
|
||||||
|
/* explicitally fill the mallocated memory with a nonzero character */
|
||||||
|
memset(ret, 0x8f, size);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
afree(void *ptr)
|
||||||
|
{
|
||||||
|
struct alist *p2 = ((struct alist*)ptr)-1;
|
||||||
|
|
||||||
|
if ( p2->magic == MAGIC ) {
|
||||||
|
if ( ! (p2->end && *(p2->end) == ~MAGIC) )
|
||||||
|
die("goddam: corrupted memory block %d in free()!\n", p2->index);
|
||||||
|
p2->last->next = p2->next;
|
||||||
|
p2->next->last = p2->last;
|
||||||
|
++frees;
|
||||||
|
free(p2);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
free(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void *
|
||||||
|
arealloc(void *ptr, int size)
|
||||||
|
{
|
||||||
|
struct alist *p2 = ((struct alist*)ptr)-1;
|
||||||
|
struct alist save;
|
||||||
|
|
||||||
|
if ( p2->magic == MAGIC ) {
|
||||||
|
if ( ! (p2->end && *(p2->end) == ~MAGIC) )
|
||||||
|
die("goddam: corrupted memory block %d in realloc()!\n", p2->index);
|
||||||
|
save.next = p2->next;
|
||||||
|
save.last = p2->last;
|
||||||
|
p2 = realloc(p2, sizeof(int) + sizeof(*p2) + size);
|
||||||
|
|
||||||
|
if ( p2 ) {
|
||||||
|
p2->size = size;
|
||||||
|
p2->end = (int*)(size + (char*) (p2 + 1));
|
||||||
|
*(p2->end) = ~MAGIC;
|
||||||
|
p2->next->last = p2;
|
||||||
|
p2->last->next = p2;
|
||||||
|
++reallocs;
|
||||||
|
return p2+1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
save.next->last = save.last;
|
||||||
|
save.last->next = save.next;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return realloc(ptr, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
adump()
|
||||||
|
{
|
||||||
|
struct alist *p;
|
||||||
|
|
||||||
|
|
||||||
|
for ( p = list.next; p && (p != &list); p = p->next ) {
|
||||||
|
fprintf(stderr, "allocated: %d byte%s\n", p->size, (p->size==1) ? "" : "s");
|
||||||
|
fprintf(stderr, " [%.*s]\n", p->size, (char*)(p+1));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( getenv("AMALLOC_STATISTICS") ) {
|
||||||
|
fprintf(stderr, "%d malloc%s\n", mallocs, (mallocs==1)?"":"s");
|
||||||
|
fprintf(stderr, "%d realloc%s\n", reallocs, (reallocs==1)?"":"s");
|
||||||
|
fprintf(stderr, "%d free%s\n", frees, (frees==1)?"":"s");
|
||||||
|
}
|
||||||
|
}
|
||||||
29
amalloc.h
Normal file
29
amalloc.h
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* debugging malloc()/realloc()/calloc()/free() that attempts
|
||||||
|
* to keep track of just what's been allocated today.
|
||||||
|
*/
|
||||||
|
#ifndef AMALLOC_D
|
||||||
|
#define AMALLOC_D
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#ifdef USE_AMALLOC
|
||||||
|
|
||||||
|
extern void *amalloc(int);
|
||||||
|
extern void *acalloc(int,int);
|
||||||
|
extern void *arealloc(void*,int);
|
||||||
|
extern void afree(void*);
|
||||||
|
extern void adump();
|
||||||
|
|
||||||
|
#define malloc amalloc
|
||||||
|
#define calloc acalloc
|
||||||
|
#define realloc arealloc
|
||||||
|
#define free afree
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define adump() (void)1
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif/*AMALLOC_D*/
|
||||||
42
basename.c
Normal file
42
basename.c
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* mkdio -- markdown front end input functions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007 Jessica L Parsons.
|
||||||
|
* The redistribution terms are provided in the COPYRIGHT file that must
|
||||||
|
* be distributed with this source code.
|
||||||
|
*/
|
||||||
|
#include "config.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
#include "mkdio.h"
|
||||||
|
#include "cstring.h"
|
||||||
|
#include "amalloc.h"
|
||||||
|
|
||||||
|
static char *
|
||||||
|
e_basename(const char *string, const int size, void *context)
|
||||||
|
{
|
||||||
|
char *ret;
|
||||||
|
char *base = (char*)context;
|
||||||
|
|
||||||
|
if ( base && string && (string[0] == '/') && (ret=malloc(strlen(base)+size+2)) ) {
|
||||||
|
strcpy(ret, base);
|
||||||
|
strncat(ret, string, size);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
basename_free(char *p, int len, void *ctx)
|
||||||
|
{
|
||||||
|
if ( p ) free(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
mkd_basename(MMIOT *document, char *base)
|
||||||
|
{
|
||||||
|
if ( document && base )
|
||||||
|
mkd_e_url(document, e_basename, (mkd_free_t)basename_free, base);
|
||||||
|
}
|
||||||
266
cmake/CMakeLists.txt
Normal file
266
cmake/CMakeLists.txt
Normal file
@ -0,0 +1,266 @@
|
|||||||
|
cmake_minimum_required(VERSION 2.8.12)
|
||||||
|
|
||||||
|
project(DISCOUNT C)
|
||||||
|
|
||||||
|
get_filename_component(_ROOT "${CMAKE_CURRENT_LIST_DIR}" PATH)
|
||||||
|
|
||||||
|
file(READ "${_ROOT}/VERSION" ${PROJECT_NAME}_VERSION)
|
||||||
|
string(STRIP "${${PROJECT_NAME}_VERSION}" ${PROJECT_NAME}_VERSION)
|
||||||
|
|
||||||
|
set(${PROJECT_NAME}_WITH_TABSTOPS "4" CACHE STRING
|
||||||
|
"Set tabstops to N characters (default is 4)")
|
||||||
|
set(TABSTOP "${${PROJECT_NAME}_WITH_TABSTOPS}")
|
||||||
|
|
||||||
|
set(${PROJECT_NAME}_MAKE_INSTALL ON CACHE BOOL
|
||||||
|
"Set to OFF to disable install rules (default is ON)")
|
||||||
|
|
||||||
|
set(${PROJECT_NAME}_INSTALL_SAMPLES OFF CACHE BOOL
|
||||||
|
"Set to ON to install sample programs (default is OFF)")
|
||||||
|
|
||||||
|
set(${PROJECT_NAME}_ONLY_LIBRARY OFF CACHE BOOL
|
||||||
|
"Set to ON to only build markdown library (default is OFF)")
|
||||||
|
|
||||||
|
set(${PROJECT_NAME}_CXX_BINDING OFF CACHE BOOL
|
||||||
|
"Set to ON to install header files with c++ wrappers (default is OFF)")
|
||||||
|
|
||||||
|
# Check headers
|
||||||
|
include(CheckIncludeFile)
|
||||||
|
check_include_file(libgen.h HAVE_LIBGEN_H)
|
||||||
|
check_include_file(pwd.h HAVE_PWD_H)
|
||||||
|
check_include_file(alloca.h HAVE_ALLOCA_H)
|
||||||
|
check_include_file(malloc.h HAVE_MALLOC_H)
|
||||||
|
check_include_file(sys/stat.h HAVE_STAT)
|
||||||
|
|
||||||
|
# Types detection (from configure.inc: AC_SCALAR_TYPES ())
|
||||||
|
include(CheckTypeSize)
|
||||||
|
check_type_size("unsigned long" SIZEOF_ULONG BUILTIN_TYPES_ONLY)
|
||||||
|
check_type_size("unsigned int" SIZEOF_UINT BUILTIN_TYPES_ONLY)
|
||||||
|
check_type_size("unsigned short" SIZEOF_USHORT BUILTIN_TYPES_ONLY)
|
||||||
|
|
||||||
|
if(SIZEOF_ULONG EQUAL 4)
|
||||||
|
set(DWORD "unsigned long")
|
||||||
|
elseif(SIZEOF_UINT EQUAL 4)
|
||||||
|
set(DWORD "unsigned int")
|
||||||
|
else()
|
||||||
|
message(FATAL_ERROR "Could not detect DWORD type")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(SIZEOF_UINT EQUAL 2)
|
||||||
|
set(WORD "unsigned int")
|
||||||
|
elseif(SIZEOF_USHORT EQUAL 2)
|
||||||
|
set(WORD "unsigned short")
|
||||||
|
else()
|
||||||
|
message(FATAL_ERROR "Could not detect WORD type")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(BYTE "unsigned char")
|
||||||
|
|
||||||
|
# Check symbols
|
||||||
|
include(CheckSymbolExists)
|
||||||
|
foreach(_symbol
|
||||||
|
bzero
|
||||||
|
strcasecmp _stricmp
|
||||||
|
strncasecmp _strnicmp)
|
||||||
|
string(TOUPPER ${_symbol} _SYMBOL)
|
||||||
|
check_symbol_exists(${_symbol} string.h HAVE_${_SYMBOL})
|
||||||
|
endforeach()
|
||||||
|
check_symbol_exists(random stdlib.h HAVE_RANDOM)
|
||||||
|
check_symbol_exists(srandom stdlib.h HAVE_SRANDOM)
|
||||||
|
check_symbol_exists(getpwuid pwd.h HAVE_GETPWUID)
|
||||||
|
check_symbol_exists(basename libgen.h HAVE_BASENAME)
|
||||||
|
check_symbol_exists(fchdir unistd.h HAVE_FCHDIR)
|
||||||
|
if(HAVE_STAT)
|
||||||
|
check_symbol_exists(S_ISCHR sys/stat.h HAVE_S_ISCHR)
|
||||||
|
check_symbol_exists(S_ISFIFO sys/stat.h HAVE_S_ISFIFO)
|
||||||
|
check_symbol_exists(S_ISSOCK sys/stat.h HAVE_S_ISSOCK)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT HAVE_BZERO)
|
||||||
|
set(DEFINE_BZERO "#define bzero(p, n) memset(p, 0, n)")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT HAVE_STRCASECMP)
|
||||||
|
if(HAVE__STRICMP)
|
||||||
|
set(DEFINE_STRCASECMP "#define strcasecmp _stricmp")
|
||||||
|
else()
|
||||||
|
set(DEFINE_STRCASECMP "#error The symbol strcasecmp is not defined.")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT HAVE_STRNCASECMP)
|
||||||
|
if(HAVE__STRNICMP)
|
||||||
|
set(DEFINE_STRNCASECMP "#define strncasecmp _strnicmp")
|
||||||
|
else()
|
||||||
|
set(DEFINE_STRNCASECMP "#error The symbol strncasecmp is not defined.")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT HAVE_S_ISCHR OR NOT HAVE_S_ISFIFO OR NOT HAVE_S_ISSOCK)
|
||||||
|
set(HAVE_STAT "")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
configure_file(config.h.in
|
||||||
|
"${CMAKE_CURRENT_BINARY_DIR}/config.h"
|
||||||
|
@ONLY)
|
||||||
|
|
||||||
|
configure_file("${_ROOT}/version.c.in"
|
||||||
|
"${CMAKE_CURRENT_BINARY_DIR}/version.c"
|
||||||
|
@ONLY)
|
||||||
|
set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/version.c" APPEND PROPERTY COMPILE_DEFINITIONS
|
||||||
|
BRANCH=""
|
||||||
|
VERSION="${${PROJECT_NAME}_VERSION}")
|
||||||
|
|
||||||
|
configure_file("${_ROOT}/mkdio.h.in"
|
||||||
|
"${CMAKE_CURRENT_BINARY_DIR}/mkdio.h"
|
||||||
|
@ONLY)
|
||||||
|
if(${PROJECT_NAME}_CXX_BINDING)
|
||||||
|
message(STATUS "Applying c++ glue to mkdio.h")
|
||||||
|
file(READ "${CMAKE_CURRENT_BINARY_DIR}/mkdio.h" _ROOT_MKDIO_H)
|
||||||
|
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/mkdio.h" "#ifdef __cplusplus\nextern \"C\" {\n#endif\n")
|
||||||
|
file(APPEND "${CMAKE_CURRENT_BINARY_DIR}/mkdio.h" "${_ROOT_MKDIO_H}")
|
||||||
|
file(APPEND "${CMAKE_CURRENT_BINARY_DIR}/mkdio.h" "#ifdef __cplusplus\n}\n#endif\n")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_executable(mktags
|
||||||
|
"${_ROOT}/mktags.c")
|
||||||
|
|
||||||
|
set(BLOCKTAGS_FILE "${CMAKE_CURRENT_BINARY_DIR}/blocktags")
|
||||||
|
add_custom_command(OUTPUT "${BLOCKTAGS_FILE}"
|
||||||
|
COMMAND mktags > ${BLOCKTAGS_FILE}
|
||||||
|
WORKING_DIRECTORY "${_ROOT}")
|
||||||
|
|
||||||
|
target_include_directories(mktags
|
||||||
|
PRIVATE
|
||||||
|
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>
|
||||||
|
)
|
||||||
|
|
||||||
|
add_library(libmarkdown
|
||||||
|
"${_ROOT}/mkdio.c"
|
||||||
|
"${_ROOT}/markdown.c"
|
||||||
|
"${_ROOT}/dumptree.c"
|
||||||
|
"${_ROOT}/generate.c"
|
||||||
|
"${_ROOT}/resource.c"
|
||||||
|
"${_ROOT}/docheader.c"
|
||||||
|
"${CMAKE_CURRENT_BINARY_DIR}/version.c"
|
||||||
|
"${_ROOT}/toc.c"
|
||||||
|
"${_ROOT}/css.c"
|
||||||
|
"${_ROOT}/xml.c"
|
||||||
|
"${_ROOT}/Csio.c"
|
||||||
|
"${_ROOT}/xmlpage.c"
|
||||||
|
"${_ROOT}/basename.c"
|
||||||
|
"${_ROOT}/emmatch.c"
|
||||||
|
"${_ROOT}/github_flavoured.c"
|
||||||
|
"${_ROOT}/setup.c"
|
||||||
|
"${BLOCKTAGS_FILE}"
|
||||||
|
"${_ROOT}/tags.c"
|
||||||
|
"${_ROOT}/html5.c"
|
||||||
|
"${_ROOT}/v2compat.c"
|
||||||
|
"${_ROOT}/flagprocs.c"
|
||||||
|
"${_ROOT}/flags.c")
|
||||||
|
|
||||||
|
set_target_properties(libmarkdown PROPERTIES
|
||||||
|
OUTPUT_NAME markdown)
|
||||||
|
|
||||||
|
target_include_directories(libmarkdown
|
||||||
|
PUBLIC
|
||||||
|
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>
|
||||||
|
PRIVATE
|
||||||
|
$<BUILD_INTERFACE:${_ROOT}>
|
||||||
|
)
|
||||||
|
|
||||||
|
if(NOT ${PROJECT_NAME}_ONLY_LIBRARY)
|
||||||
|
add_library(common OBJECT
|
||||||
|
"${_ROOT}/pgm_options.c"
|
||||||
|
"${_ROOT}/gethopt.c")
|
||||||
|
|
||||||
|
target_include_directories(common
|
||||||
|
PRIVATE
|
||||||
|
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>
|
||||||
|
)
|
||||||
|
|
||||||
|
add_executable(markdown
|
||||||
|
"${_ROOT}/main.c"
|
||||||
|
$<TARGET_OBJECTS:common>)
|
||||||
|
|
||||||
|
target_link_libraries(markdown PRIVATE libmarkdown)
|
||||||
|
|
||||||
|
add_executable(mkd2html
|
||||||
|
"${_ROOT}/mkd2html.c"
|
||||||
|
$<TARGET_OBJECTS:common>
|
||||||
|
"${_ROOT}/notspecial.c")
|
||||||
|
|
||||||
|
target_link_libraries(mkd2html PRIVATE libmarkdown)
|
||||||
|
|
||||||
|
add_executable(makepage
|
||||||
|
"${_ROOT}/makepage.c"
|
||||||
|
$<TARGET_OBJECTS:common>)
|
||||||
|
|
||||||
|
target_link_libraries(makepage PRIVATE libmarkdown)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(${PROJECT_NAME}_MAKE_INSTALL)
|
||||||
|
string(TOLOWER ${PROJECT_NAME} _PACKAGE_NAME)
|
||||||
|
include(GNUInstallDirs)
|
||||||
|
if(NOT DEFINED CMAKE_INSTALL_CMAKEDIR)
|
||||||
|
set(CMAKE_INSTALL_CMAKEDIR
|
||||||
|
"${CMAKE_INSTALL_LIBDIR}/cmake/${_PACKAGE_NAME}"
|
||||||
|
CACHE STRING "CMake packages")
|
||||||
|
endif()
|
||||||
|
if(NOT DEFINED CMAKE_INSTALL_PKGCONFIGDIR)
|
||||||
|
set(CMAKE_INSTALL_PKGCONFIGDIR
|
||||||
|
"${CMAKE_INSTALL_LIBDIR}/pkgconfig"
|
||||||
|
CACHE STRING "The pkg-config packages")
|
||||||
|
endif()
|
||||||
|
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/mkdio.h"
|
||||||
|
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}")
|
||||||
|
target_include_directories(libmarkdown INTERFACE
|
||||||
|
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
||||||
|
)
|
||||||
|
set(_TARGETS libmarkdown)
|
||||||
|
if(NOT ${PROJECT_NAME}_ONLY_LIBRARY)
|
||||||
|
list(APPEND _TARGETS markdown)
|
||||||
|
endif()
|
||||||
|
if(${PROJECT_NAME}_INSTALL_SAMPLES)
|
||||||
|
list(APPEND _TARGETS mkd2html makepage)
|
||||||
|
endif()
|
||||||
|
install(TARGETS ${_TARGETS} EXPORT ${_PACKAGE_NAME}-targets
|
||||||
|
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}"
|
||||||
|
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
|
||||||
|
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}")
|
||||||
|
install(EXPORT ${_PACKAGE_NAME}-targets
|
||||||
|
NAMESPACE ${_PACKAGE_NAME}::
|
||||||
|
DESTINATION "${CMAKE_INSTALL_CMAKEDIR}")
|
||||||
|
include(CMakePackageConfigHelpers)
|
||||||
|
write_basic_package_version_file(
|
||||||
|
"${CMAKE_CURRENT_BINARY_DIR}/${_PACKAGE_NAME}-config-version.cmake"
|
||||||
|
VERSION ${${PROJECT_NAME}_VERSION}
|
||||||
|
COMPATIBILITY AnyNewerVersion
|
||||||
|
)
|
||||||
|
configure_file("${CMAKE_CURRENT_LIST_DIR}/discount-config.cmake.in"
|
||||||
|
"${CMAKE_CURRENT_BINARY_DIR}/${_PACKAGE_NAME}-config.cmake"
|
||||||
|
@ONLY)
|
||||||
|
install(FILES
|
||||||
|
"${CMAKE_CURRENT_BINARY_DIR}/${_PACKAGE_NAME}-config.cmake"
|
||||||
|
"${CMAKE_CURRENT_BINARY_DIR}/${_PACKAGE_NAME}-config-version.cmake"
|
||||||
|
DESTINATION "${CMAKE_INSTALL_CMAKEDIR}")
|
||||||
|
unset(_TARGETS)
|
||||||
|
unset(_PACKAGE_NAME)
|
||||||
|
set(prefix "${CMAKE_INSTALL_PREFIX}")
|
||||||
|
set(libdir "${CMAKE_INSTALL_FULL_LIBDIR}")
|
||||||
|
set(PACKAGE_NAME "libmarkdown")
|
||||||
|
set(PACKAGE_VERSION "${${PROJECT_NAME}_VERSION}")
|
||||||
|
set(LIBS)
|
||||||
|
configure_file("${_ROOT}/${PACKAGE_NAME}.pc.in"
|
||||||
|
"${CMAKE_CURRENT_BINARY_DIR}/${PACKAGE_NAME}.pc"
|
||||||
|
@ONLY)
|
||||||
|
install(FILES
|
||||||
|
"${CMAKE_CURRENT_BINARY_DIR}/${PACKAGE_NAME}.pc"
|
||||||
|
DESTINATION "${CMAKE_INSTALL_PKGCONFIGDIR}")
|
||||||
|
unset(prefix)
|
||||||
|
unset(libdir)
|
||||||
|
unset(PACKAGE_NAME)
|
||||||
|
unset(PACKAGE_VERSION)
|
||||||
|
unset(LIBS)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
unset(_ROOT)
|
||||||
79
cmake/config.h.in
Normal file
79
cmake/config.h.in
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
/*
|
||||||
|
* Pre-digested configuration header.
|
||||||
|
* Generated from cmake/config.h.in.
|
||||||
|
* Tested with MSVC, MinGW on Windows and with GCC on Linux.
|
||||||
|
* File prototype: msvc/config.h.vc.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _CONFIG_D
|
||||||
|
#define _CONFIG_D 1
|
||||||
|
|
||||||
|
/*
|
||||||
|
* `discount` feature macros - we want them all!
|
||||||
|
*/
|
||||||
|
#ifndef WITH_ID_ANCHOR
|
||||||
|
#define WITH_ID_ANCHOR 1
|
||||||
|
#endif
|
||||||
|
#ifndef WITH_FENCED_CODE
|
||||||
|
#define WITH_FENCED_CODE 1
|
||||||
|
#endif
|
||||||
|
#ifndef WITH_GITHUB_TAGS
|
||||||
|
#define WITH_GITHUB_TAGS 1
|
||||||
|
#endif
|
||||||
|
#ifndef USE_DISCOUNT_DL
|
||||||
|
#define USE_DISCOUNT_DL 1
|
||||||
|
#endif
|
||||||
|
#ifndef USE_EXTRA_DL
|
||||||
|
#define USE_EXTRA_DL 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The Visual C++ "C" compiler has a `__inline` keyword implemented
|
||||||
|
* in Visual Studio 2008 and later, see
|
||||||
|
* <http://msdn.microsoft.com/de-de/library/cx3b23a3%28v=vs.90%29.aspx>
|
||||||
|
*/
|
||||||
|
#if _MSC_VER >= 1500 /* VC 9.0, MSC_VER 15, Visual Studio 2008 */
|
||||||
|
#define inline __inline
|
||||||
|
#else
|
||||||
|
#define inline
|
||||||
|
#endif /* _MSC_VER >= 1500 */
|
||||||
|
|
||||||
|
#endif /* _MSC_VER */
|
||||||
|
|
||||||
|
@DEFINE_BZERO@
|
||||||
|
@DEFINE_STRCASECMP@
|
||||||
|
@DEFINE_STRNCASECMP@
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Beware of conflicts with <Windows.h>, which typedef's these names.
|
||||||
|
*/
|
||||||
|
#ifndef WINVER
|
||||||
|
#define DWORD @DWORD@
|
||||||
|
#define WORD @WORD@
|
||||||
|
#define BYTE @BYTE@
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#cmakedefine HAVE_PWD_H 1
|
||||||
|
#cmakedefine HAVE_GETPWUID 1
|
||||||
|
|
||||||
|
#cmakedefine HAVE_LIBGEN_H 1
|
||||||
|
#cmakedefine HAVE_BASENAME 1
|
||||||
|
|
||||||
|
#cmakedefine HAVE_RANDOM 1
|
||||||
|
#cmakedefine HAVE_SRANDOM 1
|
||||||
|
|
||||||
|
#define INITRNG(x) srand((unsigned int)x)
|
||||||
|
#define COINTOSS() (rand()&1)
|
||||||
|
|
||||||
|
#cmakedefine HAVE_FCHDIR 1
|
||||||
|
#cmakedefine HAVE_ALLOCA_H 1
|
||||||
|
#cmakedefine HAVE_MALLOC_H 1
|
||||||
|
#cmakedefine HAVE_STAT 1
|
||||||
|
|
||||||
|
#define TABSTOP @TABSTOP@
|
||||||
|
|
||||||
|
#define DESTRUCTOR
|
||||||
|
|
||||||
|
#endif /* _CONFIG_D */
|
||||||
1
cmake/discount-config.cmake.in
Normal file
1
cmake/discount-config.cmake.in
Normal file
@ -0,0 +1 @@
|
|||||||
|
include("${CMAKE_CURRENT_LIST_DIR}/@_PACKAGE_NAME@-targets.cmake")
|
||||||
2019
configure.inc
Executable file
2019
configure.inc
Executable file
File diff suppressed because it is too large
Load Diff
296
configure.sh
Executable file
296
configure.sh
Executable file
@ -0,0 +1,296 @@
|
|||||||
|
#! /bin/sh
|
||||||
|
|
||||||
|
# local options: ac_help is the help message that describes them
|
||||||
|
# and LOCAL_AC_OPTIONS is the script that interprets them. LOCAL_AC_OPTIONS
|
||||||
|
# is a script that's processed with eval, so you need to be very careful to
|
||||||
|
# make certain that what you quote is what you want to quote.
|
||||||
|
|
||||||
|
# load in the configuration file
|
||||||
|
#
|
||||||
|
ac_help='--enable-amalloc Enable memory allocation debugging
|
||||||
|
--with-tabstops=N Set tabstops to N characters (default is 4)
|
||||||
|
--shared Build shared libraries (default is static)
|
||||||
|
--container Build inside a container
|
||||||
|
--pkg-config Install pkg-config(1) glue files
|
||||||
|
--cxx-binding Install header files with c++ wrappers
|
||||||
|
--github-checkbox[=input] Enable github-style checkboxes in lists
|
||||||
|
(if =input, use <input checkbox>, otherwise
|
||||||
|
use html ballot entities)'
|
||||||
|
|
||||||
|
LOCAL_AC_OPTIONS='
|
||||||
|
set=`locals $*`;
|
||||||
|
if [ "$set" ]; then
|
||||||
|
eval $set
|
||||||
|
shift 1
|
||||||
|
else
|
||||||
|
ac_error=T;
|
||||||
|
fi'
|
||||||
|
|
||||||
|
locals() {
|
||||||
|
K=`echo $1 | $AC_UPPERCASE`
|
||||||
|
case "$K" in
|
||||||
|
--SHARED)
|
||||||
|
echo TRY_SHARED=T
|
||||||
|
;;
|
||||||
|
--ENABLE-*) enable=`echo $K | sed -e 's/--ENABLE-//' | tr '-' '_'`
|
||||||
|
echo WITH_${enable}=T ;;
|
||||||
|
--DEBIAN-GLITCH)
|
||||||
|
echo DEBIAN_GLITCH=T
|
||||||
|
;;
|
||||||
|
--CONTAINER)
|
||||||
|
echo CONTAINER=T
|
||||||
|
;;
|
||||||
|
--H1-TITLE)
|
||||||
|
echo H1TITLE=T
|
||||||
|
;;
|
||||||
|
--PKG-CONFIG)
|
||||||
|
echo PKGCONFIG=T
|
||||||
|
;;
|
||||||
|
--CXX-BINDING)
|
||||||
|
echo CXX_BINDING=T
|
||||||
|
;;
|
||||||
|
--GITHUB-CHECKBOX=ENTITY)
|
||||||
|
echo GITHUB_CHECKBOX_STYLE=entity
|
||||||
|
;;
|
||||||
|
--GITHUB-CHECKBOX=INPUT)
|
||||||
|
echo GITHUB_CHECKBOX_STYLE=input
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
VERSION=`cat VERSION`
|
||||||
|
TARGET=markdown
|
||||||
|
. ./configure.inc
|
||||||
|
|
||||||
|
# if there's a makefile here, it's likely that it's a discount
|
||||||
|
# makefile and there's bits of an old configuration here. So
|
||||||
|
# blow everything away before we start the configuration.
|
||||||
|
|
||||||
|
test -f Makefile && make spotless 2>/dev/null >/dev/null
|
||||||
|
|
||||||
|
AC_INIT $TARGET
|
||||||
|
AC_SUB 'PACKAGE_NAME' lib$TARGET
|
||||||
|
AC_SUB 'PACKAGE_VERSION' $VERSION
|
||||||
|
|
||||||
|
# define definition list type defaults (for theme)
|
||||||
|
#
|
||||||
|
case "`echo "$WITH_DL" | $AC_UPPERCASE`" in
|
||||||
|
DISCOUNT) AC_DEFINE THEME_DL_MODE 1 ;;
|
||||||
|
EXTRA) AC_DEFINE THEME_DL_MODE 2 ;;
|
||||||
|
BOTH) AC_DEFINE THEME_DL_MODE 3 ;;
|
||||||
|
esac
|
||||||
|
test "$WITH_FENCED_CODE" && AC_DEFINE THEME_FENCED_CODE 1
|
||||||
|
|
||||||
|
AC_DEFINE THEME_CF "$THEME_CF"
|
||||||
|
|
||||||
|
|
||||||
|
test "$DEBIAN_GLITCH" && AC_DEFINE 'DEBIAN_GLITCH' 1
|
||||||
|
|
||||||
|
AC_PROG_CC
|
||||||
|
AC_QUIET AC_PROG git && AC_DEFINE 'HAS_GIT' '1'
|
||||||
|
|
||||||
|
test "$TRY_SHARED" && AC_COMPILER_PIC && AC_CC_SHLIBS
|
||||||
|
|
||||||
|
if [ "IS_BROKEN_CC" ]; then
|
||||||
|
case "$AC_CC $AC_CFLAGS" in
|
||||||
|
*-pedantic*) ;;
|
||||||
|
*) # hack around deficiencies in gcc and clang
|
||||||
|
#
|
||||||
|
AC_DEFINE 'while(x)' 'while( (x) != 0 )'
|
||||||
|
AC_DEFINE 'if(x)' 'if( (x) != 0 )'
|
||||||
|
|
||||||
|
if [ "$IS_CLANG" ]; then
|
||||||
|
AC_CC="$AC_CC -Wno-implicit-int"
|
||||||
|
elif [ "$IS_GCC" ]; then
|
||||||
|
AC_CC="$AC_CC -Wno-return-type -Wno-implicit-int"
|
||||||
|
fi ;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
AC_PROG ar || AC_FAIL "$TARGET requires ar"
|
||||||
|
AC_PROG ranlib
|
||||||
|
|
||||||
|
# should we create a .pc for pkg-config & GNU automake
|
||||||
|
#
|
||||||
|
if [ "$PKGCONFIG" ]; then
|
||||||
|
AC_SUB MK_PKGCONFIG ''
|
||||||
|
elif AC_PROG pkg-config || AC_PROG automake ; then
|
||||||
|
PKGCONFIG=true
|
||||||
|
AC_SUB MK_PKGCONFIG ''
|
||||||
|
else
|
||||||
|
AC_SUB MK_PKGCONFIG '#'
|
||||||
|
fi
|
||||||
|
|
||||||
|
AC_C_VOLATILE
|
||||||
|
AC_C_CONST
|
||||||
|
AC_C_INLINE
|
||||||
|
AC_SCALAR_TYPES sub hdr
|
||||||
|
AC_CHECK_BASENAME
|
||||||
|
AC_CHECK_ALLOCA
|
||||||
|
|
||||||
|
AC_CHECK_HEADERS sys/types.h pwd.h && AC_CHECK_FUNCS getpwuid
|
||||||
|
if AC_CHECK_HEADERS sys/stat.h && AC_CHECK_FUNCS stat; then
|
||||||
|
|
||||||
|
# need to check some of the S_ISxxx stat macros, because they may not
|
||||||
|
# exist (for notspecial.c)
|
||||||
|
|
||||||
|
cat > ngc$$.c << EOF
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
struct stat info;
|
||||||
|
|
||||||
|
if ( stat(argv[0], &info) != 0 )
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return MACRO(info.st_mode);
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
LOGN "special file macros in sys/stat.h:"
|
||||||
|
_none="none"
|
||||||
|
for x in ISSOCK ISCHR ISFIFO; do
|
||||||
|
if $AC_CC -DMACRO=S_$x -o ngc$$.o ngc$$.c; then
|
||||||
|
LOGN " S_${x}"
|
||||||
|
AC_DEFINE "HAS_${x}" '1'
|
||||||
|
unset _none
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
LOG "${_none}."
|
||||||
|
__remove ngc$$.o ngc$$.c
|
||||||
|
fi
|
||||||
|
|
||||||
|
# find out if the isspace() function on this system is one
|
||||||
|
# that dumps core of characters with the 8th bit set
|
||||||
|
|
||||||
|
cat > ngc$$.c << EOF
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
main()
|
||||||
|
{
|
||||||
|
char text[] = { -3 };
|
||||||
|
|
||||||
|
return isspace(text[0]);
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
if $AC_CC $AC_CFLAGS -o ngc$$ ngc$$.c; then
|
||||||
|
LOGN "is isspace() broken: "
|
||||||
|
if ./ngc$$ ; then
|
||||||
|
LOG "no"
|
||||||
|
else
|
||||||
|
AC_CC="$AC_CC -funsigned-char"
|
||||||
|
|
||||||
|
$AC_CC $AC_CFLAGS -o ngc$$ ngc$$.c
|
||||||
|
|
||||||
|
if ./ngc$$; then
|
||||||
|
LOG "yes (patchable)"
|
||||||
|
else
|
||||||
|
LOG "yes (not patchable)"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
LOG "can't compile test program?"
|
||||||
|
fi
|
||||||
|
rm -rf ngc$$*
|
||||||
|
|
||||||
|
|
||||||
|
if AC_CHECK_FUNCS srandom; then
|
||||||
|
AC_DEFINE 'INITRNG(x)' 'srandom((unsigned int)x)'
|
||||||
|
elif AC_CHECK_FUNCS srand; then
|
||||||
|
AC_DEFINE 'INITRNG(x)' 'srand((unsigned int)x)'
|
||||||
|
else
|
||||||
|
AC_DEFINE 'INITRNG(x)' '(void)1'
|
||||||
|
fi
|
||||||
|
|
||||||
|
AC_CHECK_FUNCS 'memset((char*)0,0,0)' 'string.h' || \
|
||||||
|
AC_CHECK_FUNCS 'memset((char*)0,0,0)' || \
|
||||||
|
AC_FAIL "$TARGET requires memset"
|
||||||
|
|
||||||
|
if AC_CHECK_FUNCS random; then
|
||||||
|
AC_DEFINE 'COINTOSS()' '(random()&1)'
|
||||||
|
elif AC_CHECK_FUNCS rand; then
|
||||||
|
AC_DEFINE 'COINTOSS()' '(rand()&1)'
|
||||||
|
else
|
||||||
|
AC_DEFINE 'COINTOSS()' '1'
|
||||||
|
fi
|
||||||
|
|
||||||
|
if AC_CHECK_FUNCS strcasecmp; then
|
||||||
|
:
|
||||||
|
elif AC_CHECK_FUNCS stricmp; then
|
||||||
|
AC_DEFINE strcasecmp stricmp
|
||||||
|
else
|
||||||
|
AC_FAIL "$TARGET requires either strcasecmp() or stricmp()"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if AC_CHECK_FUNCS strncasecmp; then
|
||||||
|
:
|
||||||
|
elif AC_CHECK_FUNCS strnicmp; then
|
||||||
|
AC_DEFINE strncasecmp strnicmp
|
||||||
|
else
|
||||||
|
AC_FAIL "$TARGET requires either strncasecmp() or strnicmp()"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if AC_CHECK_FUNCS fchdir || AC_CHECK_FUNCS getcwd ; then
|
||||||
|
AC_SUB 'THEME' ''
|
||||||
|
else
|
||||||
|
AC_SUB 'THEME' '#'
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$WITH_TABSTOPS" ]; then
|
||||||
|
TABSTOP=4
|
||||||
|
elif [ "$WITH_TABSTOPS" -eq 1 ]; then
|
||||||
|
TABSTOP=8
|
||||||
|
else
|
||||||
|
TABSTOP=$WITH_TABSTOPS
|
||||||
|
fi
|
||||||
|
AC_DEFINE 'TABSTOP' $TABSTOP
|
||||||
|
AC_SUB 'TABSTOP' $TABSTOP
|
||||||
|
|
||||||
|
|
||||||
|
if [ "$WITH_AMALLOC" ]; then
|
||||||
|
AC_DEFINE 'USE_AMALLOC' 1
|
||||||
|
AC_SUB 'AMALLOC' 'amalloc.o'
|
||||||
|
else
|
||||||
|
AC_SUB 'AMALLOC' ''
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$H1TITLE" ]; then
|
||||||
|
AC_SUB 'H1TITLE' h1title.o
|
||||||
|
AC_DEFINE USE_H1TITLE 1
|
||||||
|
else
|
||||||
|
AC_SUB 'H1TITLE' ''
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$GITHUB_CHECKBOX_STYLE" = "entity" ]; then
|
||||||
|
AC_DEFINE 'CHECKBOX_AS_INPUT' '0'
|
||||||
|
else
|
||||||
|
AC_DEFINE 'CHECKBOX_AS_INPUT' '1'
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
[ "$OS_FREEBSD" -o "$OS_DRAGONFLY" ] || AC_CHECK_HEADERS malloc.h
|
||||||
|
|
||||||
|
[ "$WITH_PANDOC_HEADER" ] && AC_DEFINE 'PANDOC_HEADER' '1'
|
||||||
|
|
||||||
|
GENERATE="Makefile version.c mkdio.h"
|
||||||
|
|
||||||
|
if [ "$PKGCONFIG" ]; then
|
||||||
|
GENERATE="$GENERATE libmarkdown.pc"
|
||||||
|
fi
|
||||||
|
|
||||||
|
AC_OUTPUT $GENERATE
|
||||||
|
|
||||||
|
if [ "$CXX_BINDING" ]; then
|
||||||
|
LOG "applying c++ glue to mkdio.h"
|
||||||
|
mv mkdio.h mkdio.h$$
|
||||||
|
( echo '#ifdef __cplusplus'
|
||||||
|
echo 'extern "C" {'
|
||||||
|
echo '#endif'
|
||||||
|
cat mkdio.h$$
|
||||||
|
echo '#ifdef __cplusplus'
|
||||||
|
echo '}'
|
||||||
|
echo '#endif' ) > mkdio.h
|
||||||
|
rm mkdio.h$$
|
||||||
|
fi
|
||||||
85
css.c
Normal file
85
css.c
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
/* markdown: a C implementation of John Gruber's Markdown markup language.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009 Jessica L Parsons.
|
||||||
|
* The redistribution terms are provided in the COPYRIGHT file that must
|
||||||
|
* be distributed with this source code.
|
||||||
|
*/
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "cstring.h"
|
||||||
|
#include "markdown.h"
|
||||||
|
#include "amalloc.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* dump out stylesheet sections.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
stylesheets(Paragraph *p, Cstring *f)
|
||||||
|
{
|
||||||
|
Line* q;
|
||||||
|
|
||||||
|
for ( ; p ; p = p->next ) {
|
||||||
|
if ( p->typ == STYLE ) {
|
||||||
|
for ( q = p->text; q ; q = q->next ) {
|
||||||
|
Cswrite(f, T(q->text), S(q->text));
|
||||||
|
Csputc('\n', f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( p->down )
|
||||||
|
stylesheets(p->down, f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* dump any embedded styles to a string
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
mkd_css(Document *d, char **res)
|
||||||
|
{
|
||||||
|
Cstring f;
|
||||||
|
int size;
|
||||||
|
|
||||||
|
if ( res && d && d->compiled ) {
|
||||||
|
*res = 0;
|
||||||
|
CREATE(f);
|
||||||
|
RESERVE(f, 100);
|
||||||
|
stylesheets(d->code, &f);
|
||||||
|
|
||||||
|
if ( (size = S(f)) > 0 ) {
|
||||||
|
/* null-terminate, then strdup() into a free()able memory
|
||||||
|
* chunk
|
||||||
|
*/
|
||||||
|
COMPLETE(f);
|
||||||
|
*res = strdup(T(f));
|
||||||
|
}
|
||||||
|
DELETE(f);
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
return EOF;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* dump any embedded styles to a file
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
mkd_generatecss(Document *d, FILE *f)
|
||||||
|
{
|
||||||
|
char *res;
|
||||||
|
int written;
|
||||||
|
int size = mkd_css(d, &res);
|
||||||
|
|
||||||
|
written = (size > 0) ? fwrite(res,1,size,f) : 0;
|
||||||
|
|
||||||
|
if ( res )
|
||||||
|
free(res);
|
||||||
|
|
||||||
|
return (written == size) ? size : EOF;
|
||||||
|
}
|
||||||
78
cstring.h
Normal file
78
cstring.h
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
/* two template types: STRING(t) which defines a pascal-style string
|
||||||
|
* of element (t) [STRING(char) is the closest to the pascal string],
|
||||||
|
* and ANCHOR(t) which defines a baseplate that a linked list can be
|
||||||
|
* built up from. [The linked list /must/ contain a ->next pointer
|
||||||
|
* for linking the list together with.]
|
||||||
|
*/
|
||||||
|
#ifndef _CSTRING_D
|
||||||
|
#define _CSTRING_D
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#ifndef __WITHOUT_AMALLOC
|
||||||
|
# include "amalloc.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* expandable Pascal-style string.
|
||||||
|
*/
|
||||||
|
#define STRING(type) struct { type *text; int size, alloc; }
|
||||||
|
|
||||||
|
#define CREATE(x) ( (T(x) = (void*)0), (S(x) = (x).alloc = 0) )
|
||||||
|
#define EXPAND(x) (S(x)++)[(S(x) < (x).alloc) \
|
||||||
|
? (T(x)) \
|
||||||
|
: (T(x) = T(x) ? realloc(T(x), sizeof T(x)[0] * ((x).alloc += 100)) \
|
||||||
|
: malloc(sizeof T(x)[0] * ((x).alloc += 100)) )]
|
||||||
|
|
||||||
|
#define DELETE(x) ALLOCATED(x) ? (free(T(x)), S(x) = (x).alloc = 0) \
|
||||||
|
: ( S(x) = 0 )
|
||||||
|
#define CLIP(t,i,sz) \
|
||||||
|
S(t) -= ( ((i) >= 0) && ((sz) > 0) && (((i)+(sz)) <= S(t)) ) ? \
|
||||||
|
(memmove(&T(t)[i], &T(t)[i+sz], (S(t)-(i+sz)+1)*sizeof(T(t)[0])), \
|
||||||
|
(sz)) : 0
|
||||||
|
|
||||||
|
#define RESERVE(x, sz) T(x) = ((x).alloc > S(x) + (sz) \
|
||||||
|
? T(x) \
|
||||||
|
: T(x) \
|
||||||
|
? realloc(T(x), sizeof T(x)[0] * ((x).alloc = 100+(sz)+S(x))) \
|
||||||
|
: malloc(sizeof T(x)[0] * ((x).alloc = 100+(sz)+S(x))))
|
||||||
|
#define SUFFIX(t,p,sz) \
|
||||||
|
memcpy(((S(t) += (sz)) - (sz)) + \
|
||||||
|
(T(t) = T(t) ? realloc(T(t), sizeof T(t)[0] * ((t).alloc += sz)) \
|
||||||
|
: malloc(sizeof T(t)[0] * ((t).alloc += sz))), \
|
||||||
|
(p), sizeof(T(t)[0])*(sz))
|
||||||
|
|
||||||
|
#define PREFIX(t,p,sz) \
|
||||||
|
RESERVE( (t), (sz) ); \
|
||||||
|
if ( S(t) ) { memmove(T(t)+(sz), T(t), S(t)); } \
|
||||||
|
memcpy( T(t), (p), (sz) ); \
|
||||||
|
S(t) += (sz)
|
||||||
|
|
||||||
|
/* reference-style links (and images) are stored in an array
|
||||||
|
*/
|
||||||
|
#define T(x) (x).text
|
||||||
|
#define S(x) (x).size
|
||||||
|
#define ALLOCATED(x) (x).alloc
|
||||||
|
|
||||||
|
/* abstract anchor type that defines a list base
|
||||||
|
* with a function that attaches an element to
|
||||||
|
* the end of the list.
|
||||||
|
*
|
||||||
|
* the list base field is named .text so that the T()
|
||||||
|
* macro will work with it.
|
||||||
|
*/
|
||||||
|
#define ANCHOR(t) struct { t *text, *end; }
|
||||||
|
#define E(t) ((t).end)
|
||||||
|
|
||||||
|
#define ATTACH(t, p) ( T(t) ? ( (E(t)->next = (p)), (E(t) = (p)) ) \
|
||||||
|
: ( (T(t) = E(t) = (p)) ) )
|
||||||
|
|
||||||
|
typedef STRING(char) Cstring;
|
||||||
|
|
||||||
|
#define COMPLETE(t) (EXPAND(t) = 0),(S(t)--)
|
||||||
|
|
||||||
|
extern void Csputc(int, Cstring *);
|
||||||
|
extern int Csprintf(Cstring *, char *, ...);
|
||||||
|
extern int Cswrite(Cstring *, char *, int);
|
||||||
|
|
||||||
|
#endif/*_CSTRING_D*/
|
||||||
54
docheader.c
Normal file
54
docheader.c
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
* docheader -- get values from the document header
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007 Jessica L Parsons.
|
||||||
|
* The redistribution terms are provided in the COPYRIGHT file that must
|
||||||
|
* be distributed with this source code.
|
||||||
|
*/
|
||||||
|
#include "config.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
#include "cstring.h"
|
||||||
|
#include "markdown.h"
|
||||||
|
#include "amalloc.h"
|
||||||
|
|
||||||
|
static char *
|
||||||
|
onlyifset(Line *l)
|
||||||
|
{
|
||||||
|
char *ret;
|
||||||
|
|
||||||
|
if ( l->dle < 0 || l->dle >= S(l->text) )
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
ret = T(l->text) + l->dle;
|
||||||
|
|
||||||
|
return ret[0] ? ret : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
mkd_doc_title(Document *doc)
|
||||||
|
{
|
||||||
|
if ( doc && doc->title )
|
||||||
|
return onlyifset(doc->title);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char *
|
||||||
|
mkd_doc_author(Document *doc)
|
||||||
|
{
|
||||||
|
if ( doc && doc->author )
|
||||||
|
return onlyifset(doc->author);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char *
|
||||||
|
mkd_doc_date(Document *doc)
|
||||||
|
{
|
||||||
|
if ( doc && doc->date )
|
||||||
|
return onlyifset(doc->date);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
163
dumptree.c
Normal file
163
dumptree.c
Normal file
@ -0,0 +1,163 @@
|
|||||||
|
/* markdown: a C implementation of John Gruber's Markdown markup language.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007 Jessica L Parsons.
|
||||||
|
* The redistribution terms are provided in the COPYRIGHT file that must
|
||||||
|
* be distributed with this source code.
|
||||||
|
*/
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "markdown.h"
|
||||||
|
#include "cstring.h"
|
||||||
|
#include "amalloc.h"
|
||||||
|
|
||||||
|
struct frame {
|
||||||
|
int indent;
|
||||||
|
char c;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef STRING(struct frame) Stack;
|
||||||
|
|
||||||
|
static char *
|
||||||
|
Pptype(int typ)
|
||||||
|
{
|
||||||
|
switch (typ) {
|
||||||
|
case WHITESPACE: return "whitespace";
|
||||||
|
case CODE : return "code";
|
||||||
|
case QUOTE : return "quote";
|
||||||
|
case MARKUP : return "markup";
|
||||||
|
case HTML : return "html";
|
||||||
|
case DL : return "dl";
|
||||||
|
case UL : return "ul";
|
||||||
|
case OL : return "ol";
|
||||||
|
case LISTITEM : return "item";
|
||||||
|
case HDR : return "header";
|
||||||
|
case HR : return "hr";
|
||||||
|
case TABLE : return "table";
|
||||||
|
case SOURCE : return "source";
|
||||||
|
case STYLE : return "style";
|
||||||
|
default : return "mystery node!";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
pushpfx(int indent, char c, Stack *sp)
|
||||||
|
{
|
||||||
|
struct frame *q = &EXPAND(*sp);
|
||||||
|
|
||||||
|
q->indent = indent;
|
||||||
|
q->c = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
poppfx(Stack *sp)
|
||||||
|
{
|
||||||
|
S(*sp)--;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
changepfx(Stack *sp, char c)
|
||||||
|
{
|
||||||
|
char ch;
|
||||||
|
|
||||||
|
if ( S(*sp) > 0 ) {
|
||||||
|
ch = T(*sp)[S(*sp)-1].c;
|
||||||
|
|
||||||
|
if ( ch == '+' || ch == '|' )
|
||||||
|
T(*sp)[S(*sp)-1].c = c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
printpfx(Stack *sp, FILE *f)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
char c;
|
||||||
|
|
||||||
|
if ( S(*sp) > 0 ) {
|
||||||
|
c = T(*sp)[S(*sp)-1].c;
|
||||||
|
|
||||||
|
if ( c == '+' || c == '-' ) {
|
||||||
|
fprintf(f, "--%c", c);
|
||||||
|
T(*sp)[S(*sp)-1].c = (c == '-') ? ' ' : '|';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
for ( i=0; i < S(*sp); i++ ) {
|
||||||
|
if ( i )
|
||||||
|
fprintf(f, " ");
|
||||||
|
fprintf(f, "%*s%c", T(*sp)[i].indent + 2, " ", T(*sp)[i].c);
|
||||||
|
if ( T(*sp)[i].c == '`' )
|
||||||
|
T(*sp)[i].c = ' ';
|
||||||
|
}
|
||||||
|
fprintf(f, "--");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
dumptree(Paragraph *pp, Stack *sp, FILE *f)
|
||||||
|
{
|
||||||
|
int count;
|
||||||
|
Line *p;
|
||||||
|
int d;
|
||||||
|
static char *Begin[] = { 0, "P", "center" };
|
||||||
|
|
||||||
|
while ( pp ) {
|
||||||
|
if ( !pp->next )
|
||||||
|
changepfx(sp, '`');
|
||||||
|
printpfx(sp, f);
|
||||||
|
|
||||||
|
if ( pp->typ == HDR )
|
||||||
|
d += fprintf(f, "[h%d", pp->hnumber);
|
||||||
|
else
|
||||||
|
d = fprintf(f, "[%s", Pptype(pp->typ));
|
||||||
|
if ( pp->ident )
|
||||||
|
d += fprintf(f, " %s", pp->ident);
|
||||||
|
|
||||||
|
if ( pp->para_flags )
|
||||||
|
d += fprintf(f, " %x", pp->para_flags);
|
||||||
|
|
||||||
|
if ( pp->align > 1 )
|
||||||
|
d += fprintf(f, ", <%s>", Begin[pp->align]);
|
||||||
|
|
||||||
|
for (count=0, p=pp->text; p; ++count, (p = p->next) )
|
||||||
|
;
|
||||||
|
|
||||||
|
if ( count )
|
||||||
|
d += fprintf(f, ", %d line%s", count, (count==1)?"":"s");
|
||||||
|
|
||||||
|
#if EXTENDED_DEBUG
|
||||||
|
if ( pp->text && T(pp->text->text) )
|
||||||
|
d += fprintf(f, " <%.*s>", S(pp->text->text), T(pp->text->text));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
d += fprintf(f, "]");
|
||||||
|
|
||||||
|
if ( pp->down ) {
|
||||||
|
pushpfx(d, pp->down->next ? '+' : '-', sp);
|
||||||
|
dumptree(pp->down, sp, f);
|
||||||
|
poppfx(sp);
|
||||||
|
}
|
||||||
|
else fputc('\n', f);
|
||||||
|
pp = pp->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
mkd_dump(Document *doc, FILE *out, mkd_flag_t *flags, char *title)
|
||||||
|
{
|
||||||
|
Stack stack;
|
||||||
|
|
||||||
|
if ( mkd_compile(doc, flags) && doc->code ) {
|
||||||
|
|
||||||
|
CREATE(stack);
|
||||||
|
pushpfx(fprintf(out, "%s", title), doc->code->next ? '+' : '-', &stack);
|
||||||
|
dumptree(doc->code, &stack, out);
|
||||||
|
DELETE(stack);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
189
emmatch.c
Normal file
189
emmatch.c
Normal file
@ -0,0 +1,189 @@
|
|||||||
|
/* markdown: a C implementation of John Gruber's Markdown markup language.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 Jessica L Parsons.
|
||||||
|
* The redistribution terms are provided in the COPYRIGHT file that must
|
||||||
|
* be distributed with this source code.
|
||||||
|
*/
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "cstring.h"
|
||||||
|
#include "markdown.h"
|
||||||
|
#include "amalloc.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* emmatch: the emphasis mangler that's run after a block
|
||||||
|
* of html has been generated.
|
||||||
|
*
|
||||||
|
* It should create MarkdownTest_1.0 (and _1.0.3)
|
||||||
|
* compatible emphasis for non-pathological cases
|
||||||
|
* and it should fail in a standards-compliant way
|
||||||
|
* when someone attempts to feed it junk.
|
||||||
|
*
|
||||||
|
* Emmatching is done after the input has been
|
||||||
|
* processed into a STRING (f->Q) of text and
|
||||||
|
* emphasis blocks. After ___mkd_emblock() finishes,
|
||||||
|
* it truncates f->Q and leaves the rendered paragraph
|
||||||
|
* if f->out.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* empair() -- find the NEAREST matching emphasis token (or
|
||||||
|
* subtoken of a 3+ long emphasis token.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
empair(MMIOT *f, int first, int last, int match)
|
||||||
|
{
|
||||||
|
|
||||||
|
int i;
|
||||||
|
block *begin, *p;
|
||||||
|
|
||||||
|
begin = &T(f->Q)[first];
|
||||||
|
|
||||||
|
for (i=first+1; i <= last; i++) {
|
||||||
|
p = &T(f->Q)[i];
|
||||||
|
|
||||||
|
if ( (p->b_type != bTEXT) && (p->b_count <= 0) )
|
||||||
|
continue; /* break? */
|
||||||
|
|
||||||
|
if ( p->b_type == begin->b_type ) {
|
||||||
|
if ( p->b_count == match ) /* exact match */
|
||||||
|
return i;
|
||||||
|
|
||||||
|
if ( p->b_count > 2 ) /* fuzzy match */
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
} /* empair */
|
||||||
|
|
||||||
|
|
||||||
|
/* emfill() -- if an emphasis token has leftover stars or underscores,
|
||||||
|
* convert them back into character and append them to b_text.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
emfill(block *p)
|
||||||
|
{
|
||||||
|
int j;
|
||||||
|
|
||||||
|
if ( p->b_type == bTEXT )
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (j=0; j < p->b_count; j++)
|
||||||
|
EXPAND(p->b_text) = p->b_char;
|
||||||
|
p->b_count = 0;
|
||||||
|
} /* emfill */
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
emclose(MMIOT *f, int first, int last)
|
||||||
|
{
|
||||||
|
int j;
|
||||||
|
|
||||||
|
for (j=first+1; j<last-1; j++)
|
||||||
|
emfill(&T(f->Q)[j]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static struct emtags {
|
||||||
|
char open[10];
|
||||||
|
char close[10];
|
||||||
|
int size;
|
||||||
|
} emtags[] = { { "<em>" , "</em>", 5 }, { "<strong>", "</strong>", 9 } };
|
||||||
|
|
||||||
|
|
||||||
|
static void emblock(MMIOT*,int,int);
|
||||||
|
|
||||||
|
|
||||||
|
/* emmatch() -- match emphasis for a single emphasis token.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
emmatch(MMIOT *f, int first, int last)
|
||||||
|
{
|
||||||
|
block *start = &T(f->Q)[first];
|
||||||
|
int e, e2, match;
|
||||||
|
|
||||||
|
switch (start->b_count) {
|
||||||
|
case 2: if ( e = empair(f,first,last,match=2) )
|
||||||
|
break;
|
||||||
|
case 1: e = empair(f,first,last,match=1);
|
||||||
|
break;
|
||||||
|
case 0: return;
|
||||||
|
default:
|
||||||
|
e = empair(f,first,last,1);
|
||||||
|
e2= empair(f,first,last,2);
|
||||||
|
|
||||||
|
if ( e2 >= e ) {
|
||||||
|
e = e2;
|
||||||
|
match = 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
match = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( e ) {
|
||||||
|
/* if we found emphasis to match, match it, recursively call
|
||||||
|
* emblock to match emphasis inside the new html block, add
|
||||||
|
* the emphasis markers for the block, then (tail) recursively
|
||||||
|
* call ourself to match any remaining emphasis on this token.
|
||||||
|
*/
|
||||||
|
block *end = &T(f->Q)[e];
|
||||||
|
|
||||||
|
end->b_count -= match;
|
||||||
|
start->b_count -= match;
|
||||||
|
|
||||||
|
emblock(f, first, e);
|
||||||
|
|
||||||
|
PREFIX(start->b_text, emtags[match-1].open, emtags[match-1].size-1);
|
||||||
|
SUFFIX(end->b_post, emtags[match-1].close, emtags[match-1].size);
|
||||||
|
|
||||||
|
emmatch(f, first, last);
|
||||||
|
}
|
||||||
|
} /* emmatch */
|
||||||
|
|
||||||
|
|
||||||
|
/* emblock() -- walk a blocklist, attempting to match emphasis
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
emblock(MMIOT *f, int first, int last)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for ( i = first; i <= last; i++ )
|
||||||
|
if ( T(f->Q)[i].b_type != bTEXT )
|
||||||
|
emmatch(f, i, last);
|
||||||
|
emclose(f, first, last);
|
||||||
|
} /* emblock */
|
||||||
|
|
||||||
|
|
||||||
|
/* ___mkd_emblock() -- emblock a string of blocks, then concatenate the
|
||||||
|
* resulting text onto f->out.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
___mkd_emblock(MMIOT *f)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
block *p;
|
||||||
|
|
||||||
|
if ( S(f->Q) > 0 ) {
|
||||||
|
emblock(f, 0, S(f->Q)-1);
|
||||||
|
|
||||||
|
for (i=0; i < S(f->Q); i++) {
|
||||||
|
p = &T(f->Q)[i];
|
||||||
|
emfill(p);
|
||||||
|
|
||||||
|
if ( S(p->b_post) ) { SUFFIX(f->out, T(p->b_post), S(p->b_post));
|
||||||
|
DELETE(p->b_post); }
|
||||||
|
if ( S(p->b_text) ) { SUFFIX(f->out, T(p->b_text), S(p->b_text));
|
||||||
|
DELETE(p->b_text); }
|
||||||
|
}
|
||||||
|
S(f->Q) = 0;
|
||||||
|
}
|
||||||
|
} /* ___mkd_emblock */
|
||||||
50
flagprocs.c
Normal file
50
flagprocs.c
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
/* markdown: a C implementation of John Gruber's Markdown markup language.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007-2011 Jessica L Parsons.
|
||||||
|
* The redistribution terms are provided in the COPYRIGHT file that must
|
||||||
|
* be distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include "markdown.h"
|
||||||
|
#include "amalloc.h"
|
||||||
|
|
||||||
|
#if HAVE_LIBGEN_H
|
||||||
|
#include <libgen.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void
|
||||||
|
mkd_set_flag_num(mkd_flag_t *p, unsigned long bit)
|
||||||
|
{
|
||||||
|
if ( p && (bit < MKD_NR_FLAGS) )
|
||||||
|
set_mkd_flag(p, bit);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
mkd_clr_flag_num(mkd_flag_t *p, unsigned long bit)
|
||||||
|
{
|
||||||
|
if ( p && (bit < MKD_NR_FLAGS) )
|
||||||
|
clear_mkd_flag(p, bit);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
mkd_set_flag_bitmap(mkd_flag_t *p, long bits)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if ( p == 0 )
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (i=0; i < 8*sizeof(long) && i < MKD_NR_FLAGS; i++)
|
||||||
|
if ( bits & (1<<i) )
|
||||||
|
set_mkd_flag(p, i);
|
||||||
|
}
|
||||||
137
flags.c
Normal file
137
flags.c
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include "markdown.h"
|
||||||
|
|
||||||
|
struct flagnames {
|
||||||
|
int flag;
|
||||||
|
char *name;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct flagnames flagnames[] = {
|
||||||
|
{ MKD_NOLINKS, "!LINKS" },
|
||||||
|
{ MKD_NOIMAGE, "!IMAGE" },
|
||||||
|
{ MKD_NOPANTS, "!PANTS" },
|
||||||
|
{ MKD_NOHTML, "!HTML" },
|
||||||
|
{ MKD_TAGTEXT, "TAGTEXT" },
|
||||||
|
{ MKD_NO_EXT, "!EXT" },
|
||||||
|
{ MKD_CDATA, "CDATA" },
|
||||||
|
{ MKD_NOSUPERSCRIPT, "!SUPERSCRIPT" },
|
||||||
|
{ MKD_STRICT, "STRICT" },
|
||||||
|
{ MKD_NOTABLES, "!TABLES" },
|
||||||
|
{ MKD_NOSTRIKETHROUGH,"!STRIKETHROUGH" },
|
||||||
|
{ MKD_TOC, "TOC" },
|
||||||
|
{ MKD_1_COMPAT, "MKD_1_COMPAT" },
|
||||||
|
{ MKD_AUTOLINK, "AUTOLINK" },
|
||||||
|
{ MKD_SAFELINK, "SAFELINK" },
|
||||||
|
{ MKD_NOHEADER, "!HEADER" },
|
||||||
|
{ MKD_TABSTOP, "TABSTOP" },
|
||||||
|
{ MKD_NODIVQUOTE, "!DIVQUOTE" },
|
||||||
|
{ MKD_NOALPHALIST, "!ALPHALIST" },
|
||||||
|
{ MKD_EXTRA_FOOTNOTE, "FOOTNOTE" },
|
||||||
|
{ MKD_NOSTYLE, "!STYLE" },
|
||||||
|
{ MKD_DLDISCOUNT, "DLDISCOUNT" },
|
||||||
|
{ MKD_DLEXTRA, "DLEXTRA" },
|
||||||
|
{ MKD_FENCEDCODE, "FENCEDCODE" },
|
||||||
|
{ MKD_IDANCHOR, "IDANCHOR" },
|
||||||
|
{ MKD_GITHUBTAGS, "GITHUBTAGS" },
|
||||||
|
{ MKD_NORMAL_LISTITEM, "NORMAL_LISTITEM" },
|
||||||
|
{ MKD_URLENCODEDANCHOR, "URLENCODEDANCHOR" },
|
||||||
|
{ MKD_LATEX, "LATEX" },
|
||||||
|
{ MKD_EXPLICITLIST, "EXPLICITLIST" },
|
||||||
|
{ MKD_ALT_AS_TITLE, "ALT_AS_TITLE" },
|
||||||
|
{ MKD_EXTENDED_ATTR, "EXTENDED_ATTR" },
|
||||||
|
{ MKD_HTML5, "HTML5" },
|
||||||
|
};
|
||||||
|
#define NR(x) (sizeof x/sizeof x[0])
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
mkd_flag_isset(mkd_flag_t *flags, int i)
|
||||||
|
{
|
||||||
|
return flags ? is_flag_set(flags, i) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
mkd_flags_are(FILE *f, mkd_flag_t* flags, int htmlplease)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int not, set, even=1;
|
||||||
|
char *name;
|
||||||
|
|
||||||
|
if ( htmlplease )
|
||||||
|
fprintf(f, "<table class=\"mkd_flags_are\">\n");
|
||||||
|
for (i=0; i < NR(flagnames); i++) {
|
||||||
|
set = mkd_flag_isset(flags, flagnames[i].flag);
|
||||||
|
name = flagnames[i].name;
|
||||||
|
if ( not = (*name == '!') ) {
|
||||||
|
++name;
|
||||||
|
set = !set;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( htmlplease ) {
|
||||||
|
if ( even ) fprintf(f, " <tr>");
|
||||||
|
fprintf(f, "<td>");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
fputc(' ', f);
|
||||||
|
|
||||||
|
if ( !set )
|
||||||
|
fprintf(f, htmlplease ? "<s>" : "!");
|
||||||
|
|
||||||
|
fprintf(f, "%s", name);
|
||||||
|
|
||||||
|
if ( htmlplease ) {
|
||||||
|
if ( !set )
|
||||||
|
fprintf(f, "</s>");
|
||||||
|
fprintf(f, "</td>");
|
||||||
|
if ( !even ) fprintf(f, "</tr>\n");
|
||||||
|
}
|
||||||
|
even = !even;
|
||||||
|
}
|
||||||
|
if ( htmlplease ) {
|
||||||
|
if ( even ) fprintf(f, "</tr>\n");
|
||||||
|
fprintf(f, "</table>\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
mkd_mmiot_flags(FILE *f, MMIOT *m, int htmlplease)
|
||||||
|
{
|
||||||
|
if ( m )
|
||||||
|
mkd_flags_are(f, &(m->flags), htmlplease);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
mkd_init_flags(mkd_flag_t *p)
|
||||||
|
{
|
||||||
|
memset(p, 0, sizeof(*p));
|
||||||
|
}
|
||||||
|
|
||||||
|
mkd_flag_t *
|
||||||
|
mkd_flags(void)
|
||||||
|
{
|
||||||
|
mkd_flag_t *p = calloc( 1, sizeof(mkd_flag_t) );
|
||||||
|
|
||||||
|
if ( p )
|
||||||
|
mkd_init_flags(p);
|
||||||
|
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
mkd_flag_t *
|
||||||
|
mkd_copy_flags(mkd_flag_t *original)
|
||||||
|
{
|
||||||
|
mkd_flag_t *copy = mkd_flags();
|
||||||
|
|
||||||
|
if ( original && copy )
|
||||||
|
*copy = *original;
|
||||||
|
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
mkd_free_flags(mkd_flag_t *rip)
|
||||||
|
{
|
||||||
|
if (rip) free(rip);
|
||||||
|
}
|
||||||
2164
generate.c
Normal file
2164
generate.c
Normal file
File diff suppressed because it is too large
Load Diff
195
gethopt.3
Normal file
195
gethopt.3
Normal file
@ -0,0 +1,195 @@
|
|||||||
|
.\" Copyright (c) 1988, 1991 Regents of the University of California.
|
||||||
|
.\" Copyright (c) 2017-2024 Jessica Loren Parsons.
|
||||||
|
.\" All rights reserved.
|
||||||
|
.\"
|
||||||
|
.\" Redistribution and use in source and binary forms, with or without
|
||||||
|
.\" modification, are permitted provided that the following conditions
|
||||||
|
.\" are met:
|
||||||
|
.\" 1. Redistributions of source code must retain the above copyright
|
||||||
|
.\" notice, this list of conditions and the following disclaimer.
|
||||||
|
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
.\" notice, this list of conditions and the following disclaimer in the
|
||||||
|
.\" documentation and/or other materials provided with the distribution.
|
||||||
|
.\" 3. All advertising materials mentioning features or use of this software
|
||||||
|
.\" must display the following acknowledgement:
|
||||||
|
.\" This product includes software developed by the University of
|
||||||
|
.\" California, Berkeley and its contributors.
|
||||||
|
.\" 4. Neither the name of the University nor the names of its contributors
|
||||||
|
.\" may be used to endorse or promote products derived from this software
|
||||||
|
.\" without specific prior written permission.
|
||||||
|
.\"
|
||||||
|
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
.\" SUCH DAMAGE.
|
||||||
|
.\"
|
||||||
|
.Dd Jan 23, 2017
|
||||||
|
.Dt GETHOPT 3
|
||||||
|
.Os Mastodon
|
||||||
|
.Sh NAME
|
||||||
|
.Nm gethopt
|
||||||
|
.Nd get option letter or word from argv
|
||||||
|
.Sh SYNOPSIS
|
||||||
|
.Fd #include "gethopt.h"
|
||||||
|
|
||||||
|
.Bd -literal -compact
|
||||||
|
struct h_opt {
|
||||||
|
int option;
|
||||||
|
char *optword;
|
||||||
|
char optchar;
|
||||||
|
int opthasarg;
|
||||||
|
char *optdesc;
|
||||||
|
} ;
|
||||||
|
.Ed
|
||||||
|
.Ft char*
|
||||||
|
.Fn hoptarg "struct h_context* argctx"
|
||||||
|
.Ft int
|
||||||
|
.Fn hoptind "struct h_context* argctx"
|
||||||
|
.Ft int
|
||||||
|
.Fn hopterr "struct h_context* argctx" "int flag"
|
||||||
|
.Ft char
|
||||||
|
.Fn hoptopt "struct h_context* argctx"
|
||||||
|
.Ft void
|
||||||
|
.Fn hoptset "struct h_context* argctx" "int argc" "char** argv"
|
||||||
|
.Ft struct h_opt*
|
||||||
|
.Fn gethopt "struct h_context* argctx" "struct h_opt* optarray" "int nropts"
|
||||||
|
|
||||||
|
.Sh DESCRIPTION
|
||||||
|
The
|
||||||
|
.Fn gethopt
|
||||||
|
function gets
|
||||||
|
the next
|
||||||
|
.Em known
|
||||||
|
option word or character from
|
||||||
|
.Fa argctx .
|
||||||
|
An option is
|
||||||
|
.Em known
|
||||||
|
if it has been specified in the array of accepted options
|
||||||
|
.Fa optarray .
|
||||||
|
.Pp
|
||||||
|
The option array
|
||||||
|
.Fa optarray
|
||||||
|
contains records with either an option word, character, or both,
|
||||||
|
a flag saying the option needs an argument, a short description
|
||||||
|
of the option, and an
|
||||||
|
.Va option
|
||||||
|
key (which is there for the convenience of the calling program;
|
||||||
|
.Fn gethopt
|
||||||
|
does not use it in any way.).
|
||||||
|
It does not matter to
|
||||||
|
.Fn getopt
|
||||||
|
if a following argument has leading white space.
|
||||||
|
.Pp
|
||||||
|
On return from
|
||||||
|
.Fn gethopt ,
|
||||||
|
.Fn hoptarg
|
||||||
|
returns an option argument, if it is anticipated,
|
||||||
|
and the variable
|
||||||
|
.Fn hoptind
|
||||||
|
contains the index to the next
|
||||||
|
.Fa argv
|
||||||
|
argument for a subsequent call
|
||||||
|
to
|
||||||
|
.Fn gethopt .
|
||||||
|
.Pp
|
||||||
|
.Fn
|
||||||
|
gethopt
|
||||||
|
uses a (semi) opaque data blob to hold the current state, which
|
||||||
|
must be initialized by the
|
||||||
|
.Fn hoptset
|
||||||
|
function.
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Fn gethopt
|
||||||
|
function
|
||||||
|
returns
|
||||||
|
.Dv HOPTERR
|
||||||
|
if a non-recognized
|
||||||
|
option is encountered,
|
||||||
|
and NULL when it reaches the end of the options on the command line..
|
||||||
|
.Pp
|
||||||
|
The interpretation of options in the argument list may be cancelled
|
||||||
|
by
|
||||||
|
.Ql -
|
||||||
|
(single dash) or
|
||||||
|
.Ql --
|
||||||
|
(double dash) which causes
|
||||||
|
.Fn getopt
|
||||||
|
to signal the end of argument processing and return an
|
||||||
|
.Dv NULL .
|
||||||
|
When all options have been processed (i.e., up to the first non-option
|
||||||
|
argument),
|
||||||
|
.Fn gethopt
|
||||||
|
returns
|
||||||
|
.Dv NULL .
|
||||||
|
.Sh DIAGNOSTICS
|
||||||
|
If the
|
||||||
|
.Fn gethopt
|
||||||
|
function encounters a character not found in
|
||||||
|
.Va optarray
|
||||||
|
or detects
|
||||||
|
a missing option argument
|
||||||
|
it returns
|
||||||
|
.Dv HOPTERR
|
||||||
|
(and writes an error message to the
|
||||||
|
.Em stderr
|
||||||
|
if
|
||||||
|
.Fn hopterr
|
||||||
|
is used to turn error reporting on.)
|
||||||
|
.Sh EXAMPLE
|
||||||
|
.Bd -literal -compact
|
||||||
|
struct h_opt opts[] = {
|
||||||
|
{ 0, "css", 0, 1, "css file" },
|
||||||
|
{ 1, "header", 0, 1, "header file" },
|
||||||
|
{ 2, 0, 'a', 0, "option a (no arg)" },
|
||||||
|
{ 3, 0, 'b', 1, "option B (with arg)" },
|
||||||
|
{ 4, "help", '?', 0, "help message" },
|
||||||
|
} ;
|
||||||
|
|
||||||
|
#define NROPT (sizeof opts/sizeof opts[0])
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
struct h_opt *ret;
|
||||||
|
struct h_context ctx;
|
||||||
|
|
||||||
|
hoptset(&ctx, argc, argv);
|
||||||
|
hopterr(&ctx, 1);
|
||||||
|
|
||||||
|
while (( ret = gethopt(&ctx, opts, NROPT) )) {
|
||||||
|
|
||||||
|
if ( ret != HOPTERR ) {
|
||||||
|
if ( ret->optword )
|
||||||
|
printf("%s", ret->optword);
|
||||||
|
else
|
||||||
|
printf("%c", ret->optchar);
|
||||||
|
|
||||||
|
if ( ret->opthasarg ) {
|
||||||
|
if ( hoptarg(&ctx) )
|
||||||
|
printf(" = %s", hoptarg(&ctx));
|
||||||
|
else
|
||||||
|
printf(" with no argument?");
|
||||||
|
}
|
||||||
|
puts(ret->optdesc ? ret->optdesc : "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
argc -= hoptind(&ctx);
|
||||||
|
argv += hoptind(&ctx);
|
||||||
|
|
||||||
|
.Ed
|
||||||
|
.Sh HISTORY
|
||||||
|
The
|
||||||
|
.Fn gethopt
|
||||||
|
function was a quick hack to replace manually parsing full-word arguments
|
||||||
|
in
|
||||||
|
.Va discount .
|
||||||
347
gethopt.c
Normal file
347
gethopt.c
Normal file
@ -0,0 +1,347 @@
|
|||||||
|
/*
|
||||||
|
* gehopt; options processing with both single-character and whole-word
|
||||||
|
* options both introduced with -
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "gethopt.h"
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
hoptset(struct h_context *ctx, int argc, char **argv)
|
||||||
|
{
|
||||||
|
memset(ctx, 0, sizeof *ctx);
|
||||||
|
ctx->argc = argc;
|
||||||
|
ctx->argv = argv;
|
||||||
|
ctx->optind = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char *
|
||||||
|
hoptarg(struct h_context *ctx)
|
||||||
|
{
|
||||||
|
return ctx->optarg;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
hoptind(struct h_context *ctx)
|
||||||
|
{
|
||||||
|
return ctx->optind;
|
||||||
|
}
|
||||||
|
|
||||||
|
char
|
||||||
|
hoptopt(struct h_context *ctx)
|
||||||
|
{
|
||||||
|
return ctx->optopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
hopterr(struct h_context *ctx, int val)
|
||||||
|
{
|
||||||
|
int old = ctx->opterr;
|
||||||
|
|
||||||
|
ctx->opterr = !!val;
|
||||||
|
return old;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct h_opt *
|
||||||
|
gethopt(struct h_context *ctx, struct h_opt *opts, int nropts)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int dashes;
|
||||||
|
|
||||||
|
|
||||||
|
if ( (ctx == 0) || ctx->optend || (ctx->optind >= ctx->argc) )
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
ctx->optarg = 0;
|
||||||
|
ctx->optopt = 0;
|
||||||
|
|
||||||
|
if ( ctx->optchar == 0) {
|
||||||
|
/* check for leading -
|
||||||
|
*/
|
||||||
|
if ( ctx->argv[ctx->optind][0] != '-' ) {
|
||||||
|
/* out of arguments */
|
||||||
|
ctx->optend = 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ctx->argv[ctx->optind][1] == 0
|
||||||
|
|| strcmp(ctx->argv[ctx->optind], "--") == 0 ) {
|
||||||
|
/* option list finishes with - or -- token
|
||||||
|
*/
|
||||||
|
ctx->optend = 1;
|
||||||
|
ctx->optind++;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
dashes = 1;
|
||||||
|
if ( ctx->argv[ctx->optind][dashes] == '-' ) {
|
||||||
|
/* support GNU-style long option double-dash prefix
|
||||||
|
* (if gethopt is passed an unknown option with a double-dash
|
||||||
|
* prefix, it won't match a word and then the second dash
|
||||||
|
* will be scanned as if it was a regular old single-character
|
||||||
|
* option.)
|
||||||
|
*/
|
||||||
|
dashes = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( i=0; i < nropts; i++ ) {
|
||||||
|
if ( ! opts[i].optword )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (strcmp(opts[i].optword, dashes+(ctx->argv[ctx->optind]) ) == 0 ) {
|
||||||
|
if ( opts[i].opthasarg ) {
|
||||||
|
if ( ctx->argc > ctx->optind ) {
|
||||||
|
ctx->optarg = ctx->argv[ctx->optind+1];
|
||||||
|
ctx->optind += 2;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* word argument with required arg at end of
|
||||||
|
*command line
|
||||||
|
*/
|
||||||
|
if ( ctx->opterr )
|
||||||
|
fprintf(stderr,
|
||||||
|
"%s: option requires an argument -- %s\n",
|
||||||
|
ctx->argv[0], opts[i].optword);
|
||||||
|
ctx->optind ++;
|
||||||
|
return HOPTERR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ctx->optind ++;
|
||||||
|
}
|
||||||
|
return &opts[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ctx->optchar = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->optopt = ctx->argv[ctx->optind][ctx->optchar++];
|
||||||
|
|
||||||
|
if ( !ctx->optopt ) {
|
||||||
|
/* fell off the end of this argument */
|
||||||
|
ctx->optind ++;
|
||||||
|
ctx->optchar = 0;
|
||||||
|
return gethopt(ctx, opts, nropts);
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( i=0; i<nropts; i++ ) {
|
||||||
|
if ( opts[i].optchar == ctx->optopt ) {
|
||||||
|
/* found a single-char option!
|
||||||
|
*/
|
||||||
|
if ( opts[i].opthasarg ) {
|
||||||
|
if ( ctx->argv[ctx->optind][ctx->optchar] ) {
|
||||||
|
/* argument immediately follows this options (-Oc)
|
||||||
|
*/
|
||||||
|
ctx->optarg = &ctx->argv[ctx->optind][ctx->optchar];
|
||||||
|
ctx->optind ++;
|
||||||
|
ctx->optchar = 0;
|
||||||
|
}
|
||||||
|
else if ( ctx->optind < ctx->argc-1 ) {
|
||||||
|
/* argument is next arg (-O c)
|
||||||
|
*/
|
||||||
|
ctx->optarg = &ctx->argv[ctx->optind+1][0];
|
||||||
|
ctx->optind += 2;
|
||||||
|
ctx->optchar = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* end of arg string (-O); set optarg to null, return
|
||||||
|
* (should it opterr on me?)
|
||||||
|
*/
|
||||||
|
ctx->optarg = 0;
|
||||||
|
ctx->optind ++;
|
||||||
|
ctx->optchar = 0;
|
||||||
|
if ( ctx->opterr )
|
||||||
|
fprintf(stderr,
|
||||||
|
"%s: option requires an argument -- %c\n",
|
||||||
|
ctx->argv[0], opts[i].optchar);
|
||||||
|
return HOPTERR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if ( !ctx->argv[ctx->optind][ctx->optchar] ) {
|
||||||
|
ctx->optind ++;
|
||||||
|
ctx->optchar = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return &opts[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( ctx->opterr )
|
||||||
|
fprintf(stderr, "%s: illegal option -- %c\n", ctx->argv[0], ctx->optopt);
|
||||||
|
return HOPTERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
hoptdescribe(char *pgm, struct h_opt opts[], int nropts, char *arguments, int verbose)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int sz;
|
||||||
|
|
||||||
|
if ( verbose ) {
|
||||||
|
fprintf(stderr, "usage: %s", pgm);
|
||||||
|
if ( nropts > 0 )
|
||||||
|
fprintf(stderr, " [options]");
|
||||||
|
if ( arguments )
|
||||||
|
fprintf(stderr, " %s", arguments);
|
||||||
|
fputc('\n', stderr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
fprintf(stderr, "usage: %s", pgm);
|
||||||
|
|
||||||
|
/* print out the options that don't have flags first */
|
||||||
|
|
||||||
|
if ( verbose ) {
|
||||||
|
int maxoptwidth = 0;
|
||||||
|
int maxargwidth = 0;
|
||||||
|
int hasoptchar = 0;
|
||||||
|
int j;
|
||||||
|
|
||||||
|
if ( nropts > 0 )
|
||||||
|
fprintf(stderr, "options:\n");
|
||||||
|
|
||||||
|
/* find column widths */
|
||||||
|
for ( i=0; i < nropts; i++ ) {
|
||||||
|
if ( opts[i].optword && (( sz = strlen(opts[i].optword) ) > maxoptwidth ) )
|
||||||
|
maxoptwidth = sz;
|
||||||
|
if ( opts[i].opthasarg && (( sz = strlen(opts[i].opthasarg) ) > maxargwidth ) )
|
||||||
|
maxargwidth = sz;
|
||||||
|
if ( opts[i].optchar )
|
||||||
|
hasoptchar = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( i=0; i < nropts; i++ ) {
|
||||||
|
if ( opts[i].optword ) {
|
||||||
|
fprintf(stderr, " -%s", opts[i].optword);
|
||||||
|
j = strlen(opts[i].optword);
|
||||||
|
}
|
||||||
|
else j = -2;
|
||||||
|
|
||||||
|
while ( j++ < maxoptwidth )
|
||||||
|
fputc(' ', stderr);
|
||||||
|
|
||||||
|
if ( opts[i].optchar )
|
||||||
|
fprintf(stderr, " -%c ", opts[i].optchar);
|
||||||
|
else if ( hasoptchar )
|
||||||
|
fprintf(stderr, " ");
|
||||||
|
|
||||||
|
if ( maxargwidth > 0 ) {
|
||||||
|
if ( opts[i].opthasarg ) {
|
||||||
|
fprintf(stderr, " [%s]", opts[i].opthasarg);
|
||||||
|
j = strlen(opts[i].opthasarg);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
fprintf(stderr, " ");
|
||||||
|
j = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ( j++ < maxargwidth )
|
||||||
|
fputc(' ', stderr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( opts[i].optdesc )
|
||||||
|
fprintf(stderr, " %s", opts[i].optdesc);
|
||||||
|
|
||||||
|
fputc('\n', stderr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
int optcount;
|
||||||
|
|
||||||
|
for ( optcount=i=0; i < nropts; i++ ) {
|
||||||
|
if ( opts[i].optchar && !opts[i].opthasarg) {
|
||||||
|
if (optcount == 0 )
|
||||||
|
fputs(" [-", stderr);
|
||||||
|
fputc(opts[i].optchar, stderr);
|
||||||
|
optcount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( optcount )
|
||||||
|
fputc(']', stderr);
|
||||||
|
|
||||||
|
/* print out the options WITH flags */
|
||||||
|
for ( i = 0; i < nropts; i++ )
|
||||||
|
if ( opts[i].optchar && opts[i].opthasarg)
|
||||||
|
fprintf(stderr, " [-%c %s]", opts[i].optchar, opts[i].opthasarg);
|
||||||
|
|
||||||
|
/* print out the long options */
|
||||||
|
for ( i = 0; i < nropts; i++ )
|
||||||
|
if ( opts[i].optword ) {
|
||||||
|
fprintf(stderr, " [-%s", opts[i].optword);
|
||||||
|
if ( opts[i].opthasarg )
|
||||||
|
fprintf(stderr, " %s", opts[i].opthasarg);
|
||||||
|
fputc(']', stderr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( arguments )
|
||||||
|
fprintf(stderr, " %s", arguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* and we're done */
|
||||||
|
fputc('\n', stderr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
hoptusage(char *pgm, struct h_opt opts[], int nropts, char *arguments)
|
||||||
|
{
|
||||||
|
hoptdescribe(pgm, opts, nropts, arguments, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
struct h_opt opts[] = {
|
||||||
|
{ 0, "css", 0, 1, "css file" },
|
||||||
|
{ 1, "header", 0, 1, "header file" },
|
||||||
|
{ 2, 0, 'a', 0, "option a (no arg)" },
|
||||||
|
{ 3, 0, 'b', 1, "option B (with arg)" },
|
||||||
|
{ 4, "help", '?', 0, "help message" },
|
||||||
|
} ;
|
||||||
|
|
||||||
|
#define NROPT (sizeof opts/sizeof opts[0])
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
struct h_opt *ret;
|
||||||
|
struct h_context ctx;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
|
||||||
|
hoptset(&ctx, argc, argv);
|
||||||
|
hopterr(&ctx, 1);
|
||||||
|
|
||||||
|
while (( ret = gethopt(&ctx, opts, NROPT) )) {
|
||||||
|
|
||||||
|
if ( ret != HOPTERR ) {
|
||||||
|
if ( ret->optword )
|
||||||
|
printf("%s", ret->optword);
|
||||||
|
else
|
||||||
|
printf("%c", ret->optchar);
|
||||||
|
|
||||||
|
if ( ret->opthasarg ) {
|
||||||
|
if ( hoptarg(&ctx) )
|
||||||
|
printf(" with argument \"%s\"", hoptarg(&ctx));
|
||||||
|
else
|
||||||
|
printf(" with no argument?");
|
||||||
|
}
|
||||||
|
printf(" (%s)\n", ret->optdesc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
argc -= hoptind(&ctx);
|
||||||
|
argv += hoptind(&ctx);
|
||||||
|
|
||||||
|
for ( i=0; i < argc; i++ )
|
||||||
|
printf("%d: %s\n", i, argv[i]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /*DEBUG*/
|
||||||
44
gethopt.h
Normal file
44
gethopt.h
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* gethopt; options processing with both single-character and whole-work
|
||||||
|
* options both introduced with -
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __GETHOPT_D
|
||||||
|
#define __GETHOPT_D
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
|
struct h_opt {
|
||||||
|
int option;
|
||||||
|
char *optword;
|
||||||
|
char optchar;
|
||||||
|
char *opthasarg;
|
||||||
|
char *optdesc;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
#define HOPTERR ((struct h_opt*)-1)
|
||||||
|
|
||||||
|
struct h_context {
|
||||||
|
char **argv;
|
||||||
|
int argc;
|
||||||
|
int optchar;
|
||||||
|
int optind;
|
||||||
|
char *optarg;
|
||||||
|
char optopt;
|
||||||
|
int opterr:1;
|
||||||
|
int optend:1;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
extern char *hoptarg(struct h_context *);
|
||||||
|
extern int hoptind(struct h_context *);
|
||||||
|
extern char hoptopt(struct h_context *);
|
||||||
|
extern void hoptset(struct h_context *, int, char **);
|
||||||
|
extern int hopterr(struct h_context *, int);
|
||||||
|
extern struct h_opt *gethopt(struct h_context *, struct h_opt*, int);
|
||||||
|
|
||||||
|
extern void hoptusage(char *, struct h_opt*, int, char *);
|
||||||
|
extern void hoptdescribe(char *, struct h_opt*, int, char *, int);
|
||||||
|
|
||||||
|
#endif/*__GETHOPT_D*/
|
||||||
103
github_flavoured.c
Normal file
103
github_flavoured.c
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
|
||||||
|
/*
|
||||||
|
* github_flavoured -- implement the obnoxious "returns are hard newlines"
|
||||||
|
* feature in github flavoured markdown.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012 Jessica L Parsons.
|
||||||
|
* The redistribution terms are provided in the COPYRIGHT file that must
|
||||||
|
* be distributed with this source code.
|
||||||
|
*/
|
||||||
|
#include "config.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
#include "cstring.h"
|
||||||
|
#include "markdown.h"
|
||||||
|
#include "amalloc.h"
|
||||||
|
|
||||||
|
/* build a Document from any old input.
|
||||||
|
*/
|
||||||
|
typedef int (*getc_func)(void*);
|
||||||
|
|
||||||
|
Document *
|
||||||
|
gfm_populate(getc_func getc, void* ctx, mkd_flag_t *flags)
|
||||||
|
{
|
||||||
|
Cstring line;
|
||||||
|
Document *a = __mkd_new_Document();
|
||||||
|
int c;
|
||||||
|
int pandoc = 0;
|
||||||
|
|
||||||
|
if ( !a ) return 0;
|
||||||
|
|
||||||
|
if ( is_flag_set(flags, MKD_TABSTOP) || is_flag_set(flags, MKD_STRICT) )
|
||||||
|
a->tabstop = 4;
|
||||||
|
else
|
||||||
|
a->tabstop = TABSTOP;
|
||||||
|
|
||||||
|
CREATE(line);
|
||||||
|
|
||||||
|
while ( (c = (*getc)(ctx)) != EOF ) {
|
||||||
|
if ( c == '\n' ) {
|
||||||
|
if ( pandoc != EOF && pandoc < 3 ) {
|
||||||
|
if ( S(line) && (T(line)[0] == '%') )
|
||||||
|
pandoc++;
|
||||||
|
else
|
||||||
|
pandoc = EOF;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pandoc == EOF) {
|
||||||
|
EXPAND(line) = ' ';
|
||||||
|
EXPAND(line) = ' ';
|
||||||
|
}
|
||||||
|
__mkd_enqueue(a, &line);
|
||||||
|
S(line) = 0;
|
||||||
|
}
|
||||||
|
else if ( isprint(c) || isspace(c) || (c & 0x80) )
|
||||||
|
EXPAND(line) = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( S(line) )
|
||||||
|
__mkd_enqueue(a, &line);
|
||||||
|
|
||||||
|
DELETE(line);
|
||||||
|
|
||||||
|
if ( (pandoc == 3) && !is_flag_set(flags, MKD_NOHEADER) ) {
|
||||||
|
/* the first three lines started with %, so we have a header.
|
||||||
|
* clip the first three lines out of content and hang them
|
||||||
|
* off header.
|
||||||
|
*/
|
||||||
|
Line *headers = T(a->content);
|
||||||
|
|
||||||
|
a->title = headers; __mkd_trim_line(a->title, 1);
|
||||||
|
a->author= headers->next; __mkd_trim_line(a->author, 1);
|
||||||
|
a->date = headers->next->next; __mkd_trim_line(a->date, 1);
|
||||||
|
|
||||||
|
T(a->content) = headers->next->next->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* convert a block of text into a linked list
|
||||||
|
*/
|
||||||
|
Document *
|
||||||
|
gfm_string(const char *buf, int len, mkd_flag_t* flags)
|
||||||
|
{
|
||||||
|
struct string_stream about;
|
||||||
|
|
||||||
|
about.data = buf;
|
||||||
|
about.size = len;
|
||||||
|
|
||||||
|
return gfm_populate((getc_func)__mkd_io_strget, &about, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* convert a file into a linked list
|
||||||
|
*/
|
||||||
|
Document *
|
||||||
|
gfm_in(FILE *f, mkd_flag_t* flags)
|
||||||
|
{
|
||||||
|
return gfm_populate((getc_func)fgetc, f, flags);
|
||||||
|
}
|
||||||
38
h1title.c
Normal file
38
h1title.c
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include "markdown.h"
|
||||||
|
|
||||||
|
static Paragraph *
|
||||||
|
mkd_h1(Paragraph *p)
|
||||||
|
{
|
||||||
|
Paragraph *found;
|
||||||
|
|
||||||
|
while ( p ) {
|
||||||
|
if ( p->typ == HDR && p->hnumber == 1 )
|
||||||
|
return p;
|
||||||
|
if ( p->down && (found = mkd_h1(p->down)) )
|
||||||
|
return found;
|
||||||
|
p = p->next;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
mkd_h1_title(Document *doc)
|
||||||
|
{
|
||||||
|
Paragraph *title;
|
||||||
|
|
||||||
|
if (doc && (title = mkd_h1(doc->code)) ) {
|
||||||
|
char *generated;
|
||||||
|
int size;
|
||||||
|
|
||||||
|
/* assert that a H1 header is one line long, so that's
|
||||||
|
* the only thing needed
|
||||||
|
*/
|
||||||
|
set_mkd_flag(&(doc->ctx->flags), MKD_TAGTEXT);
|
||||||
|
size = mkd_line(T(title->text->text),
|
||||||
|
S(title->text->text), &generated, &(doc->ctx->flags));
|
||||||
|
clear_mkd_flag(&(doc->ctx->flags), MKD_TAGTEXT);
|
||||||
|
if ( size ) return generated;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
16
html5.c
Normal file
16
html5.c
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
/* block-level tags for passing html5 blocks through the blender
|
||||||
|
*/
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "markdown.h"
|
||||||
|
#include "tags.h"
|
||||||
|
|
||||||
|
void
|
||||||
|
mkd_add_html5_tags(MMIOT* doc)
|
||||||
|
{
|
||||||
|
mkd_define_tag(doc, "ASIDE", 0);
|
||||||
|
mkd_define_tag(doc, "FOOTER", 0);
|
||||||
|
mkd_define_tag(doc, "HEADER", 0);
|
||||||
|
mkd_define_tag(doc, "NAV", 0);
|
||||||
|
mkd_define_tag(doc, "SECTION", 0);
|
||||||
|
mkd_define_tag(doc, "ARTICLE", 0);
|
||||||
|
}
|
||||||
11
libmarkdown.pc.in
Normal file
11
libmarkdown.pc.in
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
prefix=@prefix@
|
||||||
|
exec_prefix=@prefix@
|
||||||
|
libdir=@libdir@
|
||||||
|
includedir=@prefix@/include
|
||||||
|
|
||||||
|
Name: @PACKAGE_NAME@
|
||||||
|
Version: @PACKAGE_VERSION@
|
||||||
|
Description: C implementation of John Gruber's Markdown markup language
|
||||||
|
|
||||||
|
Libs: -L${libdir} -lmarkdown @LIBS@
|
||||||
|
Cflags: -I${includedir}
|
||||||
378
main.c
Normal file
378
main.c
Normal file
@ -0,0 +1,378 @@
|
|||||||
|
/*
|
||||||
|
* markdown: convert a single markdown document into html
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2007 Jessica L Parsons.
|
||||||
|
* The redistribution terms are provided in the COPYRIGHT file that must
|
||||||
|
* be distributed with this source code.
|
||||||
|
*/
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <mkdio.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include "amalloc.h"
|
||||||
|
#include "pgm_options.h"
|
||||||
|
#include "tags.h"
|
||||||
|
#include "gethopt.h"
|
||||||
|
|
||||||
|
#if HAVE_LIBGEN_H
|
||||||
|
#include <libgen.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef HAVE_BASENAME
|
||||||
|
char*
|
||||||
|
basename(char *p)
|
||||||
|
{
|
||||||
|
char *ret = strrchr(p, '/');
|
||||||
|
|
||||||
|
return ret ? (1+ret) : p;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
char *pgm = "markdown";
|
||||||
|
|
||||||
|
char *
|
||||||
|
e_flags(const char *text, const int size, void *context)
|
||||||
|
{
|
||||||
|
return (char*)context;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
complain(char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list ptr;
|
||||||
|
|
||||||
|
fprintf(stderr, "%s: ", pgm);
|
||||||
|
va_start(ptr, fmt);
|
||||||
|
vfprintf(stderr, fmt, ptr);
|
||||||
|
va_end(ptr);
|
||||||
|
fputc('\n', stderr);
|
||||||
|
fflush(stderr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
callback_free(char *input, int size, void *ctx)
|
||||||
|
{
|
||||||
|
if (input)
|
||||||
|
free(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char *
|
||||||
|
anchor_format(char *input, void *ctx)
|
||||||
|
{
|
||||||
|
int i, j, size;
|
||||||
|
char* ret;
|
||||||
|
|
||||||
|
if ( !input )
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
size = strlen(input);
|
||||||
|
|
||||||
|
ret = malloc(1+size);
|
||||||
|
|
||||||
|
if ( !ret )
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
|
||||||
|
while ( size && isspace(input[size-1]) )
|
||||||
|
--size;
|
||||||
|
|
||||||
|
for ( j=i=0; i < size; i++ ) {
|
||||||
|
if (isalnum(input[i]) || strchr("-_+", input[i]) )
|
||||||
|
ret[j++] = input[i];
|
||||||
|
else if ( input[i] == ' ' )
|
||||||
|
ret[j++] = '-';
|
||||||
|
}
|
||||||
|
ret[j++] = 0;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *external_formatter = 0;
|
||||||
|
|
||||||
|
|
||||||
|
#define RECEIVER 0
|
||||||
|
#define SENDER 1
|
||||||
|
|
||||||
|
char *
|
||||||
|
external_codefmt(char *src, int len, char *lang)
|
||||||
|
{
|
||||||
|
int child_status;
|
||||||
|
int size, bufsize, curr;
|
||||||
|
char *res;
|
||||||
|
|
||||||
|
pid_t child;
|
||||||
|
|
||||||
|
int tochild[2], toparent[2];
|
||||||
|
|
||||||
|
if ( pipe(tochild) != 0 || pipe(toparent) != 0 ) {
|
||||||
|
perror("external_codefmt (pipe)");
|
||||||
|
res = malloc(len+1);
|
||||||
|
strcpy(res, src);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( (child = fork()) > 0 ) {
|
||||||
|
|
||||||
|
close(tochild[RECEIVER]);
|
||||||
|
close(toparent[SENDER]);
|
||||||
|
|
||||||
|
bufsize = 1000;
|
||||||
|
res = malloc(1+bufsize);
|
||||||
|
curr = 0;
|
||||||
|
|
||||||
|
/* parent */
|
||||||
|
write(tochild[SENDER], src, len);
|
||||||
|
close(tochild[SENDER]);
|
||||||
|
|
||||||
|
while ( (size = read(toparent[RECEIVER], res+curr, 1000)) > 0 ) {
|
||||||
|
curr += size;
|
||||||
|
res = realloc(res, bufsize += 1000);
|
||||||
|
}
|
||||||
|
res[curr] = 0;
|
||||||
|
waitpid(child, &child_status, 0);
|
||||||
|
|
||||||
|
close(toparent[RECEIVER]);
|
||||||
|
|
||||||
|
if ( WIFEXITED(child_status) )
|
||||||
|
return res;
|
||||||
|
else
|
||||||
|
free(res); /* something failed; just return the original string */
|
||||||
|
}
|
||||||
|
else if ( child == 0 ) {
|
||||||
|
close(tochild[SENDER]);
|
||||||
|
close(toparent[RECEIVER]);
|
||||||
|
close(1); dup2(toparent[SENDER], 1);
|
||||||
|
close(0); dup2(tochild[RECEIVER], 0);
|
||||||
|
system(external_formatter);
|
||||||
|
close(0); close(tochild[RECEIVER]);
|
||||||
|
close(1); close(toparent[SENDER]);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
res = malloc(len+1);
|
||||||
|
strcpy(res, src);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct h_opt opts[] = {
|
||||||
|
{ 0, "html5", '5', 0, "recognise html5 block elements" },
|
||||||
|
{ 0, "base", 'b', "url-base", "URL prefix" },
|
||||||
|
{ 0, "debug", 'd', 0, "debugging" },
|
||||||
|
{ 0, "version",'V', 0, "show version info" },
|
||||||
|
{ 0, 0, 'E', "flags", "url flags" },
|
||||||
|
{ 0, 0, 'F', "bitmap", "set/show hex flags" },
|
||||||
|
{ 0, 0, 'f', "{+-}flags", "set/show named flags" },
|
||||||
|
{ 0, 0, 'G', 0, "github flavoured markdown" },
|
||||||
|
{ 0, 0, 'n', 0, "don't write generated html" },
|
||||||
|
{ 0, 0, 's', "text", "format `text`" },
|
||||||
|
{ 0, "style", 'S', 0, "output <style> blocks" },
|
||||||
|
{ 0, 0, 't', "text", "format `text` with mkd_line()" },
|
||||||
|
{ 0, "toc", 'T', 0, "output a TOC" },
|
||||||
|
{ 0, 0, 'C', "prefix", "prefix for markdown extra footnotes" },
|
||||||
|
{ 0, 0, 'o', "file", "write output to file" },
|
||||||
|
{ 0, "squash", 'x', 0, "squash toc labels to be more like github" },
|
||||||
|
{ 0, "codefmt",'X', "command", "use an external code formatter" },
|
||||||
|
{ 0, "help", '?', 0, "print a detailed usage message" },
|
||||||
|
};
|
||||||
|
#define NROPTS (sizeof opts/sizeof opts[0])
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
int debug = 0;
|
||||||
|
int toc = 0;
|
||||||
|
int content = 1;
|
||||||
|
int version = 0;
|
||||||
|
int styles = 0;
|
||||||
|
int use_mkd_line = 0;
|
||||||
|
int use_e_codefmt = 0;
|
||||||
|
int github_flavoured = 0;
|
||||||
|
int squash = 0;
|
||||||
|
char *extra_footnote_prefix = 0;
|
||||||
|
char *urlflags = 0;
|
||||||
|
char *text = 0;
|
||||||
|
char *ofile = 0;
|
||||||
|
char *urlbase = 0;
|
||||||
|
char *q;
|
||||||
|
MMIOT *doc;
|
||||||
|
struct h_context blob;
|
||||||
|
struct h_opt *opt;
|
||||||
|
mkd_flag_t *flags = mkd_flags();
|
||||||
|
|
||||||
|
if ( !flags )
|
||||||
|
perror("new_flags");
|
||||||
|
|
||||||
|
hoptset(&blob, argc, argv);
|
||||||
|
hopterr(&blob, 1);
|
||||||
|
|
||||||
|
pgm = basename(argv[0]);
|
||||||
|
|
||||||
|
if ( q = getenv("MARKDOWN_FLAGS") )
|
||||||
|
mkd_set_flag_bitmap(flags, strtol(q,0,0));
|
||||||
|
|
||||||
|
while ( opt=gethopt(&blob, opts, NROPTS) ) {
|
||||||
|
if ( opt == HOPTERR ) {
|
||||||
|
hoptusage(pgm, opts, NROPTS, "[file]");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
switch (opt->optchar) {
|
||||||
|
case '5': mkd_set_flag_num(flags, MKD_HTML5);
|
||||||
|
break;
|
||||||
|
case 'b': urlbase = hoptarg(&blob);
|
||||||
|
break;
|
||||||
|
case 'd': debug++;
|
||||||
|
break;
|
||||||
|
case 'V': version++;
|
||||||
|
break;
|
||||||
|
case 'E': urlflags = hoptarg(&blob);
|
||||||
|
break;
|
||||||
|
case 'f': q = hoptarg(&blob);
|
||||||
|
if ( strcmp(q, "?") == 0 ) {
|
||||||
|
show_flags(1, version, 0);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
else if ( strcmp(q, "??") == 0 ) {
|
||||||
|
show_flags(1, version, flags);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
else if ( q=mkd_set_flag_string(flags, hoptarg(&blob)) )
|
||||||
|
complain("unknown option <%s>", q);
|
||||||
|
break;
|
||||||
|
case 'F': q = hoptarg(&blob);
|
||||||
|
if ( strcmp(q, "?") == 0 ) {
|
||||||
|
show_flags(0, 0, 0);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
else if ( strcmp(q, "??") == 0 ) {
|
||||||
|
show_flags(0, version, flags);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
mkd_set_flag_bitmap(flags,strtol(q, 0, 0));
|
||||||
|
break;
|
||||||
|
case 'G': github_flavoured = 1;
|
||||||
|
break;
|
||||||
|
case 'n': content = 0;
|
||||||
|
break;
|
||||||
|
case 's': text = hoptarg(&blob);
|
||||||
|
break;
|
||||||
|
case 'S': styles = 1;
|
||||||
|
break;
|
||||||
|
case 't': text = hoptarg(&blob);
|
||||||
|
use_mkd_line = 1;
|
||||||
|
break;
|
||||||
|
case 'T': mkd_set_flag_num(flags, MKD_TOC);
|
||||||
|
toc = 1;
|
||||||
|
break;
|
||||||
|
case 'C': extra_footnote_prefix = hoptarg(&blob);
|
||||||
|
break;
|
||||||
|
case 'o': if ( ofile ) {
|
||||||
|
complain("Too many -o options");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if ( !freopen(ofile = hoptarg(&blob), "w", stdout) ) {
|
||||||
|
perror(ofile);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'x': squash = 1;
|
||||||
|
break;
|
||||||
|
case 'X': use_e_codefmt = 1;
|
||||||
|
mkd_set_flag_num(flags, MKD_FENCEDCODE);
|
||||||
|
external_formatter = hoptarg(&blob);
|
||||||
|
fprintf(stderr, "selected external formatter (%s)\n", external_formatter);
|
||||||
|
break;
|
||||||
|
case '?': hoptdescribe(pgm, opts, NROPTS, "[file]", 1);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if ( version ) {
|
||||||
|
printf("%s: discount %s", pgm, markdown_version);
|
||||||
|
if ( version == 2 )
|
||||||
|
mkd_flags_are(stdout, flags, 0);
|
||||||
|
putchar('\n');
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
argc -= hoptind(&blob);
|
||||||
|
argv += hoptind(&blob);
|
||||||
|
|
||||||
|
if ( use_mkd_line )
|
||||||
|
rc = mkd_generateline( text, strlen(text), stdout, flags);
|
||||||
|
else {
|
||||||
|
if ( text ) {
|
||||||
|
doc = github_flavoured ? gfm_string(text, strlen(text), flags)
|
||||||
|
: mkd_string(text, strlen(text), flags) ;
|
||||||
|
|
||||||
|
if ( !doc ) {
|
||||||
|
perror(text);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if ( argc && !freopen(argv[0], "r", stdin) ) {
|
||||||
|
perror(argv[0]);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
doc = github_flavoured ? gfm_in(stdin,flags)
|
||||||
|
: mkd_in(stdin,flags);
|
||||||
|
if ( !doc ) {
|
||||||
|
perror(argc ? argv[0] : "stdin");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( urlbase )
|
||||||
|
mkd_basename(doc, urlbase);
|
||||||
|
|
||||||
|
if ( urlflags )
|
||||||
|
mkd_e_flags(doc, e_flags, NULL, urlflags);
|
||||||
|
|
||||||
|
if ( squash )
|
||||||
|
mkd_e_anchor(doc, (mkd_callback_t) anchor_format, callback_free, 0);
|
||||||
|
|
||||||
|
if ( use_e_codefmt )
|
||||||
|
mkd_e_code_format(doc, (mkd_callback_t)external_codefmt, callback_free, 0);
|
||||||
|
|
||||||
|
|
||||||
|
if ( extra_footnote_prefix )
|
||||||
|
mkd_ref_prefix(doc, extra_footnote_prefix);
|
||||||
|
|
||||||
|
if ( debug ) {
|
||||||
|
rc = mkd_dump(doc, stdout, flags, argc ? basename(argv[0]) : "stdin");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
rc = 1;
|
||||||
|
if ( mkd_compile(doc, flags) ) {
|
||||||
|
rc = 0;
|
||||||
|
if ( styles )
|
||||||
|
mkd_generatecss(doc, stdout);
|
||||||
|
if ( toc )
|
||||||
|
mkd_generatetoc(doc, stdout);
|
||||||
|
if ( content )
|
||||||
|
mkd_generatehtml(doc, stdout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mkd_cleanup(doc);
|
||||||
|
}
|
||||||
|
mkd_free_flags(flags);
|
||||||
|
adump();
|
||||||
|
exit( (rc == 0) ? 0 : errno );
|
||||||
|
}
|
||||||
45
makepage.1
Normal file
45
makepage.1
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
.\" %A%
|
||||||
|
.\"
|
||||||
|
.Dd January 10, 2010
|
||||||
|
.Dt MAKEPAGE 1
|
||||||
|
.Os MASTODON
|
||||||
|
.Sh NAME
|
||||||
|
.Nm makepage
|
||||||
|
.Nd convert markdown input to a fully-formed xhtml page
|
||||||
|
.Sh SYNOPSIS
|
||||||
|
.Nm
|
||||||
|
.Op Fl V
|
||||||
|
.Op Fl F Pa bitmap
|
||||||
|
.Op Fl f Ar flags
|
||||||
|
.Op Pa file
|
||||||
|
.Sh DESCRIPTION
|
||||||
|
The
|
||||||
|
.Nm
|
||||||
|
utility parses a
|
||||||
|
.Xr markdown 7 Ns -formatted
|
||||||
|
.Pa textfile
|
||||||
|
.Pq or stdin if not specified,
|
||||||
|
compiles it, then prints a fully-formed xhtml page to stdout.
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Fl F ,
|
||||||
|
.Fl f ,
|
||||||
|
and
|
||||||
|
.Fl V
|
||||||
|
flags are identical to the same options in
|
||||||
|
.Xr markdown 1 .
|
||||||
|
.Pp
|
||||||
|
.Nm
|
||||||
|
is part of discount.
|
||||||
|
.Sh RETURN VALUES
|
||||||
|
The
|
||||||
|
.Nm
|
||||||
|
utility exits 0 on success, and >0 if an error occurs.
|
||||||
|
.Sh SEE ALSO
|
||||||
|
.Xr markdown 1 ,
|
||||||
|
.Xr markdown 3 ,
|
||||||
|
.Xr markdown 7 ,
|
||||||
|
.Xr mkd-extensions 7 .
|
||||||
|
.Sh AUTHOR
|
||||||
|
.An Jessica L. Parsons
|
||||||
|
.Pq Li orc@pell.portland.or.us
|
||||||
116
makepage.c
Normal file
116
makepage.c
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
/*
|
||||||
|
* makepage: Use mkd_xhtmlpage() to convert markdown input to a
|
||||||
|
* fully-formed xhtml page.
|
||||||
|
*/
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <mkdio.h>
|
||||||
|
#include "config.h"
|
||||||
|
#include "pgm_options.h"
|
||||||
|
#include "gethopt.h"
|
||||||
|
|
||||||
|
#ifndef HAVE_BASENAME
|
||||||
|
char*
|
||||||
|
basename(char *p)
|
||||||
|
{
|
||||||
|
char *ret = strrchr(p, '/');
|
||||||
|
|
||||||
|
return ret ? (1+ret) : p;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
char *pgm = "makepage";
|
||||||
|
|
||||||
|
struct h_opt opts[] = {
|
||||||
|
{ 0, "version", 'V', 0, "show version info" },
|
||||||
|
{ 0, 0, 'F', "bitmap", "set/show hex flags" },
|
||||||
|
{ 0, "flags", 'f', "{+-}flags", "set/show named flags" },
|
||||||
|
} ;
|
||||||
|
#define NROPTS (sizeof opts / sizeof opts[0])
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
MMIOT *doc;
|
||||||
|
char *q;
|
||||||
|
int version = 0;
|
||||||
|
int ret, i;
|
||||||
|
DWORD bits;
|
||||||
|
mkd_flag_t *flags = mkd_flags();
|
||||||
|
struct h_opt *opt;
|
||||||
|
struct h_context blob;
|
||||||
|
|
||||||
|
if ( !flags )
|
||||||
|
perror("mkd_flags");
|
||||||
|
|
||||||
|
if ( (q = getenv("MARKDOWN_FLAGS")) ) {
|
||||||
|
bits = strtol(q, 0, 0);
|
||||||
|
|
||||||
|
for ( i=0; i < 8*sizeof(bits); i++)
|
||||||
|
if ( bits & (1<<i) )
|
||||||
|
mkd_set_flag_num(flags, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
hoptset(&blob, argc, argv);
|
||||||
|
hopterr(&blob, 1);
|
||||||
|
|
||||||
|
while ( opt = gethopt(&blob, opts, NROPTS) ) {
|
||||||
|
if ( opt == HOPTERR ) {
|
||||||
|
hoptusage(pgm, opts, NROPTS, "[file]");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
switch ( opt->optchar ) {
|
||||||
|
case 'V': version++;
|
||||||
|
break;
|
||||||
|
case 'F': if ( strcmp(hoptarg(&blob), "?") == 0 ) {
|
||||||
|
show_flags(0,0,0);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
bits = strtol(hoptarg(&blob), 0, 0);
|
||||||
|
|
||||||
|
for (i=0; i < 8*sizeof(bits); i++)
|
||||||
|
if ( bits & (1<<i) )
|
||||||
|
mkd_set_flag_num(flags, i);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'f': if ( strcmp(hoptarg(&blob), "?") == 0 ) {
|
||||||
|
show_flags(1,version,0);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
else if ( q = mkd_set_flag_string(flags, hoptarg(&blob)) )
|
||||||
|
fprintf(stderr, "unknown option <%s>\n", q);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
argc -= hoptind(&blob);
|
||||||
|
argv += hoptind(&blob);
|
||||||
|
|
||||||
|
if ( version ) {
|
||||||
|
printf("%s: discount %s", pgm, markdown_version);
|
||||||
|
if ( version > 1 )
|
||||||
|
mkd_flags_are(stdout, flags, 0);
|
||||||
|
putchar('\n');
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( (argc > 0) && !freopen(argv[0], "r", stdin) ) {
|
||||||
|
perror(argv[0]);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( (doc = mkd_in(stdin, flags)) == 0 ) {
|
||||||
|
perror( (argc > 1) ? argv[1] : "stdin" );
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = mkd_xhtmlpage(doc, flags, stdout);
|
||||||
|
|
||||||
|
mkd_cleanup(doc);
|
||||||
|
|
||||||
|
mkd_free_flags(flags);
|
||||||
|
|
||||||
|
return (ret == EOF);
|
||||||
|
}
|
||||||
201
markdown.1
Normal file
201
markdown.1
Normal file
@ -0,0 +1,201 @@
|
|||||||
|
.\" %A%
|
||||||
|
.\"
|
||||||
|
.Dd January 7, 2008
|
||||||
|
.Dt MARKDOWN 1
|
||||||
|
.Os MASTODON
|
||||||
|
.Sh NAME
|
||||||
|
.Nm markdown
|
||||||
|
.Nd text to html conversion tool
|
||||||
|
.Sh SYNOPSIS
|
||||||
|
.Nm
|
||||||
|
.Op Fl d
|
||||||
|
.Op Fl T
|
||||||
|
.Op Fl V
|
||||||
|
.Op Fl b Ar url-base
|
||||||
|
.Op Fl C Ar prefix
|
||||||
|
.Op Fl F Pa bitmap
|
||||||
|
.Op Fl f Ar flags
|
||||||
|
.Op Fl n
|
||||||
|
.Op Fl o Pa file
|
||||||
|
.Op Fl S
|
||||||
|
.Op Fl s Pa text
|
||||||
|
.Op Fl t Pa text
|
||||||
|
.Op Fl toc
|
||||||
|
.Op Pa textfile
|
||||||
|
.Sh DESCRIPTION
|
||||||
|
The
|
||||||
|
.Nm
|
||||||
|
utility reads the
|
||||||
|
.Xr markdown 7 Ns -formatted
|
||||||
|
.Pa textfile
|
||||||
|
.Pq or stdin if not specified,
|
||||||
|
compiles it, and writes the html output
|
||||||
|
to stdout.
|
||||||
|
.Pp
|
||||||
|
The options are as follows:
|
||||||
|
.Bl -tag -width "-o file"
|
||||||
|
.It Fl b Ar url-base
|
||||||
|
Links in source beginning with / will be prefixed with
|
||||||
|
.Ar url-base
|
||||||
|
in the output.
|
||||||
|
.It Fl C
|
||||||
|
When processing markdown extra-style footnotes, use the
|
||||||
|
given prefix instead of the default of
|
||||||
|
.Ar fn .
|
||||||
|
.It Fl d
|
||||||
|
Instead of writing the html file, dump a parse
|
||||||
|
tree to stdout.
|
||||||
|
.It Fl f Ar flags
|
||||||
|
Set or clear various translation flags. The flags
|
||||||
|
are in a comma-delimited list, with an optional
|
||||||
|
.Ar +
|
||||||
|
(enable),
|
||||||
|
.Ar -
|
||||||
|
(disable), or
|
||||||
|
.Ar no
|
||||||
|
(disable) lprefix on each flag.
|
||||||
|
.Bl -tag -width "definitionlist"
|
||||||
|
.It Ar links
|
||||||
|
Allow links.
|
||||||
|
.It Ar image
|
||||||
|
Allow images.
|
||||||
|
.It Ar smarty
|
||||||
|
Enable smartypants.
|
||||||
|
.It Ar pants
|
||||||
|
Enable smartypants.
|
||||||
|
.It Ar html
|
||||||
|
Allow raw html.
|
||||||
|
.It Ar strict
|
||||||
|
Disable superscript, strikethrough & relaxed emphasis.
|
||||||
|
.It Ar ext
|
||||||
|
Enable pseudo-protocols.
|
||||||
|
.It Ar cdata
|
||||||
|
Generate code for xml
|
||||||
|
.Em ![CDATA[...]] .
|
||||||
|
.It Ar superscript
|
||||||
|
Enable superscript processing.
|
||||||
|
.It Ar emphasis
|
||||||
|
Emphasis happens
|
||||||
|
.Em everywhere .
|
||||||
|
.It Ar tables
|
||||||
|
Don't process PHP Markdown Extra tables.
|
||||||
|
.It Ar del
|
||||||
|
Enable
|
||||||
|
.Em ~~strikethrough~~ .
|
||||||
|
.It Ar strikethrough
|
||||||
|
Enable
|
||||||
|
.Em ~~strikethrough~~ .
|
||||||
|
.It Ar toc
|
||||||
|
Enable table-of-contents processing.
|
||||||
|
.It Ar 1.0
|
||||||
|
Compatibility with MarkdownTest_1.0
|
||||||
|
.It Ar autolink
|
||||||
|
Make
|
||||||
|
.Pa http://foo.com
|
||||||
|
a link even without
|
||||||
|
.Em <> .
|
||||||
|
.It Ar safelink
|
||||||
|
Paranoid check for link protocol.
|
||||||
|
.It Ar header
|
||||||
|
Process pandoc-style header blocks.
|
||||||
|
.It Ar tabstop
|
||||||
|
Expand tabs to 4 spaces.
|
||||||
|
.It Ar divquote
|
||||||
|
Allow
|
||||||
|
.Pa >%class%
|
||||||
|
blocks.
|
||||||
|
.It Ar alphalist
|
||||||
|
Allow alphabetic lists.
|
||||||
|
.It Ar definitionlist
|
||||||
|
Allow definition lists at all (default). Use
|
||||||
|
.Em dldiscount
|
||||||
|
and
|
||||||
|
.Em dlextra
|
||||||
|
to control which syntaxes are respected.
|
||||||
|
.It Ar dldiscount
|
||||||
|
Enable discount-style definition lists (default).
|
||||||
|
.It Ar dlextra
|
||||||
|
Enable extra-style definition lists (not default). Both styles may be enabled simultaneously.
|
||||||
|
.It Ar footnote
|
||||||
|
Allow markdown extra-style footnotes.
|
||||||
|
.It Ar style
|
||||||
|
Extract <style> blocks from the output.
|
||||||
|
.It Ar fencedcode
|
||||||
|
Allow fenced code blocks (not default).
|
||||||
|
.It Ar idanchor
|
||||||
|
Use id= anchors for table-of-contents links instead of <a name=/> (not default).
|
||||||
|
.It Ar githubtags
|
||||||
|
Allow underscore and dash in passed through element names (not default).
|
||||||
|
.It Ar urlencodedanchor
|
||||||
|
Use url-encoded chars for multibyte and nonalphanumeric chars rather than dots in toc links.
|
||||||
|
.El
|
||||||
|
.Pp
|
||||||
|
As an example, the option
|
||||||
|
.Fl f Ar nolinks,smarty
|
||||||
|
tells
|
||||||
|
.Nm
|
||||||
|
to not allow \<a tags, and to do smarty
|
||||||
|
pants processing.
|
||||||
|
.It Fl F Ar bitmap
|
||||||
|
Set translation flags.
|
||||||
|
.Ar Bitmap
|
||||||
|
is a bit map of the various configuration options
|
||||||
|
described in
|
||||||
|
.Xr markdown 3
|
||||||
|
(the flag values are defined in
|
||||||
|
.Pa mkdio.h )
|
||||||
|
.It Fl n
|
||||||
|
Don't write generated html.
|
||||||
|
.It Fl o Pa file
|
||||||
|
Write the generated html to
|
||||||
|
.Pa file .
|
||||||
|
.It Fl S
|
||||||
|
output <style> blocks.
|
||||||
|
.It Fl V
|
||||||
|
Show the version# and compile-time configuration data.
|
||||||
|
.Pp
|
||||||
|
If the version includes the string
|
||||||
|
.Em DEBUG ,
|
||||||
|
.Nm
|
||||||
|
was configured with memory allocation debugging.
|
||||||
|
.Pp
|
||||||
|
If the version includes the string
|
||||||
|
.Em TAB ,
|
||||||
|
.Nm
|
||||||
|
was configured to use the specified tabstop.
|
||||||
|
.It Fl VV
|
||||||
|
Show the version#, the compile-time configuration, and the
|
||||||
|
run-time configuration.
|
||||||
|
.It Fl t Ar text
|
||||||
|
Use
|
||||||
|
.Xr mkd_text 3
|
||||||
|
to format
|
||||||
|
.Ar text
|
||||||
|
instead of processing stdin with the
|
||||||
|
.Xr markdown 3
|
||||||
|
function.
|
||||||
|
.It Fl T
|
||||||
|
If run with the table-of-content flag on, dump the
|
||||||
|
table of contents before the formatted text.
|
||||||
|
.It Fl s Ar text
|
||||||
|
Use the
|
||||||
|
.Xr markdown 3
|
||||||
|
function to format
|
||||||
|
.Ar text .
|
||||||
|
.It Fl toc
|
||||||
|
Set the table-of-content flag, then dump the table of contents
|
||||||
|
before the formatted text (a shorthand for
|
||||||
|
.Fl -T -toc
|
||||||
|
)
|
||||||
|
.El
|
||||||
|
.Sh RETURN VALUES
|
||||||
|
The
|
||||||
|
.Nm
|
||||||
|
utility exits 0 on success, and >0 if an error occurs.
|
||||||
|
.Sh SEE ALSO
|
||||||
|
.Xr markdown 3 ,
|
||||||
|
.Xr markdown 7 ,
|
||||||
|
.Xr mkd-extensions 7 .
|
||||||
|
.Sh AUTHOR
|
||||||
|
.An Jessica L. Parsons
|
||||||
|
.Pq Li orc@pell.portland.or.us
|
||||||
156
markdown.3
Normal file
156
markdown.3
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
.\"
|
||||||
|
.Dd December 20, 2007
|
||||||
|
.Dt MARKDOWN 3
|
||||||
|
.Os Mastodon
|
||||||
|
.Sh NAME
|
||||||
|
.Nm markdown
|
||||||
|
.Nd process Markdown documents
|
||||||
|
.Sh LIBRARY
|
||||||
|
Markdown
|
||||||
|
.Pq libmarkdown , -lmarkdown
|
||||||
|
.Sh SYNOPSIS
|
||||||
|
.Fd #include <mkdio.h>
|
||||||
|
.Ft MMIOT
|
||||||
|
.Fn *mkd_in "FILE *input" "mkd_flag_t *flags"
|
||||||
|
.Ft MMIOT
|
||||||
|
.Fn *mkd_string "char *string" "int size" "mkd_flag_t *flags"
|
||||||
|
.Ft int
|
||||||
|
.Fn markdown "MMIOT *doc" "FILE *output" "mkd_flag_t *flags"
|
||||||
|
.Sh DESCRIPTION
|
||||||
|
These functions
|
||||||
|
convert
|
||||||
|
.Em Markdown
|
||||||
|
documents and strings into HTML.
|
||||||
|
.Fn markdown
|
||||||
|
processes an entire document, while
|
||||||
|
.Fn mkd_text
|
||||||
|
processes a single string.
|
||||||
|
.Pp
|
||||||
|
To process a file, you pass a FILE* to
|
||||||
|
.Fn mkd_in ,
|
||||||
|
and if it returns a nonzero value you pass that in to
|
||||||
|
.Fn markdown ,
|
||||||
|
which then writes the converted document to the specified
|
||||||
|
.Em FILE* .
|
||||||
|
If your input has already been written into a string (generated
|
||||||
|
input or a file opened
|
||||||
|
with
|
||||||
|
.Xr mmap 2 )
|
||||||
|
you can feed that string to
|
||||||
|
.Fn mkd_string
|
||||||
|
and pass its return value to
|
||||||
|
.Fn markdown.
|
||||||
|
.Pp
|
||||||
|
.Fn Markdown
|
||||||
|
holds the flag values in an opaque flag blob that you need to
|
||||||
|
initialize and populate before using:
|
||||||
|
.Bl -tag -width MKD_NOSTRIKETHROUGH -compact
|
||||||
|
.It Ft "mkd_flag_t*" Fn mkd_flag_t
|
||||||
|
creates a mkd_flag_t structure and returns a pointer to it.
|
||||||
|
.It Fn mkd_free_flags "mkd_flag_t *"
|
||||||
|
deletes a mkd_flag_t structure when you are finished with it.
|
||||||
|
.It Ft mkd_flag_t* Fn mkd_copy_flags "mkd_flag_t*"
|
||||||
|
Makes a copy of a flag blob and returns a pointer to it.
|
||||||
|
.It Fn mkd_flag_isset "mkd_flag_t *" "int"
|
||||||
|
tells you if a specific flag is set
|
||||||
|
.It Fn mkd_set_flag_num "mkd_flag_t *" "int"
|
||||||
|
Sets a specified flag
|
||||||
|
.It Fn mkd_clr_flag_num "mkd_flag_t *" "int"
|
||||||
|
Clears a specified flag
|
||||||
|
.El
|
||||||
|
.Pp
|
||||||
|
The following flags are currently accepted:
|
||||||
|
.Bl -tag -width MKD_NOSTRIKETHROUGH -compact
|
||||||
|
.It Ar MKD_NOLINKS
|
||||||
|
don't do link processing, block <a> tags
|
||||||
|
.It Ar MKD_NOIMAGE
|
||||||
|
don't do image processing, block <img>
|
||||||
|
.It Ar MKD_NOPANTS
|
||||||
|
don't run smartypants()
|
||||||
|
.It Ar MKD_NOHTML
|
||||||
|
don't allow raw html through AT ALL
|
||||||
|
.It Ar MKD_NORMAL_LISTITEM
|
||||||
|
disable github-style checkbox lists
|
||||||
|
.It Ar MKD_TAGTEXT
|
||||||
|
process text inside an html tag
|
||||||
|
.It Ar MKD_NO_EXT
|
||||||
|
don't allow pseudo-protocols
|
||||||
|
.It Ar MKD_EXPLICITLIST
|
||||||
|
don't combine numbered/bulletted lists
|
||||||
|
.It Ar MKD_CDATA
|
||||||
|
generate code for xml ![CDATA[...]]
|
||||||
|
.It Ar MKD_NOSUPERSCRIPT
|
||||||
|
no A^B
|
||||||
|
.It Ar MKD_STRICT
|
||||||
|
conform to Markdown standard as implemented in Markdown.pl
|
||||||
|
.It Ar MKD_NOTABLES
|
||||||
|
disallow tables
|
||||||
|
.It Ar MKD_NOSTRIKETHROUGH
|
||||||
|
forbid ~~strikethrough~~
|
||||||
|
.It Ar MKD_1_COMPAT
|
||||||
|
compatibility with MarkdownTest_1.0
|
||||||
|
.It Ar MKD_TOC
|
||||||
|
do table-of-contents processing
|
||||||
|
.It Ar MKD_AUTOLINK
|
||||||
|
make http://foo.com link even without <>s
|
||||||
|
.It Ar MKD_NOHEADER
|
||||||
|
don't process header blocks
|
||||||
|
.It Ar MKD_TABSTOP
|
||||||
|
expand tabs to 4 spaces
|
||||||
|
.It Ar MKD_SAFELINK
|
||||||
|
paranoid check for link protocol
|
||||||
|
.It Ar MKD_NODIVQUOTE
|
||||||
|
forbid >%class% blocks
|
||||||
|
.It Ar MKD_NOALPHALIST
|
||||||
|
forbid alphabetic lists
|
||||||
|
.It Ar MKD_EXTRA_FOOTNOTE
|
||||||
|
enable markdown extra-style footnotes
|
||||||
|
.It Ar MKD_NOSTYLE
|
||||||
|
don't extract <style> blocks
|
||||||
|
.It Ar MKD_DLDISCOUNT
|
||||||
|
enable discount-style definition lists
|
||||||
|
.It Ar MKD_DLEXTRA
|
||||||
|
enable extra-style definition lists
|
||||||
|
.It Ar MKD_FENCEDCODE
|
||||||
|
enabled fenced code blocks
|
||||||
|
.It Ar MKD_IDANCHOR
|
||||||
|
use id= anchors for TOC links
|
||||||
|
.It Ar MKD_GITHUBTAGS
|
||||||
|
allow dash and underscore in element names
|
||||||
|
.It Ar MKD_URLENCODEDANCHOR
|
||||||
|
urlencode non-identifier chars instead of replacing with dots
|
||||||
|
.It Ar MKD_LATEX
|
||||||
|
handle embedded LaTeX escapes
|
||||||
|
.It Ar MKD_ALT_AS_TITLE
|
||||||
|
use alt text as the title if no title is listed
|
||||||
|
.It Ar MKD_EXTENDED_ATTR
|
||||||
|
allow extended attribute suffixes
|
||||||
|
.El
|
||||||
|
.Sh RETURN VALUES
|
||||||
|
.Fn markdown
|
||||||
|
returns 0 on success, 1 on failure.
|
||||||
|
The
|
||||||
|
.Fn mkd_in
|
||||||
|
and
|
||||||
|
.Fn mkd_string
|
||||||
|
functions return a MMIOT* on success, null on failure.
|
||||||
|
.Sh SEE ALSO
|
||||||
|
.Xr markdown 1 ,
|
||||||
|
.Xr mkd-callbacks 3 ,
|
||||||
|
.Xr mkd-functions 3 ,
|
||||||
|
.Xr mkd-line 3 ,
|
||||||
|
.Xr markdown 7 ,
|
||||||
|
.Xr mkd-extensions 7 ,
|
||||||
|
.Xr mmap 2 .
|
||||||
|
.Pp
|
||||||
|
http://daringfireball.net/projects/markdown/syntax
|
||||||
|
.Sh BUGS
|
||||||
|
Error handling is minimal at best.
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Ar MMIOT
|
||||||
|
created by
|
||||||
|
.Fn mkd_string
|
||||||
|
is deleted by the
|
||||||
|
.Nm
|
||||||
|
function.
|
||||||
1020
markdown.7
Normal file
1020
markdown.7
Normal file
File diff suppressed because it is too large
Load Diff
1546
markdown.c
Normal file
1546
markdown.c
Normal file
File diff suppressed because it is too large
Load Diff
323
markdown.h
Normal file
323
markdown.h
Normal file
@ -0,0 +1,323 @@
|
|||||||
|
#ifndef _MARKDOWN_D
|
||||||
|
#define _MARKDOWN_D
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include "cstring.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_INTTYPES_H
|
||||||
|
# include <inttypes.h>
|
||||||
|
#elif HAVE_STDINT_H
|
||||||
|
# include <stdint.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* flags, captured into a named type
|
||||||
|
*/
|
||||||
|
enum { MKD_NOLINKS=0, /* don't do link processing, block <a> tags */
|
||||||
|
MKD_NOIMAGE, /* don't do image processing, block <img> */
|
||||||
|
MKD_NOPANTS, /* don't run smartypants() */
|
||||||
|
MKD_NOHTML, /* don't allow raw html through AT ALL */
|
||||||
|
MKD_NORMAL_LISTITEM, /* disable github-style checkbox lists */
|
||||||
|
MKD_TAGTEXT, /* process text inside an html tag */
|
||||||
|
MKD_NO_EXT, /* don't allow pseudo-protocols */
|
||||||
|
#define MKD_NOEXT MKD_NO_EXT
|
||||||
|
MKD_EXPLICITLIST, /* don't combine numbered/bulletted lists */
|
||||||
|
MKD_CDATA, /* generate code for xml ![CDATA[...]] */
|
||||||
|
MKD_NOSUPERSCRIPT, /* no A^B */
|
||||||
|
MKD_STRICT, /* conform to Markdown standard as implemented in Markdown.pl */
|
||||||
|
MKD_NOTABLES, /* disallow tables */
|
||||||
|
MKD_NOSTRIKETHROUGH, /* forbid ~~strikethrough~~ */
|
||||||
|
MKD_1_COMPAT, /* compatibility with MarkdownTest_1.0 */
|
||||||
|
MKD_TOC, /* do table-of-contents processing */
|
||||||
|
MKD_AUTOLINK, /* make http://foo.com link even without <>s */
|
||||||
|
MKD_NOHEADER, /* don't process header blocks */
|
||||||
|
MKD_TABSTOP, /* expand tabs to 4 spaces */
|
||||||
|
MKD_SAFELINK, /* paranoid check for link protocol */
|
||||||
|
MKD_NODIVQUOTE, /* forbid >%class% blocks */
|
||||||
|
MKD_NOALPHALIST, /* forbid alphabetic lists */
|
||||||
|
MKD_EXTRA_FOOTNOTE, /* enable markdown extra-style footnotes */
|
||||||
|
MKD_NOSTYLE, /* don't extract <style> blocks */
|
||||||
|
MKD_DLDISCOUNT, /* enable discount-style definition lists */
|
||||||
|
MKD_DLEXTRA, /* enable extra-style definition lists */
|
||||||
|
MKD_FENCEDCODE, /* enabled fenced code blocks */
|
||||||
|
MKD_IDANCHOR, /* use id= anchors for TOC links */
|
||||||
|
MKD_GITHUBTAGS, /* allow dash and underscore in element names */
|
||||||
|
MKD_URLENCODEDANCHOR, /* urlencode non-identifier chars instead of replacing with dots */
|
||||||
|
MKD_LATEX, /* handle embedded LaTeX escapes */
|
||||||
|
MKD_ALT_AS_TITLE, /* use alt text as the title if no title is listed */
|
||||||
|
MKD_EXTENDED_ATTR, /* allow extended attribute suffixes */
|
||||||
|
MKD_HTML5, /* handle html5 tags (obsolete?) */
|
||||||
|
/* end of user flags */
|
||||||
|
IS_LABEL,
|
||||||
|
MKD_NR_FLAGS };
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct { char bit[MKD_NR_FLAGS]; } mkd_flag_t;
|
||||||
|
|
||||||
|
void mkd_init_flags(mkd_flag_t *p);
|
||||||
|
|
||||||
|
#define is_flag_set(flags, item) ((flags)->bit[item])
|
||||||
|
#define set_mkd_flag(flags, item) ((flags)->bit[item] = 1)
|
||||||
|
#define clear_mkd_flag(flags, item) ((flags)->bit[item] = 0)
|
||||||
|
|
||||||
|
#define COPY_FLAGS(dst,src) memcpy(&dst,&src,sizeof dst)
|
||||||
|
|
||||||
|
void ___mkd_or_flags(mkd_flag_t* dst, mkd_flag_t* src);
|
||||||
|
int ___mkd_different(mkd_flag_t* dst, mkd_flag_t* src);
|
||||||
|
int ___mkd_any_flags(mkd_flag_t* dst, mkd_flag_t* src);
|
||||||
|
|
||||||
|
#define ADD_FLAGS(dst,src) ___mkd_or_flags(dst,src)
|
||||||
|
#define DIFFERENT(dst,src) ___mkd_different(dst,src)
|
||||||
|
#define ANY_FLAGS(dst,src) ___mkd_any_flags(dst,src)
|
||||||
|
|
||||||
|
/* each input line is read into a Line, which contains the line,
|
||||||
|
* the offset of the first non-space character [this assumes
|
||||||
|
* that all tabs will be expanded to spaces!], and a pointer to
|
||||||
|
* the next line.
|
||||||
|
*/
|
||||||
|
typedef enum { chk_text, chk_code,
|
||||||
|
chk_hr, chk_dash,
|
||||||
|
chk_tilde, chk_backtick,
|
||||||
|
chk_equal } line_type;
|
||||||
|
typedef struct line {
|
||||||
|
Cstring text;
|
||||||
|
struct line *next;
|
||||||
|
int dle; /* leading indent on the line */
|
||||||
|
int has_pipechar; /* line contains a | */
|
||||||
|
int is_checked;
|
||||||
|
line_type kind;
|
||||||
|
int is_fenced; /* line inside a fenced code block (ick) */
|
||||||
|
char *fence_class; /* fenced code class (ick) */
|
||||||
|
int count;
|
||||||
|
} Line;
|
||||||
|
|
||||||
|
|
||||||
|
/* a paragraph is a collection of Lines, with links to the next paragraph
|
||||||
|
* and (if it's a QUOTE, UL, or OL) to the reparsed contents of this
|
||||||
|
* paragraph.
|
||||||
|
*/
|
||||||
|
typedef struct paragraph {
|
||||||
|
struct paragraph *next; /* next paragraph */
|
||||||
|
struct paragraph *down; /* recompiled contents of this paragraph */
|
||||||
|
struct line *text; /* all the text in this paragraph */
|
||||||
|
char *label; /* toc label, uniqued */
|
||||||
|
char *ident; /* %id% tag for QUOTE */
|
||||||
|
char *lang; /* lang attribute for CODE */
|
||||||
|
enum { WHITESPACE=0, CODE, QUOTE, MARKUP,
|
||||||
|
HTML, STYLE, DL, UL, OL, AL, LISTITEM,
|
||||||
|
HDR, HR, TABLE, SOURCE } typ;
|
||||||
|
enum { IMPLICIT=0, PARA, CENTER} align;
|
||||||
|
int hnumber; /* <Hn> for typ == HDR */
|
||||||
|
int para_flags;
|
||||||
|
#define GITHUB_CHECK 0x01
|
||||||
|
#define IS_CHECKED 0x02
|
||||||
|
} Paragraph;
|
||||||
|
|
||||||
|
typedef ANCHOR(Paragraph) ParagraphRoot;
|
||||||
|
|
||||||
|
enum { ETX, SETEXT }; /* header types */
|
||||||
|
|
||||||
|
/* reference-style links (and images) are stored in an array
|
||||||
|
* of footnotes.
|
||||||
|
*/
|
||||||
|
typedef struct footnote {
|
||||||
|
Cstring tag; /* the tag for the reference link */
|
||||||
|
Cstring link; /* what this footnote points to */
|
||||||
|
Cstring title; /* what it's called (TITLE= attribute) */
|
||||||
|
Paragraph *text; /* EXTRA_FOOTNOTE content */
|
||||||
|
|
||||||
|
Cstring height, width; /* dimensions (for image link) */
|
||||||
|
Cstring extended_attr; /* extended attributes iff MKD_EXTENDED_ATTR */
|
||||||
|
int dealloc; /* deallocation needed? */
|
||||||
|
int refnumber;
|
||||||
|
int fn_flags;
|
||||||
|
#define EXTRA_FOOTNOTE 0x01
|
||||||
|
#define REFERENCED 0x02
|
||||||
|
} Footnote;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct block {
|
||||||
|
enum { bTEXT, bSTAR, bUNDER } b_type;
|
||||||
|
int b_count;
|
||||||
|
char b_char;
|
||||||
|
Cstring b_text;
|
||||||
|
Cstring b_post;
|
||||||
|
} block;
|
||||||
|
|
||||||
|
typedef STRING(block) Qblock;
|
||||||
|
|
||||||
|
|
||||||
|
typedef char* (*mkd_callback_t)(const char*, const int, void*);
|
||||||
|
typedef void (*mkd_free_t)(char*, void*);
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
mkd_callback_t func, free;
|
||||||
|
void *data;
|
||||||
|
} One_callback;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
One_callback e_url; /* url edit callback */
|
||||||
|
One_callback e_flags; /* extra href flags callback */
|
||||||
|
One_callback e_anchor; /* callback for anchor types */
|
||||||
|
One_callback e_codefmt; /* codeblock formatter (for highlighting) */
|
||||||
|
} Callback_data;
|
||||||
|
|
||||||
|
|
||||||
|
struct escaped {
|
||||||
|
char *text;
|
||||||
|
struct escaped *up;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
struct footnote_list {
|
||||||
|
int reference;
|
||||||
|
STRING(Footnote) note;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* html tag structure (here for MMIOT->extratags)
|
||||||
|
*/
|
||||||
|
struct kw {
|
||||||
|
char *id;
|
||||||
|
int size;
|
||||||
|
int selfclose;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* a magic markdown io thing holds all the data structures needed to
|
||||||
|
* do the backend processing of a markdown document
|
||||||
|
*/
|
||||||
|
typedef struct mmiot {
|
||||||
|
Cstring out;
|
||||||
|
Cstring in;
|
||||||
|
Qblock Q;
|
||||||
|
char last; /* last text character added to out */
|
||||||
|
int isp;
|
||||||
|
struct escaped *esc;
|
||||||
|
char *ref_prefix;
|
||||||
|
struct footnote_list *footnotes;
|
||||||
|
mkd_flag_t flags;
|
||||||
|
|
||||||
|
Callback_data *cb;
|
||||||
|
STRING(struct kw) extratags; /* extra (mainly html5) tags */
|
||||||
|
} MMIOT;
|
||||||
|
|
||||||
|
|
||||||
|
#define MKD_EOLN '\r'
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* the mkdio text input functions return a document structure,
|
||||||
|
* which contains a header (retrieved from the document if
|
||||||
|
* markdown was configured * with the * --enable-pandoc-header
|
||||||
|
* and the document begins with a pandoc-style header) and the
|
||||||
|
* root of the linked list of Lines.
|
||||||
|
*/
|
||||||
|
typedef struct document {
|
||||||
|
int magic; /* "I AM VALID" magic number */
|
||||||
|
#define VALID_DOCUMENT 0x19600731
|
||||||
|
Line *title;
|
||||||
|
Line *author;
|
||||||
|
Line *date;
|
||||||
|
ANCHOR(Line) content; /* uncompiled text, not valid after compile() */
|
||||||
|
Paragraph *code; /* intermediate code generated by compile() */
|
||||||
|
int compiled; /* set after mkd_compile() */
|
||||||
|
int dirty; /* flags or callbacks changed */
|
||||||
|
int html; /* set after (internal) htmlify() */
|
||||||
|
int tabstop; /* for properly expanding tabs (ick) */
|
||||||
|
char *ref_prefix;
|
||||||
|
MMIOT *ctx; /* backend buffers, flags, and structures */
|
||||||
|
Callback_data cb; /* callback functions & private data */
|
||||||
|
} Document;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* economy FILE-type structure for pulling characters out of a
|
||||||
|
* fixed-length string.
|
||||||
|
*/
|
||||||
|
struct string_stream {
|
||||||
|
const char *data; /* the unread data */
|
||||||
|
int size; /* and how much is there? */
|
||||||
|
} ;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* sneakily back-define the published interface (leaving the old functions for v2 compatibility)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define mkd_in mkd3_in
|
||||||
|
#define mkd_string mkd3_string
|
||||||
|
#define gfm_in gfm3_in
|
||||||
|
#define gfm_string gfm3_string
|
||||||
|
#define mkd_compile mkd3_compile
|
||||||
|
#define mkd_dump mkd3_dump
|
||||||
|
#define markdown markdown3
|
||||||
|
#define mkd_line mkd3_line
|
||||||
|
#define mkd_xhtmlpage mkd3_xhtmlpage
|
||||||
|
#define mkd_generateline mkd3_generateline
|
||||||
|
#define mkd_flags_are mkd3_flags_are
|
||||||
|
|
||||||
|
|
||||||
|
/* the published interface (plus a few local functions that I need to fix)
|
||||||
|
*/
|
||||||
|
extern int mkd_firstnonblank(Line *);
|
||||||
|
extern int mkd_compile(Document *, mkd_flag_t*);
|
||||||
|
extern int mkd_document(Document *, char **);
|
||||||
|
extern int mkd_generatehtml(Document *, FILE *);
|
||||||
|
extern int mkd_css(Document *, char **);
|
||||||
|
extern int mkd_generatecss(Document *, FILE *);
|
||||||
|
#define mkd_style mkd_generatecss
|
||||||
|
extern int mkd_xml(char *, int , char **);
|
||||||
|
extern int mkd_generatexml(char *, int, FILE *);
|
||||||
|
extern void mkd_cleanup(Document *);
|
||||||
|
extern int mkd_line(char *, int, char **, mkd_flag_t*);
|
||||||
|
extern int mkd_generateline(char *, int, FILE*, mkd_flag_t*);
|
||||||
|
#define mkd_text mkd_generateline
|
||||||
|
extern void mkd_basename(Document*, char *);
|
||||||
|
extern void mkd_add_html5_tags(MMIOT*);
|
||||||
|
|
||||||
|
typedef int (*mkd_sta_function_t)(const int,const void*);
|
||||||
|
extern void mkd_string_to_anchor(char*,int, mkd_sta_function_t, void*, int, MMIOT *);
|
||||||
|
|
||||||
|
extern Document *mkd_in(FILE *, mkd_flag_t*);
|
||||||
|
extern Document *mkd_string(const char*, int, mkd_flag_t*);
|
||||||
|
|
||||||
|
extern Document *gfm_in(FILE *, mkd_flag_t*);
|
||||||
|
extern Document *gfm_string(const char*,int, mkd_flag_t*);
|
||||||
|
|
||||||
|
extern void mkd_initialize(void);
|
||||||
|
|
||||||
|
extern void mkd_ref_prefix(Document*, char*);
|
||||||
|
|
||||||
|
/* internal resource handling functions.
|
||||||
|
*/
|
||||||
|
extern void ___mkd_freeLine(Line *);
|
||||||
|
extern void ___mkd_freeLines(Line *);
|
||||||
|
extern void ___mkd_freeParagraph(Paragraph *);
|
||||||
|
extern void ___mkd_freefootnote(Footnote *);
|
||||||
|
extern void ___mkd_freefootnotes(MMIOT *);
|
||||||
|
extern void ___mkd_initmmiot(MMIOT *, void *, mkd_flag_t*);
|
||||||
|
extern void ___mkd_freemmiot(MMIOT *, void *);
|
||||||
|
extern void ___mkd_freeLineRange(Line *, Line *);
|
||||||
|
extern void ___mkd_xml(char *, int, FILE *);
|
||||||
|
extern void ___mkd_reparse(char *, int, mkd_flag_t*, MMIOT*, char*);
|
||||||
|
extern void ___mkd_emblock(MMIOT*);
|
||||||
|
extern void ___mkd_tidy(Cstring *);
|
||||||
|
|
||||||
|
extern Document *__mkd_new_Document(void);
|
||||||
|
extern void __mkd_enqueue(Document*, Cstring *);
|
||||||
|
extern void __mkd_trim_line(Line *, int);
|
||||||
|
|
||||||
|
extern int __mkd_io_strget(struct string_stream *);
|
||||||
|
|
||||||
|
/* toc uniquifier
|
||||||
|
*/
|
||||||
|
extern void ___mkd_uniquify(ParagraphRoot *, Paragraph *);
|
||||||
|
|
||||||
|
/* utility function to do some operation and exit the current function
|
||||||
|
* if it fails
|
||||||
|
*/
|
||||||
|
#define DO_OR_DIE(op) if ( (op) == EOF ) return EOF; else 1
|
||||||
|
|
||||||
|
#endif/*_MARKDOWN_D*/
|
||||||
77
mkd-callbacks.3
Normal file
77
mkd-callbacks.3
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
.\"
|
||||||
|
.Dd January 18, 2008
|
||||||
|
.Dt MKD_CALLBACKS 3
|
||||||
|
.Os Mastodon
|
||||||
|
.Sh NAME
|
||||||
|
.Nm mkd_callbacks
|
||||||
|
.Nd functions that modify link targets
|
||||||
|
.Sh LIBRARY
|
||||||
|
Markdown
|
||||||
|
.Pq libmarkdown , -lmarkdown
|
||||||
|
.Sh SYNOPSIS
|
||||||
|
.Fd #include <mkdio.h>
|
||||||
|
.Ft char*
|
||||||
|
.Fn (*mkd_callback_t) "const char*" "const int" "void*"
|
||||||
|
.Ft void
|
||||||
|
.Fn (*mkd_free_t) "char *" "void*"
|
||||||
|
.Ft void
|
||||||
|
.Fn mkd_e_url "MMIOT *document" "mkd_callback_t edit"
|
||||||
|
.Ft void
|
||||||
|
.Fn mkd_e_flags "MMIOT *document" "mkd_callback_t edit"
|
||||||
|
.Ft void
|
||||||
|
.Fn mkd_e_free "MMIOT *document" "mkd_free_t dealloc"
|
||||||
|
.Ft void
|
||||||
|
.Fn mkd_e_code "MMIOT *document" "mkd_callback_t edit"
|
||||||
|
.Ft void
|
||||||
|
.Fn mkd_e_data "MMIOT *document" "void *data"
|
||||||
|
.Sh DESCRIPTION
|
||||||
|
.Pp
|
||||||
|
.Nm Discount
|
||||||
|
provides a small set of data access functions to let a
|
||||||
|
library user modify the generated html.
|
||||||
|
.Bl -tag -width "!mkd_e_flags!"
|
||||||
|
.It Fn mkd_e_url
|
||||||
|
modifies the target given in a `[]` link;
|
||||||
|
.It Fn mkd_e_flags
|
||||||
|
adds additional flags to a `[]` link;
|
||||||
|
.It Fn mkd_e_code
|
||||||
|
lets you manipulate the contents of a code block.
|
||||||
|
.El
|
||||||
|
.Pp
|
||||||
|
The data access functions are passed a character pointer to
|
||||||
|
the url being generated, the size of the url, and a data pointer
|
||||||
|
pointing to a user data area (set by the
|
||||||
|
.Fn mkd_e_data
|
||||||
|
function.) After the callback function is called
|
||||||
|
the data freeing function (if supplied) is called and passed the
|
||||||
|
character pointer and user data pointer.
|
||||||
|
.Sh EXAMPLE
|
||||||
|
The
|
||||||
|
.Fn mkd_basename
|
||||||
|
function (in the module basename.c) is implemented by means of
|
||||||
|
mkd callbacks; it modifies urls that start with a `/' so that
|
||||||
|
they begin with a user-supplied url base by allocating a new
|
||||||
|
string and filling it with the base + the url. Discount plugs
|
||||||
|
that url in place of the original, then calls the basename
|
||||||
|
free function (it only does this when
|
||||||
|
.Fn mkd_e_url
|
||||||
|
or
|
||||||
|
.Fn mkd_e_flags
|
||||||
|
returns nonzero) to deallocate this memory.
|
||||||
|
.Pp
|
||||||
|
Note that only one level of callbacks are supported; if you
|
||||||
|
wish to do multiple callbacks, you need to write your own
|
||||||
|
code to handle them all.
|
||||||
|
.Sh SEE ALSO
|
||||||
|
.Xr markdown 1 ,
|
||||||
|
.Xr markdown 3 ,
|
||||||
|
.Xr mkd-line 3 ,
|
||||||
|
.Xr markdown 7 ,
|
||||||
|
.Xr mkd-extensions 7 ,
|
||||||
|
.Xr mmap 2 .
|
||||||
|
.Pp
|
||||||
|
basename.c
|
||||||
|
.Pp
|
||||||
|
http://daringfireball.net/projects/markdown/syntax
|
||||||
|
.Sh BUGS
|
||||||
|
Error handling is minimal at best.
|
||||||
197
mkd-extensions.7
Normal file
197
mkd-extensions.7
Normal file
@ -0,0 +1,197 @@
|
|||||||
|
.\"
|
||||||
|
.Dd Dec 22, 2007
|
||||||
|
.Dt MKD-EXTENSIONS 7
|
||||||
|
.Os MASTODON
|
||||||
|
.Sh NAME
|
||||||
|
.Nm mkd-extensions
|
||||||
|
.Nd Extensions to the Markdown text formatting syntax
|
||||||
|
.Sh DESCRIPTION
|
||||||
|
This version of markdown has been extended in a few ways by
|
||||||
|
extending existing markup, creating new markup from scratch,
|
||||||
|
and borrowing markup from other markup languages.
|
||||||
|
.Ss Image dimensions
|
||||||
|
Markdown embedded images have been extended to allow specifying
|
||||||
|
the dimensions of the image by adding a new argument
|
||||||
|
.Em =/height/x/width/
|
||||||
|
to the link description.
|
||||||
|
.Pp
|
||||||
|
The new image syntax is
|
||||||
|
.nf
|
||||||
|

|
||||||
|
.fi
|
||||||
|
.Ss pseudo-protocols
|
||||||
|
Five pseudo-protocols have been added to links
|
||||||
|
.Bl -tag -width XXXXX
|
||||||
|
.It Ar id:
|
||||||
|
The
|
||||||
|
.Ar "alt text"
|
||||||
|
is marked up and written to the output, wrapped with
|
||||||
|
.Em "<a id=id>"
|
||||||
|
and
|
||||||
|
.Em "</a>" .
|
||||||
|
.It Ar class:
|
||||||
|
The
|
||||||
|
.Ar "alt text"
|
||||||
|
is marked up and written to the output, wrapped with
|
||||||
|
.Em "<span class=class>"
|
||||||
|
and
|
||||||
|
.Em "</span>" .
|
||||||
|
.It Ar raw:
|
||||||
|
The
|
||||||
|
.Ar title
|
||||||
|
is written
|
||||||
|
.Em -- with no further processing --
|
||||||
|
to the output. The
|
||||||
|
.Ar "alt text"
|
||||||
|
is discarded.
|
||||||
|
.It Ar abbr:
|
||||||
|
The
|
||||||
|
.Ar "alt text"
|
||||||
|
is marked up and written to the output, wrapped with
|
||||||
|
.Em "<abbr title=abbr>"
|
||||||
|
and
|
||||||
|
.Em "</abbr>" .
|
||||||
|
.It Ar lang:
|
||||||
|
The
|
||||||
|
.Ar "alt text"
|
||||||
|
s marked up and written to the output, wrapped with
|
||||||
|
.Em "<span lang=lang>"
|
||||||
|
and
|
||||||
|
.Em "</span>" .
|
||||||
|
.El
|
||||||
|
.Ss Pandoc headers
|
||||||
|
The markdown source document can have a 3-line
|
||||||
|
.Xr Pandoc
|
||||||
|
header in the format of
|
||||||
|
.nf
|
||||||
|
% title
|
||||||
|
% author(s)
|
||||||
|
% date
|
||||||
|
.fi
|
||||||
|
which will be made available to the
|
||||||
|
.Fn mkd_doc_title ,
|
||||||
|
.Fn mkd_doc_author ,
|
||||||
|
and
|
||||||
|
.Fn mkd_doc_date
|
||||||
|
functions.
|
||||||
|
.Ss Definition lists
|
||||||
|
A definition list item
|
||||||
|
is defined as
|
||||||
|
.nf
|
||||||
|
=tag=
|
||||||
|
description
|
||||||
|
.fi
|
||||||
|
(that is a
|
||||||
|
.Ar = ,
|
||||||
|
followed by text, another
|
||||||
|
.Ar = ,
|
||||||
|
a newline, 4 spaces of intent, and then more text.)
|
||||||
|
.Pp
|
||||||
|
Alternatively, definition list items are defined as
|
||||||
|
.nf
|
||||||
|
tag
|
||||||
|
: description
|
||||||
|
.fi
|
||||||
|
(This is the format that
|
||||||
|
.Ar "PHP Markdown Extra"
|
||||||
|
uses.)
|
||||||
|
.Pp
|
||||||
|
.Ss embedded stylesheets
|
||||||
|
Stylesheets may be defined and modified in a
|
||||||
|
.Em <style>
|
||||||
|
block. A style block is parsed like any other
|
||||||
|
block level html;
|
||||||
|
.Em <style>
|
||||||
|
starting on column 1, raw html (or, in this case, css) following
|
||||||
|
it, and either ending with a
|
||||||
|
.Em </style>
|
||||||
|
at the end of the line or a
|
||||||
|
.Em </style>
|
||||||
|
at the beginning of a subsequent line.
|
||||||
|
.Pp
|
||||||
|
Be warned that style blocks work like footnote links -- no matter
|
||||||
|
where you define them they are valid for the entire document.
|
||||||
|
.Ss alpha lists
|
||||||
|
Alphabetic lists (like regular numeric lists, but with alphabetic
|
||||||
|
items) are supported. So:
|
||||||
|
.nf
|
||||||
|
a. this
|
||||||
|
b. is
|
||||||
|
c. an alphabetic
|
||||||
|
d. list
|
||||||
|
.fi
|
||||||
|
will produce:
|
||||||
|
.nf
|
||||||
|
<ol type=a>
|
||||||
|
<li>this</li>
|
||||||
|
<li>is</li>
|
||||||
|
<li>an alphabetic</li>
|
||||||
|
<li>list</li>
|
||||||
|
</ol>
|
||||||
|
.fi
|
||||||
|
.Ss tables
|
||||||
|
.Ar "PHP Markdown Extra"
|
||||||
|
tables are supported; input of the form
|
||||||
|
.nf
|
||||||
|
header|header
|
||||||
|
------|------
|
||||||
|
text | text
|
||||||
|
.fi
|
||||||
|
will produce:
|
||||||
|
.nf
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>header</th>
|
||||||
|
<th>header</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>text</td>
|
||||||
|
<td>text</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
.fi
|
||||||
|
The dashed line can also contain
|
||||||
|
.Em :
|
||||||
|
characters for formatting; if a
|
||||||
|
.Em :
|
||||||
|
is at the start of a column, it tells
|
||||||
|
.Nm discount
|
||||||
|
to align the cell contents to the left; if it's at the end, it
|
||||||
|
aligns right, and if there's one at the start and at the
|
||||||
|
end, it centers.
|
||||||
|
.Ss strikethrough
|
||||||
|
A strikethrough syntax is supported in much the same way that
|
||||||
|
.Ar `
|
||||||
|
is used to define a section of code. If you enclose text with
|
||||||
|
two or more tildes, such as
|
||||||
|
.Em ~~erased text~~
|
||||||
|
it will be written as
|
||||||
|
.Em "<del>erased text</del>" .
|
||||||
|
Like code sections, you may use as many
|
||||||
|
.Ar ~
|
||||||
|
as you want, but there must be as many starting tildes as closing
|
||||||
|
tildes.
|
||||||
|
.Ss markdown extra-style footnotes
|
||||||
|
.Ar "PHP Markdown Extra"
|
||||||
|
footnotes are supported. If a footnote link begins with a
|
||||||
|
.Ar ^ ,
|
||||||
|
the first use of that footnote will generate a link down to the
|
||||||
|
bottom of the rendered document, which will contain a numbered footnote
|
||||||
|
with a link back to where the footnote was called.
|
||||||
|
.Sh AUTHOR
|
||||||
|
Jessica L. Parsons
|
||||||
|
.%T http://www.pell.portland.or.us/~orc/
|
||||||
|
.Sh SEE ALSO
|
||||||
|
.Xr markdown 1 ,
|
||||||
|
.Xr markdown 3 ,
|
||||||
|
.Xr mkd-callbacks 3 ,
|
||||||
|
.Xr mkd-functions 3 ,
|
||||||
|
.Xr mkd-line 3 .
|
||||||
|
.Pp
|
||||||
|
.%T http://daringfireball.net/projects/markdown
|
||||||
|
.Pp
|
||||||
|
.%T http://michelf.com/projects/php-markdown
|
||||||
186
mkd-functions.3
Normal file
186
mkd-functions.3
Normal file
@ -0,0 +1,186 @@
|
|||||||
|
.\"
|
||||||
|
.Dd January 18, 2008
|
||||||
|
.Dt MKD_FUNCTIONS 3
|
||||||
|
.Os Mastodon
|
||||||
|
.Sh NAME
|
||||||
|
.Nm mkd_functions
|
||||||
|
.Nd access and process Markdown documents.
|
||||||
|
.Sh LIBRARY
|
||||||
|
Markdown
|
||||||
|
.Pq libmarkdown , -lmarkdown
|
||||||
|
.Sh SYNOPSIS
|
||||||
|
.Fd #include <mkdio.h>
|
||||||
|
.Ft int
|
||||||
|
.Fn mkd_compile "MMIOT *document" "mkd_flag_t *flags"
|
||||||
|
.Ft int
|
||||||
|
.Fn mkd_css "MMIOT *document" "char **doc"
|
||||||
|
.Ft int
|
||||||
|
.Fn mkd_generatecss "MMIOT *document" "FILE *output"
|
||||||
|
.Ft int
|
||||||
|
.Fn mkd_document "MMIOT *document" "char **doc"
|
||||||
|
.Ft int
|
||||||
|
.Fn mkd_generatehtml "MMIOT *document" "FILE *output"
|
||||||
|
.Ft int
|
||||||
|
.Fn mkd_xhtmlpage "MMIOT *document" "mkd_flag_t *flags" "FILE *output"
|
||||||
|
.Ft int
|
||||||
|
.Fn mkd_toc "MMIOT *document" "char **doc"
|
||||||
|
.Ft void
|
||||||
|
.Fn mkd_generatetoc "MMIOT *document" "FILE *output"
|
||||||
|
.Ft void
|
||||||
|
.Fn mkd_cleanup "MMIOT*"
|
||||||
|
.Ft char*
|
||||||
|
.Fn mkd_doc_title "MMIOT*"
|
||||||
|
.Ft char*
|
||||||
|
.Fn mkd_doc_author "MMIOT*"
|
||||||
|
.Ft char*
|
||||||
|
.Fn mkd_doc_date "MMIOT*"
|
||||||
|
.Sh DESCRIPTION
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Nm markdown
|
||||||
|
format supported in this implementation includes
|
||||||
|
Pandoc-style header and inline
|
||||||
|
.Ar \<style\>
|
||||||
|
blocks, and the standard
|
||||||
|
.Xr markdown 3
|
||||||
|
functions do not provide access to
|
||||||
|
the data provided by either of those extensions.
|
||||||
|
These functions give you access to that data, plus
|
||||||
|
they provide a finer-grained way of converting
|
||||||
|
.Em Markdown
|
||||||
|
documents into HTML.
|
||||||
|
.Pp
|
||||||
|
Given a
|
||||||
|
.Ar MMIOT*
|
||||||
|
generated by
|
||||||
|
.Fn mkd_in
|
||||||
|
or
|
||||||
|
.Fn mkd_string ,
|
||||||
|
.Fn mkd_compile
|
||||||
|
compiles the document into
|
||||||
|
.Em \<style\> ,
|
||||||
|
.Em Pandoc ,
|
||||||
|
and
|
||||||
|
.Em html
|
||||||
|
sections.
|
||||||
|
.Pp
|
||||||
|
Once compiled, the document can be examined and written
|
||||||
|
by the
|
||||||
|
.Fn mkd_css ,
|
||||||
|
.Fn mkd_document ,
|
||||||
|
.Fn mkd_generatecss ,
|
||||||
|
.Fn mkd_generatehtml ,
|
||||||
|
.Fn mkd_generatetoc ,
|
||||||
|
.Fn mkd_toc ,
|
||||||
|
.Fn mkd_xhtmlpage ,
|
||||||
|
.Fn mkd_doc_title ,
|
||||||
|
.Fn mkd_doc_author ,
|
||||||
|
and
|
||||||
|
.Fn mkd_doc_date
|
||||||
|
functions.
|
||||||
|
.Pp
|
||||||
|
.Fn mkd_css
|
||||||
|
allocates a string and populates it with any \<style\> sections
|
||||||
|
provided in the document,
|
||||||
|
.Fn mkd_generatecss
|
||||||
|
writes any \<style\> sections to the output,
|
||||||
|
.Fn mkd_document
|
||||||
|
points
|
||||||
|
.Ar text
|
||||||
|
to the text of the document and returns the
|
||||||
|
size of the document,
|
||||||
|
.Fn mkd_generatehtml
|
||||||
|
writes the rest of the document to the output,
|
||||||
|
and
|
||||||
|
.Fn mkd_doc_title ,
|
||||||
|
.Fn mkd_doc_author ,
|
||||||
|
.Fn mkd_doc_date
|
||||||
|
are used to read the contents of a Pandoc header,
|
||||||
|
if any.
|
||||||
|
.Pp
|
||||||
|
.Fn mkd_xhtmlpage
|
||||||
|
writes a xhtml page containing the document. The regular set of
|
||||||
|
flags can be passed.
|
||||||
|
.Pp
|
||||||
|
.Fn mkd_toc
|
||||||
|
writes a document outline, in the form of a collection of nested
|
||||||
|
lists with links to each header in the document, into a string
|
||||||
|
allocated with
|
||||||
|
.Fn malloc ,
|
||||||
|
and returns the size.
|
||||||
|
.Pp
|
||||||
|
.Fn mkd_generatetoc
|
||||||
|
is like
|
||||||
|
.Fn mkd_toc ,
|
||||||
|
except that it writes the document outline to the given
|
||||||
|
.Pa FILE*
|
||||||
|
argument.
|
||||||
|
.Pp
|
||||||
|
.Fn mkd_cleanup
|
||||||
|
deletes a
|
||||||
|
.Ar MMIOT*
|
||||||
|
after processing is done.
|
||||||
|
.Pp
|
||||||
|
.Fn mkd_compile
|
||||||
|
accepts the same flags that
|
||||||
|
.Fn markdown
|
||||||
|
and
|
||||||
|
.Fn mkd_string
|
||||||
|
do;
|
||||||
|
.Bl -tag -width MKD_NOSTRIKETHROUGH -compact
|
||||||
|
.It Ar MKD_NOIMAGE
|
||||||
|
Do not process `![]' and
|
||||||
|
remove
|
||||||
|
.Em \<img\>
|
||||||
|
tags from the output.
|
||||||
|
.It Ar MKD_NOLINKS
|
||||||
|
Do not process `[]' and remove
|
||||||
|
.Em \<a\>
|
||||||
|
tags from the output.
|
||||||
|
.It Ar MKD_NOPANTS
|
||||||
|
Do not do Smartypants-style mangling of quotes, dashes, or ellipses.
|
||||||
|
.It Ar MKD_TAGTEXT
|
||||||
|
Process the input as if you were inside a html tag. This means that
|
||||||
|
no html tags will be generated, and
|
||||||
|
.Fn mkd_compile
|
||||||
|
will attempt to escape anything that might terribly confuse a
|
||||||
|
web browser.
|
||||||
|
.It Ar MKD_NO_EXT
|
||||||
|
Do not process any markdown pseudo-protocols when
|
||||||
|
handing
|
||||||
|
.Ar [][]
|
||||||
|
links.
|
||||||
|
.It Ar MKD_NOHEADER
|
||||||
|
Do not attempt to parse any Pandoc-style headers.
|
||||||
|
.It Ar MKD_TOC
|
||||||
|
Label all headers for use with the
|
||||||
|
.Fn mkd_generatetoc
|
||||||
|
function.
|
||||||
|
.It Ar MKD_1_COMPAT
|
||||||
|
MarkdownTest_1.0 compatibility flag; trim trailing spaces from the
|
||||||
|
first line of code blocks and disable implicit reference links.
|
||||||
|
.It Ar MKD_NOSTRIKETHROUGH
|
||||||
|
Disable strikethrough support.
|
||||||
|
.El
|
||||||
|
.Sh RETURN VALUES
|
||||||
|
The function
|
||||||
|
.Fn mkd_compile
|
||||||
|
returns 1 in the case of success, or 0 if the document is already compiled.
|
||||||
|
The function
|
||||||
|
.Fn mkd_generatecss
|
||||||
|
returns the number of bytes written in the case of success, or EOF if an error
|
||||||
|
occurred.
|
||||||
|
The function
|
||||||
|
.Fn mkd_generatehtml
|
||||||
|
returns 0 on success, \-1 on failure.
|
||||||
|
.Sh SEE ALSO
|
||||||
|
.Xr markdown 1 ,
|
||||||
|
.Xr markdown 3 ,
|
||||||
|
.Xr mkd-line 3 ,
|
||||||
|
.Xr markdown 7 ,
|
||||||
|
.Xr mkd-extensions 7 ,
|
||||||
|
.Xr mmap 2 .
|
||||||
|
.Pp
|
||||||
|
http://daringfireball.net/projects/markdown/syntax
|
||||||
|
.Sh BUGS
|
||||||
|
Error handling is minimal at best.
|
||||||
41
mkd-line.3
Normal file
41
mkd-line.3
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
.\"
|
||||||
|
.Dd January 18, 2008
|
||||||
|
.Dt MKD_LINE 3
|
||||||
|
.Os Mastodon
|
||||||
|
.Sh NAME
|
||||||
|
.Nm mkd_line
|
||||||
|
.Nd do Markdown translation of small items
|
||||||
|
.Sh LIBRARY
|
||||||
|
Markdown
|
||||||
|
.Pq libmarkdown , -lmarkdown
|
||||||
|
.Sh SYNOPSIS
|
||||||
|
.Fd #include <mkdio.h>
|
||||||
|
.Ft int
|
||||||
|
.Fn mkd_line "char *string" "int size" "char **doc" "mkd_flag_t *flags"
|
||||||
|
.Ft int
|
||||||
|
.Fn mkd_generateline "char *string" "int size" "FILE *output" "mkd_flag_t *flags"
|
||||||
|
.Sh DESCRIPTION
|
||||||
|
.Pp
|
||||||
|
Occasionally one might want to do markdown translations on fragments of
|
||||||
|
data, like the title of an weblog article, a date, or a simple signature
|
||||||
|
line.
|
||||||
|
.Nm mkd_line
|
||||||
|
and
|
||||||
|
.Nm mkd_generateline
|
||||||
|
allow you to do markdown translations on small blocks of text.
|
||||||
|
.Nm mkd_line
|
||||||
|
allocates a buffer, then writes the translated text into that buffer,
|
||||||
|
and
|
||||||
|
.Nm mkd_generateline
|
||||||
|
writes the output to the specified
|
||||||
|
.Ar FILE* .
|
||||||
|
.Sh SEE ALSO
|
||||||
|
.Xr markdown 1 ,
|
||||||
|
.Xr markdown 3 ,
|
||||||
|
.Xr markdown 7 ,
|
||||||
|
.Xr mkd-extensions 7 ,
|
||||||
|
.Xr mmap 2 .
|
||||||
|
.Pp
|
||||||
|
http://daringfireball.net/projects/markdown/syntax
|
||||||
|
.Sh BUGS
|
||||||
|
Error handling is minimal at best.
|
||||||
52
mkd2html.1
Normal file
52
mkd2html.1
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
.\" %A%
|
||||||
|
.\"
|
||||||
|
.Dd January 10, 2010
|
||||||
|
.Dt MKD2HTML 1
|
||||||
|
.Os MASTODON
|
||||||
|
.Sh NAME
|
||||||
|
.Nm mkd2html
|
||||||
|
.Nd markdown to html converter
|
||||||
|
.Sh SYNOPSIS
|
||||||
|
.Nm
|
||||||
|
.Op Fl css Pa file
|
||||||
|
.Op Fl header Pa string
|
||||||
|
.Op Fl footer Pa string
|
||||||
|
.Op Pa file
|
||||||
|
.Sh DESCRIPTION
|
||||||
|
.Nm
|
||||||
|
utility parses a
|
||||||
|
.Xr markdown 7 Ns -formatted
|
||||||
|
.Pa textfile
|
||||||
|
.Pq or stdin if not specified,
|
||||||
|
and generates a web page. It
|
||||||
|
reads
|
||||||
|
.Ar file
|
||||||
|
or
|
||||||
|
.Ar file.text
|
||||||
|
and writes the result in
|
||||||
|
.Ar file.html
|
||||||
|
.Pq where file is the passed argument.
|
||||||
|
.Pp
|
||||||
|
.Nm
|
||||||
|
is part of discount.
|
||||||
|
.Sh OPTIONS
|
||||||
|
.Bl -tag -width "-header string"
|
||||||
|
.It Fl css Ar file
|
||||||
|
Specifies a CSS file.
|
||||||
|
.It Fl header Ar string
|
||||||
|
Specifies a line to add to the <header> tag.
|
||||||
|
.It Fl footer Ar string
|
||||||
|
Specifies a line to add before the <\/body> tag.
|
||||||
|
.El
|
||||||
|
.Sh RETURN VALUES
|
||||||
|
The
|
||||||
|
.Nm
|
||||||
|
utility exits 0 on success, and >0 if an error occurs.
|
||||||
|
.Sh SEE ALSO
|
||||||
|
.Xr markdown 1 ,
|
||||||
|
.Xr markdown 3 ,
|
||||||
|
.Xr markdown 7 ,
|
||||||
|
.Xr mkd-extensions 7 .
|
||||||
|
.Sh AUTHOR
|
||||||
|
.An Jessica L. Parsons
|
||||||
|
.Pq Li orc@pell.portland.or.us
|
||||||
235
mkd2html.c
Normal file
235
mkd2html.c
Normal file
@ -0,0 +1,235 @@
|
|||||||
|
/*
|
||||||
|
* mkd2html: parse a markdown input file and generate a web page.
|
||||||
|
*
|
||||||
|
* usage: mkd2html [options] filename
|
||||||
|
* or mkd2html [options] < markdown > html
|
||||||
|
*
|
||||||
|
* options
|
||||||
|
* -css css-file
|
||||||
|
* -header line-to-add-to-<HEADER>
|
||||||
|
* -footer line-to-add-before-</BODY>
|
||||||
|
*
|
||||||
|
* example:
|
||||||
|
*
|
||||||
|
* mkd2html -css /~orc/pages.css syntax
|
||||||
|
* ( read syntax OR syntax.text, write syntax.html )
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2007 Jessica L Parsons.
|
||||||
|
* The redistribution terms are provided in the COPYRIGHT file that must
|
||||||
|
* be distributed with this source code.
|
||||||
|
*/
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#ifdef HAVE_BASENAME
|
||||||
|
# ifdef HAVE_LIBGEN_H
|
||||||
|
# include <libgen.h>
|
||||||
|
# else
|
||||||
|
# include <unistd.h>
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
#include "mkdio.h"
|
||||||
|
#include "cstring.h"
|
||||||
|
#include "amalloc.h"
|
||||||
|
|
||||||
|
#include "gethopt.h"
|
||||||
|
|
||||||
|
char *pgm = "mkd2html";
|
||||||
|
|
||||||
|
extern int notspecial(char *filename);
|
||||||
|
|
||||||
|
#ifndef HAVE_BASENAME
|
||||||
|
char *
|
||||||
|
basename(char *path)
|
||||||
|
{
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
if ( p = strrchr(path, '/') )
|
||||||
|
return 1+p;
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void
|
||||||
|
fail(char *why, ...)
|
||||||
|
{
|
||||||
|
va_list ptr;
|
||||||
|
|
||||||
|
va_start(ptr,why);
|
||||||
|
fprintf(stderr, "%s: ", pgm);
|
||||||
|
vfprintf(stderr, why, ptr);
|
||||||
|
fputc('\n', stderr);
|
||||||
|
va_end(ptr);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
enum { GFM, ADD_CSS, ADD_HEADER, ADD_FOOTER };
|
||||||
|
|
||||||
|
struct h_opt opts[] = {
|
||||||
|
{ GFM, "gfm",'G', 0, "Github style markdown" },
|
||||||
|
{ ADD_CSS, "css", 0, "url", "Additional css for this page" },
|
||||||
|
{ ADD_HEADER, "header", 0, "header", "Additional headers for this page" },
|
||||||
|
{ ADD_FOOTER, "footer", 0, "footer", "Additional footers for this page" },
|
||||||
|
};
|
||||||
|
#define NROPTS (sizeof opts/sizeof opts[0])
|
||||||
|
|
||||||
|
#if USE_H1TITLE
|
||||||
|
extern char* mkd_h1_title(MMIOT *);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
char *h;
|
||||||
|
char *source = 0, *dest = 0;
|
||||||
|
MMIOT *mmiot;
|
||||||
|
int i;
|
||||||
|
int gfm = 0;
|
||||||
|
FILE *input, *output;
|
||||||
|
STRING(char*) css, headers, footers;
|
||||||
|
struct h_opt *res;
|
||||||
|
struct h_context flags;
|
||||||
|
|
||||||
|
|
||||||
|
CREATE(css);
|
||||||
|
CREATE(headers);
|
||||||
|
CREATE(footers);
|
||||||
|
pgm = basename(argv[0]);
|
||||||
|
|
||||||
|
hoptset(&flags, argc, argv);
|
||||||
|
hopterr(&flags, 1);
|
||||||
|
while ( res = gethopt(&flags, opts, NROPTS) ) {
|
||||||
|
if ( res == HOPTERR ) {
|
||||||
|
hoptusage(pgm, opts, NROPTS, "source [dest]");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ( res->option ) {
|
||||||
|
case ADD_CSS:
|
||||||
|
EXPAND(css) = hoptarg(&flags);
|
||||||
|
break;
|
||||||
|
case ADD_HEADER:
|
||||||
|
EXPAND(headers) = hoptarg(&flags);
|
||||||
|
break;
|
||||||
|
case ADD_FOOTER:
|
||||||
|
EXPAND(footers) = hoptarg(&flags);
|
||||||
|
break;
|
||||||
|
case GFM:
|
||||||
|
gfm = 1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fprintf(stderr, "unknown option?\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
argc -= hoptind(&flags);
|
||||||
|
argv += hoptind(&flags);
|
||||||
|
|
||||||
|
switch ( argc ) {
|
||||||
|
char *p, *dot;
|
||||||
|
case 0:
|
||||||
|
input = stdin;
|
||||||
|
output = stdout;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
case 2:
|
||||||
|
dest = malloc(strlen(argv[argc-1]) + 6);
|
||||||
|
source = malloc(strlen(argv[0]) + 6);
|
||||||
|
|
||||||
|
if ( !(source && dest) )
|
||||||
|
fail("out of memory allocating name buffers");
|
||||||
|
|
||||||
|
strcpy(source, argv[0]);
|
||||||
|
strcpy(dest, argv[argc-1]);
|
||||||
|
if (( p = strrchr(source, '/') ))
|
||||||
|
p = source;
|
||||||
|
else
|
||||||
|
++p;
|
||||||
|
|
||||||
|
if ( (input = fopen(source, "r")) == 0 ) {
|
||||||
|
strcat(source, ".text");
|
||||||
|
if ( (input = fopen(source, "r")) == 0 )
|
||||||
|
fail("can't open either %s or %s", argv[0], source);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( notspecial(dest) ) {
|
||||||
|
if (( dot = strrchr(dest, '.') ))
|
||||||
|
*dot = 0;
|
||||||
|
strcat(dest, ".html");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( (output = fopen(dest, "w")) == 0 )
|
||||||
|
fail("can't write to %s", dest);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
hoptusage(pgm, opts, NROPTS, "source [dest]");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
mmiot = gfm ? gfm_in(input, 0) : mkd_in(input, 0);
|
||||||
|
|
||||||
|
if ( mmiot == 0 )
|
||||||
|
fail("can't read %s", source ? source : "stdin");
|
||||||
|
|
||||||
|
if ( !mkd_compile(mmiot, 0) )
|
||||||
|
fail("couldn't compile input");
|
||||||
|
|
||||||
|
|
||||||
|
h = mkd_doc_title(mmiot);
|
||||||
|
#if USE_H1TITLE
|
||||||
|
if ( ! h )
|
||||||
|
h = mkd_h1_title(mmiot);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* print a header */
|
||||||
|
|
||||||
|
fprintf(output,
|
||||||
|
"<!doctype html>\n"
|
||||||
|
"<html>\n"
|
||||||
|
"<head>\n"
|
||||||
|
" <meta name=\"GENERATOR\" content=\"mkd2html %s\">\n", markdown_version);
|
||||||
|
|
||||||
|
fprintf(output," <meta http-equiv=\"Content-Type\""
|
||||||
|
" content=\"text/html; charset=utf-8\">\n");
|
||||||
|
|
||||||
|
for ( i=0; i < S(css); i++ )
|
||||||
|
fprintf(output, " <link rel=\"stylesheet\"\n"
|
||||||
|
" type=\"text/css\"\n"
|
||||||
|
" href=\"%s\" />\n", T(css)[i]);
|
||||||
|
|
||||||
|
fprintf(output," <title>");
|
||||||
|
if ( h )
|
||||||
|
mkd_generateline(h, strlen(h), output, 0);
|
||||||
|
/* xhtml requires a <title> in the header, even if it doesn't
|
||||||
|
* contain anything
|
||||||
|
*/
|
||||||
|
fprintf(output, "</title>\n");
|
||||||
|
|
||||||
|
for ( i=0; i < S(headers); i++ )
|
||||||
|
fprintf(output, " %s\n", T(headers)[i]);
|
||||||
|
fprintf(output, "</head>\n"
|
||||||
|
"<body>\n");
|
||||||
|
|
||||||
|
/* print the compiled body */
|
||||||
|
|
||||||
|
mkd_generatehtml(mmiot, output);
|
||||||
|
|
||||||
|
for ( i=0; i < S(footers); i++ )
|
||||||
|
fprintf(output, "%s\n", T(footers)[i]);
|
||||||
|
|
||||||
|
fprintf(output, "</body>\n"
|
||||||
|
"</html>\n");
|
||||||
|
|
||||||
|
mkd_cleanup(mmiot);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
527
mkdio.c
Normal file
527
mkdio.c
Normal file
@ -0,0 +1,527 @@
|
|||||||
|
/*
|
||||||
|
* mkdio -- markdown front end input functions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007 Jessica L Parsons.
|
||||||
|
* The redistribution terms are provided in the COPYRIGHT file that must
|
||||||
|
* be distributed with this source code.
|
||||||
|
*/
|
||||||
|
#include "config.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
#include "cstring.h"
|
||||||
|
#include "markdown.h"
|
||||||
|
#include "amalloc.h"
|
||||||
|
#include "tags.h"
|
||||||
|
|
||||||
|
typedef ANCHOR(Line) LineAnchor;
|
||||||
|
|
||||||
|
|
||||||
|
/* create a new blank Document
|
||||||
|
*/
|
||||||
|
Document*
|
||||||
|
__mkd_new_Document(void)
|
||||||
|
{
|
||||||
|
Document *ret = calloc(sizeof(Document), 1);
|
||||||
|
|
||||||
|
if ( ret ) {
|
||||||
|
if ( ret->ctx = calloc(sizeof(MMIOT), 1) ) {
|
||||||
|
ret->magic = VALID_DOCUMENT;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
free(ret);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* add a line to the markdown input chain, expanding tabs and
|
||||||
|
* noting the presence of special characters as we go.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
__mkd_enqueue(Document* a, Cstring *line)
|
||||||
|
{
|
||||||
|
Line *p = calloc(sizeof *p, 1);
|
||||||
|
unsigned char c;
|
||||||
|
int xp = 0;
|
||||||
|
int size = S(*line);
|
||||||
|
unsigned char *str = (unsigned char*)T(*line);
|
||||||
|
|
||||||
|
CREATE(p->text);
|
||||||
|
ATTACH(a->content, p);
|
||||||
|
|
||||||
|
while ( size-- ) {
|
||||||
|
if ( (c = *str++) == '\t' ) {
|
||||||
|
/* expand tabs into ->tabstop spaces. We use ->tabstop
|
||||||
|
* because the ENTIRE FREAKING COMPUTER WORLD uses editors
|
||||||
|
* that don't do ^T/^D, but instead use tabs for indentation,
|
||||||
|
* and, of course, set their tabs down to 4 spaces
|
||||||
|
*/
|
||||||
|
do {
|
||||||
|
EXPAND(p->text) = ' ';
|
||||||
|
} while ( ++xp % a->tabstop );
|
||||||
|
}
|
||||||
|
else if ( c >= ' ' ) {
|
||||||
|
if ( c == '|' )
|
||||||
|
p->has_pipechar = 1;
|
||||||
|
EXPAND(p->text) = c;
|
||||||
|
++xp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
COMPLETE(p->text);
|
||||||
|
p->dle = mkd_firstnonblank(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* trim leading characters from a line, then adjust the dle.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
__mkd_trim_line(Line *p, int clip)
|
||||||
|
{
|
||||||
|
if ( clip >= S(p->text) ) {
|
||||||
|
S(p->text) = p->dle = 0;
|
||||||
|
T(p->text)[0] = 0;
|
||||||
|
}
|
||||||
|
else if ( clip > 0 ) {
|
||||||
|
CLIP(p->text, 0, clip);
|
||||||
|
p->dle = mkd_firstnonblank(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* build a Document from any old input.
|
||||||
|
*/
|
||||||
|
typedef int (*getc_func)(void*);
|
||||||
|
|
||||||
|
Document *
|
||||||
|
populate(getc_func getc, void* ctx, mkd_flag_t *flags)
|
||||||
|
{
|
||||||
|
Cstring line;
|
||||||
|
Document *a = __mkd_new_Document();
|
||||||
|
int c;
|
||||||
|
int pandoc = 0;
|
||||||
|
|
||||||
|
if ( flags && (is_flag_set(flags, MKD_NOHEADER) || is_flag_set(flags, MKD_STRICT)) )
|
||||||
|
pandoc= EOF;
|
||||||
|
|
||||||
|
if ( !a ) return 0;
|
||||||
|
|
||||||
|
|
||||||
|
if ( flags && (is_flag_set(flags, MKD_TABSTOP) || is_flag_set(flags, MKD_STRICT)) )
|
||||||
|
a->tabstop = 4;
|
||||||
|
else
|
||||||
|
a->tabstop = TABSTOP;
|
||||||
|
|
||||||
|
CREATE(line);
|
||||||
|
|
||||||
|
while ( (c = (*getc)(ctx)) != EOF ) {
|
||||||
|
if ( c == '\n' ) {
|
||||||
|
if ( pandoc != EOF && pandoc < 3 ) {
|
||||||
|
if ( S(line) && (T(line)[0] == '%') )
|
||||||
|
pandoc++;
|
||||||
|
else
|
||||||
|
pandoc = EOF;
|
||||||
|
}
|
||||||
|
__mkd_enqueue(a, &line);
|
||||||
|
S(line) = 0;
|
||||||
|
}
|
||||||
|
else if ( (c & 0x80) || isprint(c) || isspace(c) )
|
||||||
|
EXPAND(line) = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( S(line) )
|
||||||
|
__mkd_enqueue(a, &line);
|
||||||
|
|
||||||
|
DELETE(line);
|
||||||
|
|
||||||
|
if ( pandoc == 3 ) {
|
||||||
|
/* the first three lines started with %, so we have a header.
|
||||||
|
* clip the first three lines out of content and hang them
|
||||||
|
* off header.
|
||||||
|
*/
|
||||||
|
Line *headers = T(a->content);
|
||||||
|
|
||||||
|
a->title = headers; __mkd_trim_line(a->title, 1);
|
||||||
|
a->author= headers->next; __mkd_trim_line(a->author, 1);
|
||||||
|
a->date = headers->next->next; __mkd_trim_line(a->date, 1);
|
||||||
|
|
||||||
|
T(a->content) = headers->next->next->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* convert a file into a linked list
|
||||||
|
*/
|
||||||
|
Document *
|
||||||
|
mkd_in(FILE *f, mkd_flag_t *flags)
|
||||||
|
{
|
||||||
|
return populate((getc_func)fgetc, f, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* return a single character out of a buffer
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
__mkd_io_strget(struct string_stream *in)
|
||||||
|
{
|
||||||
|
if ( in->size > 0 ) {
|
||||||
|
--(in->size);
|
||||||
|
return *(in->data)++;
|
||||||
|
}
|
||||||
|
return EOF;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* convert a block of text into a linked list
|
||||||
|
*/
|
||||||
|
Document *
|
||||||
|
mkd_string(const char *buf, int len, mkd_flag_t* flags)
|
||||||
|
{
|
||||||
|
struct string_stream about;
|
||||||
|
|
||||||
|
about.data = buf;
|
||||||
|
about.size = len;
|
||||||
|
|
||||||
|
return populate((getc_func)__mkd_io_strget, &about, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* write the html to a file (xmlified if necessary)
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
mkd_generatehtml(Document *p, FILE *output)
|
||||||
|
{
|
||||||
|
char *doc;
|
||||||
|
int szdoc;
|
||||||
|
|
||||||
|
DO_OR_DIE( szdoc = mkd_document(p,&doc) );
|
||||||
|
if ( is_flag_set( &(p->ctx->flags), MKD_CDATA ) )
|
||||||
|
DO_OR_DIE( mkd_generatexml(doc, szdoc, output) );
|
||||||
|
else if ( fwrite(doc, szdoc, 1, output) != 1 )
|
||||||
|
return EOF;
|
||||||
|
DO_OR_DIE( putc('\n', output) );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* convert some markdown text to html
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
markdown(Document *document, FILE *out, mkd_flag_t* flags)
|
||||||
|
{
|
||||||
|
if ( mkd_compile(document, flags) ) {
|
||||||
|
mkd_generatehtml(document, out);
|
||||||
|
mkd_cleanup(document);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* anchor_format a string, returning the formatted string in malloc()ed space
|
||||||
|
* MKD_URLENCODEDANCHOR is now perverted to being a html5 anchor
|
||||||
|
*
|
||||||
|
* !labelformat: print all characters
|
||||||
|
* labelformat && h4anchor: prefix nonalpha label with L,
|
||||||
|
* expand all nonalnum, _, ':', '.' to hex
|
||||||
|
* except space which maps to -
|
||||||
|
* labelformat && !h4anchor:expand space to -, other isspace() & '%' to hex
|
||||||
|
*/
|
||||||
|
static char *
|
||||||
|
mkd_anchor_format(char *s, int len, int labelformat, mkd_flag_t *flags)
|
||||||
|
{
|
||||||
|
char *res;
|
||||||
|
unsigned char c;
|
||||||
|
int i, needed, out = 0;
|
||||||
|
int h4anchor = !is_flag_set(flags, MKD_URLENCODEDANCHOR);
|
||||||
|
static const unsigned char hexchars[] = "0123456789abcdef";
|
||||||
|
|
||||||
|
needed = (labelformat ? (4*len) : len) + 2; /* +2 for L & \0 */
|
||||||
|
|
||||||
|
if ( (res = malloc(needed)) == NULL )
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if ( h4anchor && labelformat && !isalpha(s[0]) )
|
||||||
|
res[out++] = 'L';
|
||||||
|
|
||||||
|
|
||||||
|
for ( i=0; i < len ; i++ ) {
|
||||||
|
c = s[i];
|
||||||
|
if ( labelformat ) {
|
||||||
|
if ( h4anchor
|
||||||
|
? (isalnum(c) || (c == '_') || (c == ':') || (c == '.' ) )
|
||||||
|
: !(isspace(c) || c == '%') )
|
||||||
|
res[out++] = c;
|
||||||
|
else if ( c == ' ' )
|
||||||
|
res[out++] = '-';
|
||||||
|
else {
|
||||||
|
res[out++] = h4anchor ? '-' : '%';
|
||||||
|
res[out++] = hexchars[c >> 4 & 0xf];
|
||||||
|
res[out++] = hexchars[c & 0xf];
|
||||||
|
if ( h4anchor )
|
||||||
|
res[out++] = '-';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
res[out++] = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
res[out++] = 0;
|
||||||
|
return res;
|
||||||
|
} /* mkd_anchor_format */
|
||||||
|
|
||||||
|
|
||||||
|
/* write out a Cstring, mangled into a form suitable for `<a href=` or `<a id=`
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
mkd_string_to_anchor(char *s, int len, mkd_sta_function_t outchar,
|
||||||
|
void *out, int labelformat,
|
||||||
|
MMIOT *f)
|
||||||
|
{
|
||||||
|
char *res;
|
||||||
|
char *line;
|
||||||
|
int size;
|
||||||
|
mkd_flag_t flags;
|
||||||
|
|
||||||
|
int i;
|
||||||
|
|
||||||
|
mkd_init_flags(&flags);
|
||||||
|
set_mkd_flag(&flags,IS_LABEL);
|
||||||
|
size = mkd_line(s, len, &line, &flags);
|
||||||
|
|
||||||
|
if ( !line )
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ( f->cb->e_anchor.func )
|
||||||
|
res = (*(f->cb->e_anchor.func))(line, size, f->cb->e_anchor.data);
|
||||||
|
else
|
||||||
|
res = mkd_anchor_format(line, size, labelformat, &(f->flags));
|
||||||
|
|
||||||
|
free(line);
|
||||||
|
|
||||||
|
if ( res ) {
|
||||||
|
for ( i=0; res[i]; i++ )
|
||||||
|
(*outchar)(res[i], out);
|
||||||
|
|
||||||
|
if ( f->cb->e_anchor.free )
|
||||||
|
(*f->cb->e_anchor.free)(res, i, f);
|
||||||
|
else
|
||||||
|
free(res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ___mkd_reparse() a line
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
mkd_parse_line(char *bfr, int size, MMIOT *f, mkd_flag_t *flags)
|
||||||
|
{
|
||||||
|
___mkd_initmmiot(f, 0, flags);
|
||||||
|
___mkd_reparse(bfr, size, NULL, f, 0);
|
||||||
|
___mkd_emblock(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ___mkd_reparse() a line, returning it in malloc()ed memory
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
mkd_line(char *bfr, int size, char **res, mkd_flag_t* flags)
|
||||||
|
{
|
||||||
|
MMIOT f;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
mkd_parse_line(bfr, size, &f, flags);
|
||||||
|
|
||||||
|
if ( len = S(f.out) ) {
|
||||||
|
COMPLETE(f.out);
|
||||||
|
/* strdup() doesn't use amalloc(), so in an amalloc()ed
|
||||||
|
* build this copies the string safely out of our memory
|
||||||
|
* paranoia arena. In a non-amalloc world, it's a spurious
|
||||||
|
* memory allocation, but it avoids unintentional hilarity
|
||||||
|
* with amalloc()
|
||||||
|
*/
|
||||||
|
*res = strdup(T(f.out));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
*res = 0;
|
||||||
|
len = EOF;
|
||||||
|
}
|
||||||
|
___mkd_freemmiot(&f, 0);
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ___mkd_reparse() a line, writing it to a FILE
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
mkd_generateline(char *bfr, int size, FILE *output, mkd_flag_t* flags)
|
||||||
|
{
|
||||||
|
MMIOT f;
|
||||||
|
int status;
|
||||||
|
|
||||||
|
mkd_parse_line(bfr, size, &f, flags);
|
||||||
|
if ( flags && is_flag_set(flags, MKD_CDATA) )
|
||||||
|
status = mkd_generatexml(T(f.out), S(f.out), output) != EOF;
|
||||||
|
else
|
||||||
|
status = fwrite(T(f.out), S(f.out), 1, output) == S(f.out);
|
||||||
|
|
||||||
|
___mkd_freemmiot(&f, 0);
|
||||||
|
return status ? 0 : EOF;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* set the url display callback
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
mkd_e_url(Document *f, mkd_callback_t edit, mkd_callback_t free, void *data)
|
||||||
|
{
|
||||||
|
if ( f ) {
|
||||||
|
if ( f->cb.e_url.func != edit )
|
||||||
|
f->dirty = 1;
|
||||||
|
f->cb.e_url.func = edit;
|
||||||
|
f->cb.e_url.data = data;
|
||||||
|
f->cb.e_url.free = free;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* set the url options callback
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
mkd_e_flags(Document *f, mkd_callback_t edit, mkd_callback_t free, void *data)
|
||||||
|
{
|
||||||
|
if ( f ) {
|
||||||
|
if ( f->cb.e_flags.func != edit )
|
||||||
|
f->dirty = 1;
|
||||||
|
f->cb.e_flags.func = edit;
|
||||||
|
f->cb.e_flags.free = free;
|
||||||
|
f->cb.e_flags.data = data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* set the anchor formatter
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
mkd_e_anchor(Document *f, mkd_callback_t format, mkd_callback_t free, void *data)
|
||||||
|
{
|
||||||
|
if ( f ) {
|
||||||
|
if ( f->cb.e_anchor.func != format )
|
||||||
|
f->dirty = 1;
|
||||||
|
f->cb.e_anchor.func = format;
|
||||||
|
f->cb.e_anchor.free = free;
|
||||||
|
f->cb.e_anchor.data = data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* set the code block display callback
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
mkd_e_code_format(Document *f, mkd_callback_t codefmt, mkd_callback_t free, void *data)
|
||||||
|
{
|
||||||
|
if ( f && (f->cb.e_codefmt.func != codefmt) ) {
|
||||||
|
f->dirty = 1;
|
||||||
|
f->cb.e_codefmt.func = codefmt;
|
||||||
|
f->cb.e_codefmt.free = free;
|
||||||
|
f->cb.e_codefmt.data = data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* set the href prefix for markdown extra style footnotes
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
mkd_ref_prefix(Document *f, char *data)
|
||||||
|
{
|
||||||
|
if ( f ) {
|
||||||
|
if ( f->ref_prefix != data )
|
||||||
|
f->dirty = 1;
|
||||||
|
f->ref_prefix = data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
static void
|
||||||
|
sayflags(char *pfx, mkd_flag_t* flags, FILE *output)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
fprintf(output, "%.*s/", (int)strlen(pfx), " ");
|
||||||
|
for (i=0; i<MKD_NR_FLAGS; i++)
|
||||||
|
fputc( (i==0) || (i % 10) ? ' ' : (i/10)+'0', output);
|
||||||
|
fputc('\\', output);
|
||||||
|
fputc('\n', output);
|
||||||
|
fprintf(output, "%s|", pfx);
|
||||||
|
for (i=0; i<MKD_NR_FLAGS; i++)
|
||||||
|
fputc((i%10)+'0', output);
|
||||||
|
fputc('|', output);
|
||||||
|
fputc('\n', output);
|
||||||
|
fprintf(output, "%.*s\\", (int)strlen(pfx), " ");
|
||||||
|
for (i=0;i<MKD_NR_FLAGS; i++)
|
||||||
|
fputc(is_flag_set(flags, i)?'X':' ', output);
|
||||||
|
fputc('/', output);
|
||||||
|
fputc('\n', output);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#define sayflags(pfx,flags,output) 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
___mkd_or_flags(mkd_flag_t *dst, mkd_flag_t *src)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i=0; i<MKD_NR_FLAGS; i++)
|
||||||
|
if ( is_flag_set(src,i) )
|
||||||
|
set_mkd_flag(dst, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
___mkd_different(mkd_flag_t *dst, mkd_flag_t *src)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
mkd_flag_t zeroes;
|
||||||
|
|
||||||
|
if ( dst == 0 || src == 0 ) {
|
||||||
|
mkd_init_flags(&zeroes);
|
||||||
|
if ( !dst )
|
||||||
|
dst = &zeroes;
|
||||||
|
if ( !src )
|
||||||
|
src = &zeroes;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i=0; i < MKD_NR_FLAGS; i++)
|
||||||
|
if ( is_flag_set(src,i) != is_flag_set(dst,i) )
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
___mkd_any_flags(mkd_flag_t *dst, mkd_flag_t *src)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int count = 0;
|
||||||
|
mkd_flag_t zeroes;
|
||||||
|
|
||||||
|
if ( dst == 0 || src == 0 ) {
|
||||||
|
mkd_init_flags(&zeroes);
|
||||||
|
if ( !dst )
|
||||||
|
dst = &zeroes;
|
||||||
|
if ( !src )
|
||||||
|
src = &zeroes;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i=0; i < MKD_NR_FLAGS; i++)
|
||||||
|
if ( is_flag_set(src,i) && is_flag_set(dst,i) )
|
||||||
|
++count;
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
148
mkdio.h.in
Normal file
148
mkdio.h.in
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
#ifndef _MKDIO_D
|
||||||
|
#define _MKDIO_D
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
@SCALAR_HEADER_INCLUDE@
|
||||||
|
|
||||||
|
typedef void MMIOT;
|
||||||
|
|
||||||
|
/* special flags for markdown() and mkd_text()
|
||||||
|
*/
|
||||||
|
enum { MKD_NOLINKS=0, /* don't do link processing, block <a> tags */
|
||||||
|
MKD_NOIMAGE, /* don't do image processing, block <img> */
|
||||||
|
MKD_NOPANTS, /* don't run smartypants() */
|
||||||
|
MKD_NOHTML, /* don't allow raw html through AT ALL */
|
||||||
|
MKD_NORMAL_LISTITEM, /* disable github-style checkbox lists */
|
||||||
|
MKD_TAGTEXT, /* process text inside an html tag */
|
||||||
|
MKD_NO_EXT, /* don't allow pseudo-protocols */
|
||||||
|
#define MKD_NOEXT MKD_NO_EXT
|
||||||
|
MKD_EXPLICITLIST, /* don't combine numbered/bulletted lists */
|
||||||
|
MKD_CDATA, /* generate code for xml ![CDATA[...]] */
|
||||||
|
MKD_NOSUPERSCRIPT, /* no A^B */
|
||||||
|
MKD_STRICT, /* conform to Markdown standard as implemented in Markdown.pl */
|
||||||
|
MKD_NOTABLES, /* disallow tables */
|
||||||
|
MKD_NOSTRIKETHROUGH, /* forbid ~~strikethrough~~ */
|
||||||
|
MKD_1_COMPAT, /* compatibility with MarkdownTest_1.0 */
|
||||||
|
MKD_TOC, /* do table-of-contents processing */
|
||||||
|
MKD_AUTOLINK, /* make http://foo.com link even without <>s */
|
||||||
|
MKD_NOHEADER, /* don't process header blocks */
|
||||||
|
MKD_TABSTOP, /* expand tabs to 4 spaces */
|
||||||
|
MKD_SAFELINK, /* paranoid check for link protocol */
|
||||||
|
MKD_NODIVQUOTE, /* forbid >%class% blocks */
|
||||||
|
MKD_NOALPHALIST, /* forbid alphabetic lists */
|
||||||
|
MKD_EXTRA_FOOTNOTE, /* enable markdown extra-style footnotes */
|
||||||
|
MKD_NOSTYLE, /* don't extract <style> blocks */
|
||||||
|
MKD_DLDISCOUNT, /* enable discount-style definition lists */
|
||||||
|
MKD_DLEXTRA, /* enable extra-style definition lists */
|
||||||
|
MKD_FENCEDCODE, /* enabled fenced code blocks */
|
||||||
|
MKD_IDANCHOR, /* use id= anchors for TOC links */
|
||||||
|
MKD_GITHUBTAGS, /* allow dash and underscore in element names */
|
||||||
|
MKD_URLENCODEDANCHOR, /* urlencode non-identifier chars instead of replacing with dots */
|
||||||
|
MKD_LATEX, /* handle embedded LaTeX escapes */
|
||||||
|
MKD_ALT_AS_TITLE, /* use alt text as the title if no title is listed */
|
||||||
|
MKD_EXTENDED_ATTR, /* allow extended attribute suffixes */
|
||||||
|
MKD_HTML5, /* handle html5 tags (obsolete?) */
|
||||||
|
MKD_NR_FLAGS };
|
||||||
|
|
||||||
|
/* abstract flag type */
|
||||||
|
typedef void mkd_flag_t;
|
||||||
|
|
||||||
|
int mkd_flag_isset(mkd_flag_t*, int); /* check a flag status */
|
||||||
|
|
||||||
|
mkd_flag_t *mkd_flags(void); /* create a flag blob */
|
||||||
|
mkd_flag_t *mkd_copy_flags(mkd_flag_t*); /* copy a flag blob */
|
||||||
|
void mkd_free_flags(mkd_flag_t*); /* delete a flag blob */
|
||||||
|
char *mkd_set_flag_string(mkd_flag_t*, char*); /* set named flags */
|
||||||
|
void mkd_set_flag_num(mkd_flag_t*, unsigned long);/* set a specific flag */
|
||||||
|
void mkd_clr_flag_num(mkd_flag_t*, unsigned long);/* clear a specific flag */
|
||||||
|
void mkd_set_flag_bitmap(mkd_flag_t*,long); /* set a bunch of flags */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* sneakily back-define the published interface (leaving the old functions for v2 compatibility)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define mkd_in mkd3_in
|
||||||
|
#define mkd_string mkd3_string
|
||||||
|
#define gfm_in gfm3_in
|
||||||
|
#define gfm_string gfm3_string
|
||||||
|
#define mkd_compile mkd3_compile
|
||||||
|
#define mkd_dump mkd3_dump
|
||||||
|
#define markdown markdown3
|
||||||
|
#define mkd_line mkd3_line
|
||||||
|
#define mkd_xhtmlpage mkd3_xhtmlpage
|
||||||
|
#define mkd_generateline mkd3_generateline
|
||||||
|
#define mkd_flags_are mkd3_flags_are
|
||||||
|
|
||||||
|
/* line builder for markdown()
|
||||||
|
*/
|
||||||
|
MMIOT *mkd_in(FILE*,mkd_flag_t*); /* assemble input from a file */
|
||||||
|
MMIOT *mkd_string(const char*,int,mkd_flag_t*); /* assemble input from a buffer */
|
||||||
|
|
||||||
|
/* line builder for github flavoured markdown
|
||||||
|
*/
|
||||||
|
MMIOT *gfm_in(FILE*,mkd_flag_t*); /* assemble input from a file */
|
||||||
|
MMIOT *gfm_string(const char*,int,mkd_flag_t*); /* assemble input from a buffer */
|
||||||
|
|
||||||
|
void mkd_basename(MMIOT*,char*);
|
||||||
|
|
||||||
|
void mkd_initialize(void);
|
||||||
|
|
||||||
|
#define mkd_with_html5_tags() 0
|
||||||
|
#define mkd_shlib_destructor() 0
|
||||||
|
|
||||||
|
/* compilation, debugging, cleanup
|
||||||
|
*/
|
||||||
|
int mkd_compile(MMIOT*, mkd_flag_t*);
|
||||||
|
void mkd_cleanup(MMIOT*);
|
||||||
|
|
||||||
|
/* markup functions
|
||||||
|
*/
|
||||||
|
int mkd_dump(MMIOT*, FILE*, mkd_flag_t*, char*);
|
||||||
|
int markdown(MMIOT*, FILE*, mkd_flag_t*);
|
||||||
|
int mkd_line(char *, int, char **, mkd_flag_t*);
|
||||||
|
int mkd_xhtmlpage(MMIOT*,mkd_flag_t*,FILE*);
|
||||||
|
|
||||||
|
/* header block access
|
||||||
|
*/
|
||||||
|
char* mkd_doc_title(MMIOT*);
|
||||||
|
char* mkd_doc_author(MMIOT*);
|
||||||
|
char* mkd_doc_date(MMIOT*);
|
||||||
|
|
||||||
|
/* compiled data access
|
||||||
|
*/
|
||||||
|
int mkd_document(MMIOT*, char**);
|
||||||
|
int mkd_toc(MMIOT*, char**);
|
||||||
|
int mkd_css(MMIOT*, char **);
|
||||||
|
int mkd_xml(char *, int, char **);
|
||||||
|
|
||||||
|
/* write-to-file functions
|
||||||
|
*/
|
||||||
|
int mkd_generatehtml(MMIOT*,FILE*);
|
||||||
|
int mkd_generatetoc(MMIOT*,FILE*);
|
||||||
|
int mkd_generatexml(char *, int,FILE*);
|
||||||
|
int mkd_generatecss(MMIOT*,FILE*);
|
||||||
|
#define mkd_style mkd_generatecss
|
||||||
|
int mkd_generateline(char *, int, FILE*, mkd_flag_t*);
|
||||||
|
#define mkd_text mkd_generateline
|
||||||
|
|
||||||
|
/* url generator callbacks
|
||||||
|
*/
|
||||||
|
typedef char * (*mkd_callback_t)(const char*, const int, void*);
|
||||||
|
typedef void (*mkd_free_t)(char*, int, void*);
|
||||||
|
|
||||||
|
void mkd_e_url(void *, mkd_callback_t, mkd_free_t, void *);
|
||||||
|
void mkd_e_flags(void *, mkd_callback_t, mkd_free_t, void *);
|
||||||
|
void mkd_e_anchor(void *, mkd_callback_t, mkd_free_t, void *);
|
||||||
|
void mkd_e_code_format(void*, mkd_callback_t, mkd_free_t, void *);
|
||||||
|
|
||||||
|
/* version#.
|
||||||
|
*/
|
||||||
|
extern char markdown_version[];
|
||||||
|
void mkd_mmiot_flags(FILE *, MMIOT *, int);
|
||||||
|
void mkd_flags_are(FILE*, mkd_flag_t*, int);
|
||||||
|
|
||||||
|
void mkd_ref_prefix(MMIOT*, char*);
|
||||||
|
|
||||||
|
|
||||||
|
#endif/*_MKDIO_D*/
|
||||||
93
mktags.c
Normal file
93
mktags.c
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
/* block-level tags for passing html blocks through the blender
|
||||||
|
*/
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#define __WITHOUT_AMALLOC 1
|
||||||
|
#include "config.h"
|
||||||
|
#include "markdown.h"
|
||||||
|
#include "cstring.h"
|
||||||
|
#include "tags.h"
|
||||||
|
|
||||||
|
STRING(struct kw) blocktags;
|
||||||
|
|
||||||
|
|
||||||
|
/* define a html block tag
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
define_one_tag(char *id, int selfclose)
|
||||||
|
{
|
||||||
|
struct kw *p = &EXPAND(blocktags);
|
||||||
|
|
||||||
|
p->id = id;
|
||||||
|
p->size = strlen(id);
|
||||||
|
p->selfclose = selfclose;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* case insensitive string sort (for qsort() and bsearch() of block tags)
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
casort(struct kw *a, struct kw *b)
|
||||||
|
{
|
||||||
|
if ( a->size != b->size )
|
||||||
|
return a->size - b->size;
|
||||||
|
return strncasecmp(a->id, b->id, b->size);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* stupid cast to make gcc shut up about the function types being
|
||||||
|
* passed into qsort() and bsearch()
|
||||||
|
*/
|
||||||
|
typedef int (*stfu)(const void*,const void*);
|
||||||
|
|
||||||
|
|
||||||
|
/* load in the standard collection of html tags that markdown supports
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
main(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
#define KW(x) define_one_tag(x, 0)
|
||||||
|
#define SC(x) define_one_tag(x, 1)
|
||||||
|
|
||||||
|
KW("STYLE");
|
||||||
|
KW("SCRIPT");
|
||||||
|
KW("ADDRESS");
|
||||||
|
KW("BDO");
|
||||||
|
KW("BLOCKQUOTE");
|
||||||
|
KW("CENTER");
|
||||||
|
KW("DFN");
|
||||||
|
KW("DIV");
|
||||||
|
KW("OBJECT");
|
||||||
|
KW("H1");
|
||||||
|
KW("H2");
|
||||||
|
KW("H3");
|
||||||
|
KW("H4");
|
||||||
|
KW("H5");
|
||||||
|
KW("H6");
|
||||||
|
KW("LISTING");
|
||||||
|
KW("NOBR");
|
||||||
|
KW("FORM");
|
||||||
|
KW("UL");
|
||||||
|
KW("P");
|
||||||
|
KW("OL");
|
||||||
|
KW("DL");
|
||||||
|
KW("PLAINTEXT");
|
||||||
|
KW("PRE");
|
||||||
|
KW("TABLE");
|
||||||
|
KW("WBR");
|
||||||
|
KW("XMP");
|
||||||
|
SC("HR");
|
||||||
|
KW("IFRAME");
|
||||||
|
KW("MAP");
|
||||||
|
|
||||||
|
qsort(T(blocktags), S(blocktags), sizeof(struct kw), (stfu)casort);
|
||||||
|
|
||||||
|
printf("static struct kw blocktags[] = {\n");
|
||||||
|
for (i=0; i < S(blocktags); i++)
|
||||||
|
printf(" { \"%s\", %d, %d },\n", T(blocktags)[i].id, T(blocktags)[i].size, T(blocktags)[i].selfclose );
|
||||||
|
printf("};\n\n");
|
||||||
|
printf("#define NR_blocktags %d\n", S(blocktags));
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
65
msvc/Makefile
Normal file
65
msvc/Makefile
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
# NMAKE Makefile to build Discount with Visual C++
|
||||||
|
CFLAGS = /nologo /MP /MDd /EHa /Zi \
|
||||||
|
/D_CRT_SECURE_NO_DEPRECATE /D_CRT_NONSTDC_NO_DEPRECATE /D_SCL_SECURE_NO_WARNINGS \
|
||||||
|
/I.
|
||||||
|
LIBOBJ = mkdio.obj markdown.obj dumptree.obj generate.obj \
|
||||||
|
resource.obj docheader.obj version.obj toc.obj css.obj \
|
||||||
|
xml.obj Csio.obj xmlpage.obj basename.obj emmatch.obj \
|
||||||
|
github_flavoured.obj setup.obj tags.obj html5.obj flags.obj
|
||||||
|
MKDLIB = libmarkdown.lib
|
||||||
|
PGMS=markdown
|
||||||
|
SAMPLE_PGMS=mkd2html makepage
|
||||||
|
# modules that markdown, makepage, mkd2html, &tc use
|
||||||
|
COMMON=pgm_options.obj gethopt.obj
|
||||||
|
|
||||||
|
# Assumes VERSION is a single-line file
|
||||||
|
VERSION = \
|
||||||
|
!INCLUDE <VERSION>
|
||||||
|
|
||||||
|
default: all
|
||||||
|
|
||||||
|
all: $(MKDLIB) $(PGMS) $(SAMPLE_PGMS)
|
||||||
|
|
||||||
|
$(MKDLIB): $(LIBOBJ)
|
||||||
|
if exist $(MKDLIB) del $(MKDLIB)
|
||||||
|
lib /out:$(MKDLIB) $(LIBOBJ)
|
||||||
|
|
||||||
|
config.h: msvc/config.h.vc
|
||||||
|
copy /Y msvc\config.h.vc config.h
|
||||||
|
|
||||||
|
version.c: version.c.in
|
||||||
|
powershell.exe -Command "(gc version.c.in) -replace '@TABSTOP@', 'TABSTOP' | Out-File version.c"
|
||||||
|
|
||||||
|
version.obj: version.c VERSION config.h
|
||||||
|
$(CC) $(CFLAGS) -DBRANCH="" -DVERSION=\"$(VERSION)\" /c version.c
|
||||||
|
|
||||||
|
mkdio.h: mkdio.h.in
|
||||||
|
powershell.exe -Command "(gc mkdio.h.in) -replace '@DWORD@', 'unsigned long' -replace '@SCALAR_HEADER_INCLUDE@', '' | Out-File mkdio.h"
|
||||||
|
|
||||||
|
mkdio.obj: mkdio.h
|
||||||
|
|
||||||
|
tags.obj: tags.c cstring.h tags.h blocktags
|
||||||
|
|
||||||
|
pgm_options.obj: pgm_options.c mkdio.h config.h
|
||||||
|
$(CC) $(CFLAGS) /c pgm_options.c
|
||||||
|
|
||||||
|
mktags: mktags.obj
|
||||||
|
$(CC) $(CFLAGS) mktags.obj
|
||||||
|
|
||||||
|
blocktags: mktags
|
||||||
|
.\mktags.exe > blocktags
|
||||||
|
|
||||||
|
mkd2html: mkd2html.obj $(MKDLIB) mkdio.h gethopt.h gethopt.obj notspecial.obj
|
||||||
|
$(CC) $(CFLAGS) $(LFLAGS) mkd2html.obj gethopt.obj notspecial.obj $(MKDLIB)
|
||||||
|
|
||||||
|
markdown: main.obj $(COMMON) $(MKDLIB)
|
||||||
|
$(CC) $(CFLAGS) $(LFLAGS) /Femarkdown main.obj $(COMMON) $(MKDLIB)
|
||||||
|
|
||||||
|
makepage: makepage.c $(COMMON) $(MKDLIB) mkdio.h
|
||||||
|
$(CC) $(CFLAGS) $(LFLAGS) makepage.c $(COMMON) $(MKDLIB)
|
||||||
|
|
||||||
|
clean:
|
||||||
|
-del config.h blocktags mkdio.h version.c
|
||||||
|
-del *.obj *.lib
|
||||||
|
-del *.pdb *.exp
|
||||||
|
-del *.ilk *.exe
|
||||||
17
msvc/README.md
Normal file
17
msvc/README.md
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
# *Discount* Markdown compiler on Windows with Visual C++
|
||||||
|
|
||||||
|
Makefile for NMAKE utility to build Discount using Visual C++
|
||||||
|
and pre-digested `config.h` template.
|
||||||
|
|
||||||
|
## Build
|
||||||
|
|
||||||
|
Build generates default optimised binaries.
|
||||||
|
Edit `CFLAGS` in `Makefile` to customize generated binaries (eg. switch to debug build).
|
||||||
|
|
||||||
|
* Generate static library `libmarkdown.lib` and utility programs:
|
||||||
|
|
||||||
|
nmake /f msvc/Makefile
|
||||||
|
|
||||||
|
* Clean source tree
|
||||||
|
|
||||||
|
nmake /f msvc/Makefile clean
|
||||||
77
msvc/config.h.vc
Normal file
77
msvc/config.h.vc
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
/*
|
||||||
|
* Pre-digested configuration header for MSVC on Windows.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __AC_MARKDOWN_D
|
||||||
|
#define __AC_MARKDOWN_D 1
|
||||||
|
|
||||||
|
#ifndef _MSC_VER
|
||||||
|
#error Use this header with MSVC only.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define OS_WIN32 1
|
||||||
|
|
||||||
|
/*
|
||||||
|
* `discount` feature macros - we want them all!
|
||||||
|
*/
|
||||||
|
#ifndef WITH_ID_ANCHOR
|
||||||
|
#define WITH_ID_ANCHOR 1
|
||||||
|
#endif
|
||||||
|
#ifndef WITH_FENCED_CODE
|
||||||
|
#define WITH_FENCED_CODE 1
|
||||||
|
#endif
|
||||||
|
#ifndef WITH_GITHUB_TAGS
|
||||||
|
#define WITH_GITHUB_TAGS 1
|
||||||
|
#endif
|
||||||
|
#ifndef USE_DISCOUNT_DL
|
||||||
|
#define USE_DISCOUNT_DL 1
|
||||||
|
#endif
|
||||||
|
#ifndef USE_EXTRA_DL
|
||||||
|
#define USE_EXTRA_DL 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The Visual C++ "C" compiler has a `__inline` keyword implemented
|
||||||
|
* in Visual Studio 2008 and later, see
|
||||||
|
* <http://msdn.microsoft.com/de-de/library/cx3b23a3%28v=vs.90%29.aspx>
|
||||||
|
*/
|
||||||
|
#if _MSC_VER >= 1500 /* VC 9.0, MSC_VER 15, Visual Studio 2008 */
|
||||||
|
#define inline __inline
|
||||||
|
#else
|
||||||
|
#define inline
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#ifndef strncasecmp
|
||||||
|
#include <string.h>
|
||||||
|
#define bzero(p, n) memset(p, 0, n)
|
||||||
|
#define strcasecmp _stricmp
|
||||||
|
#define strncasecmp _strnicmp
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Beware of conflicts with <Windows.h>, which typedef's these names.
|
||||||
|
*/
|
||||||
|
#ifndef WINVER
|
||||||
|
#define DWORD unsigned long
|
||||||
|
#define WORD unsigned short
|
||||||
|
#define BYTE unsigned char
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define HAVE_PWD_H 0
|
||||||
|
#define HAVE_GETPWUID 0
|
||||||
|
#define HAVE_SRANDOM 0
|
||||||
|
#define INITRNG(x) srand((unsigned int)x)
|
||||||
|
#define HAVE_BZERO 0
|
||||||
|
#define HAVE_RANDOM 0
|
||||||
|
#define COINTOSS() (rand()&1)
|
||||||
|
#define HAVE_STRCASECMP 1
|
||||||
|
#define HAVE_STRNCASECMP 1
|
||||||
|
#define HAVE_FCHDIR 0
|
||||||
|
#define TABSTOP 8
|
||||||
|
#define HAVE_MALLOC_H 0
|
||||||
|
|
||||||
|
#define DESTRUCTOR
|
||||||
|
|
||||||
|
#endif /* __AC_MARKDOWN_D */
|
||||||
43
notspecial.c
Normal file
43
notspecial.c
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* check a filename to see if it's a (fifo|character special|socket) object
|
||||||
|
* (if a stat() function doesn't exist, we can't stat so we'll just return
|
||||||
|
* true no matter what.)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#if HAVE_STAT && HAS_ISCHR && HAS_ISFIFO && HAS_ISSOCK
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
int
|
||||||
|
notspecial(char *file)
|
||||||
|
{
|
||||||
|
struct stat info;
|
||||||
|
|
||||||
|
if ( stat(file, &info) != 0 )
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return S_ISREG(info.st_mode);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
int
|
||||||
|
notspecial(char *file)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for ( i=1; i < argc; i++ )
|
||||||
|
printf("%s is %sspecial\n", argv[i], notspecial(argv[i]) ? "not " : "");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
218
pgm_options.c
Normal file
218
pgm_options.c
Normal file
@ -0,0 +1,218 @@
|
|||||||
|
/* markdown: a C implementation of John Gruber's Markdown markup language.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007-2011 Jessica L Parsons.
|
||||||
|
* The redistribution terms are provided in the COPYRIGHT file that must
|
||||||
|
* be distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include "markdown.h"
|
||||||
|
#include "amalloc.h"
|
||||||
|
|
||||||
|
#if HAVE_LIBGEN_H
|
||||||
|
#include <libgen.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void set_dlist(mkd_flag_t *flags, int enable);
|
||||||
|
|
||||||
|
static struct _special {
|
||||||
|
char *name;
|
||||||
|
void (*setter)(mkd_flag_t *, int);
|
||||||
|
} special[] = {
|
||||||
|
{ "definitionlist", set_dlist },
|
||||||
|
{ "dlist", set_dlist },
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct _opt {
|
||||||
|
char *name;
|
||||||
|
char *desc;
|
||||||
|
int special;
|
||||||
|
int off;
|
||||||
|
int alias; /* this opt is a synonym; don't display in -F? */
|
||||||
|
int sayenable;
|
||||||
|
int flag; /* flag to set/clear */
|
||||||
|
int unflag; /* flag to clear/set */
|
||||||
|
} opts[] = {
|
||||||
|
{ "tabstop", "default (4-space) tabstops", 0, 0, 0, 1, MKD_TABSTOP },
|
||||||
|
{ "image", "images", 0, 1, 0, 1, MKD_NOIMAGE },
|
||||||
|
{ "links", "links", 0, 1, 0, 1, MKD_NOLINKS },
|
||||||
|
{ "strict", "conform to the markdown standard", 0, 0, 0, 1, MKD_STRICT },
|
||||||
|
{ "relax", "(don't) conform to the markdown standard", 0, 1, 1, 1, MKD_STRICT },
|
||||||
|
{ "standard", "conform to the markdown standard", 0, 0, 1, 1, MKD_STRICT },
|
||||||
|
{ "tables", "tables", 0, 1, 0, 1, MKD_NOTABLES },
|
||||||
|
{ "header", "pandoc-style headers", 0, 1, 0, 1, MKD_NOHEADER },
|
||||||
|
{ "html", "allow raw html", 0, 1, 0, 0, MKD_NOHTML },
|
||||||
|
{ "ext", "extended protocols", 0, 1, 0, 1, MKD_NO_EXT },
|
||||||
|
{ "cdata", "generate cdata", 0, 0, 0, 0, MKD_CDATA },
|
||||||
|
{ "smarty", "smartypants", 0, 1, 0, 1, MKD_NOPANTS },
|
||||||
|
{ "pants", "smartypants", 0, 1, 1, 1, MKD_NOPANTS },
|
||||||
|
{ "toc", "tables of contents", 0, 0, 0, 1, MKD_TOC },
|
||||||
|
{ "autolink", "autolinking", 0, 0, 0, 1, MKD_AUTOLINK },
|
||||||
|
{ "safelink", "safe links", 0, 0, 0, 1, MKD_SAFELINK },
|
||||||
|
{ "strikethrough", "strikethrough", 0, 1, 0, 1, MKD_NOSTRIKETHROUGH },
|
||||||
|
{ "del", "strikethrough", 0, 1, 1, 1, MKD_NOSTRIKETHROUGH },
|
||||||
|
{ "superscript", "superscript", 0, 1, 0, 1, MKD_NOSUPERSCRIPT },
|
||||||
|
{ "divquote", ">%class% blockquotes", 0, 1, 0, 1, MKD_NODIVQUOTE },
|
||||||
|
{ "alphalist", "alpha lists", 0, 1, 0, 1, MKD_NOALPHALIST },
|
||||||
|
{ "1.0", "markdown 1.0 compatibility", 0, 0, 0, 1, MKD_1_COMPAT },
|
||||||
|
{ "footnotes", "markdown extra footnotes", 0, 0, 0, 1, MKD_EXTRA_FOOTNOTE },
|
||||||
|
{ "footnote", "markdown extra footnotes", 0, 0, 1, 1, MKD_EXTRA_FOOTNOTE },
|
||||||
|
{ "style", "extract style blocks", 0, 1, 0, 1, MKD_NOSTYLE },
|
||||||
|
{ "dldiscount", "discount-style definition lists", 0, 0, 0, 1, MKD_DLDISCOUNT },
|
||||||
|
{ "dlextra", "markdown extra-style definition lists", 0, 0, 0, 1, MKD_DLEXTRA },
|
||||||
|
{ "fencedcode", "fenced code blocks", 0, 0, 0, 1, MKD_FENCEDCODE },
|
||||||
|
{ "idanchor", "id= anchors in TOC", 0, 0, 0, 1, MKD_IDANCHOR },
|
||||||
|
{ "githubtags", "- and _ in element names", 0, 0, 0, 1, MKD_GITHUBTAGS },
|
||||||
|
{ "urlencodedanchor", "html5-style anchors", 0, 0, 0, 1, MKD_URLENCODEDANCHOR },
|
||||||
|
{ "html5anchor", "html5-style anchors", 0, 0, 1, 1, MKD_URLENCODEDANCHOR },
|
||||||
|
{ "latex", "LaTeX escapes", 0, 0, 0, 1, MKD_LATEX },
|
||||||
|
{ "explicitlist", "merge adjacent numeric/bullet lists", 0, 0, 0, 0, MKD_EXPLICITLIST },
|
||||||
|
{ "github-listitem","github-style check items", 0, 1, 0, 1, MKD_NORMAL_LISTITEM } ,
|
||||||
|
{ "regular-listitem","github-style check items", 0, 0, 1, 1, MKD_NORMAL_LISTITEM } ,
|
||||||
|
{ "definitionlist","both discount & markdown extra definition lists", 1 },
|
||||||
|
{ "dlist", "both discount & markdown extra definition lists", 1, 0, 1 },
|
||||||
|
{ "alt_as_title", "use the alt text as a title if there isn't one (images)", 0, 0, 0, 1, MKD_ALT_AS_TITLE },
|
||||||
|
{ "extended_attr", "allow extended attributes on links", 0, 0, 1, 1, MKD_EXTENDED_ATTR },
|
||||||
|
{ "extended_attributes", "allow extended attributes on links", 0, 0, 0, 1, MKD_EXTENDED_ATTR },
|
||||||
|
{ "html5", "handle html5 tags (obsolete?)", 0, 0, 0, 1, MKD_HTML5 },
|
||||||
|
} ;
|
||||||
|
|
||||||
|
#define NR(x) (sizeof x / sizeof x[0])
|
||||||
|
|
||||||
|
|
||||||
|
typedef int (*stfu)(const void *, const void *);
|
||||||
|
|
||||||
|
int
|
||||||
|
sort_by_name(struct _opt *a, struct _opt *b)
|
||||||
|
{
|
||||||
|
return strcmp(a->name,b->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
sort_by_flag(struct _opt *a, struct _opt *b)
|
||||||
|
{
|
||||||
|
return a->flag - b->flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
show_flags(int byname, int verbose, mkd_flag_t *flags)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if ( byname ) {
|
||||||
|
int size, len=0;
|
||||||
|
|
||||||
|
qsort(opts, NR(opts), sizeof(opts[0]), (stfu)sort_by_name);
|
||||||
|
|
||||||
|
for (i=0; i < NR(opts); i++)
|
||||||
|
if ( (size=strlen(opts[i].name)) > len )
|
||||||
|
len = size;
|
||||||
|
|
||||||
|
for (i=0; i < NR(opts); i++) {
|
||||||
|
if ( opts[i].alias && !verbose )
|
||||||
|
continue;
|
||||||
|
if ( (flags==0) || is_flag_set(flags, opts[i].flag) )
|
||||||
|
fprintf(stderr, "%*s : %s\n", len+1, opts[i].name, opts[i].desc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
qsort(opts, NR(opts), sizeof(opts[0]), (stfu)sort_by_flag);
|
||||||
|
|
||||||
|
for (i=0; i < NR(opts) && i < 8*sizeof(DWORD); i++) {
|
||||||
|
|
||||||
|
if ( opts[i].special || opts[i].alias )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if ( (flags==0) || is_flag_set(flags, opts[i].flag) ) {
|
||||||
|
fprintf(stderr, "%08lx : ", 1L<<opts[i].flag);
|
||||||
|
if ( opts[i].sayenable )
|
||||||
|
fprintf(stderr, opts[i].off ? "disable " : "enable ");
|
||||||
|
fprintf(stderr, "%s\n", opts[i].desc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
handle_special(mkd_flag_t *flags, char *opt, int enable)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i=0; i < NR(special); i++)
|
||||||
|
if ( strcasecmp(opt, special[i].name) == 0 ) {
|
||||||
|
(special[i].setter)(flags, enable);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
set_dlist(mkd_flag_t *flags, int enable)
|
||||||
|
{
|
||||||
|
if ( enable ) {
|
||||||
|
set_mkd_flag(flags, MKD_DLDISCOUNT);
|
||||||
|
set_mkd_flag(flags, MKD_DLEXTRA);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
clear_mkd_flag(flags, MKD_DLDISCOUNT);
|
||||||
|
clear_mkd_flag(flags, MKD_DLEXTRA);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
mkd_set_flag_string(mkd_flag_t *flags, char *optionstring)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int enable;
|
||||||
|
char *arg;
|
||||||
|
|
||||||
|
if ( flags == 0 ) /* shouldn't happen */
|
||||||
|
return "NULL";
|
||||||
|
|
||||||
|
for ( arg = strtok(optionstring, ","); arg; arg = strtok(NULL, ",") ) {
|
||||||
|
if ( *arg == '+' || *arg == '-' )
|
||||||
|
enable = (*arg++ == '+') ? 1 : 0;
|
||||||
|
else if ( strncasecmp(arg, "no", 2) == 0 ) {
|
||||||
|
arg += 2;
|
||||||
|
enable = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
enable = 1;
|
||||||
|
|
||||||
|
for ( i=0; i < NR(opts); i++ )
|
||||||
|
if ( strcasecmp(arg, opts[i].name) == 0 )
|
||||||
|
break;
|
||||||
|
|
||||||
|
if ( i < NR(opts) ) {
|
||||||
|
|
||||||
|
if ( opts[i].special ) {
|
||||||
|
handle_special(flags, opts[i].name, enable);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ( opts[i].off )
|
||||||
|
enable = !enable;
|
||||||
|
|
||||||
|
if ( enable ) {
|
||||||
|
set_mkd_flag(flags, opts[i].flag);
|
||||||
|
if ( opts[i].unflag )
|
||||||
|
clear_mkd_flag(flags, opts[i].unflag);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
clear_mkd_flag(flags, opts[i].flag);
|
||||||
|
if ( opts[i].unflag )
|
||||||
|
set_mkd_flag(flags, opts[i].unflag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return arg;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
8
pgm_options.h
Normal file
8
pgm_options.h
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#ifndef PGM_OPTIONS_D
|
||||||
|
#define PGM_OPTIONS_D
|
||||||
|
|
||||||
|
#include <mkdio.h>
|
||||||
|
|
||||||
|
void show_flags(int byname, int verbose, mkd_flag_t *flags);
|
||||||
|
|
||||||
|
#endif/*PGM_OPTIONS_D*/
|
||||||
178
resource.c
Normal file
178
resource.c
Normal file
@ -0,0 +1,178 @@
|
|||||||
|
/* markdown: a C implementation of John Gruber's Markdown markup language.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007 Jessica L Parsons.
|
||||||
|
* The redistribution terms are provided in the COPYRIGHT file that must
|
||||||
|
* be distributed with this source code.
|
||||||
|
*/
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "cstring.h"
|
||||||
|
#include "markdown.h"
|
||||||
|
#include "amalloc.h"
|
||||||
|
|
||||||
|
/* free a (single) line
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
___mkd_freeLine(Line *ptr)
|
||||||
|
{
|
||||||
|
if ( ptr->fence_class )
|
||||||
|
free(ptr->fence_class);
|
||||||
|
DELETE(ptr->text);
|
||||||
|
free(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* free a list of lines
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
___mkd_freeLines(Line *p)
|
||||||
|
{
|
||||||
|
if (p->next)
|
||||||
|
___mkd_freeLines(p->next);
|
||||||
|
___mkd_freeLine(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* bye bye paragraph.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
___mkd_freeParagraph(Paragraph *p)
|
||||||
|
{
|
||||||
|
if (p->next)
|
||||||
|
___mkd_freeParagraph(p->next);
|
||||||
|
if (p->down)
|
||||||
|
___mkd_freeParagraph(p->down);
|
||||||
|
if (p->text)
|
||||||
|
___mkd_freeLines(p->text);
|
||||||
|
if (p->label)
|
||||||
|
free(p->label);
|
||||||
|
if (p->ident)
|
||||||
|
free(p->ident);
|
||||||
|
if (p->lang)
|
||||||
|
free(p->lang);
|
||||||
|
free(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* bye bye footnote.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
___mkd_freefootnote(Footnote *f)
|
||||||
|
{
|
||||||
|
DELETE(f->tag);
|
||||||
|
DELETE(f->link);
|
||||||
|
DELETE(f->title);
|
||||||
|
DELETE(f->height);
|
||||||
|
DELETE(f->width);
|
||||||
|
DELETE(f->extended_attr);
|
||||||
|
if ( f->text) ___mkd_freeParagraph(f->text);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* bye bye footnotes.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
___mkd_freefootnotes(MMIOT *f)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if ( f->footnotes ) {
|
||||||
|
for (i=0; i < S(f->footnotes->note); i++)
|
||||||
|
___mkd_freefootnote( &T(f->footnotes->note)[i] );
|
||||||
|
DELETE(f->footnotes->note);
|
||||||
|
free(f->footnotes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* initialize a new MMIOT
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
___mkd_initmmiot(MMIOT *f, void *footnotes, mkd_flag_t *flags)
|
||||||
|
{
|
||||||
|
if ( f ) {
|
||||||
|
memset(f, 0, sizeof *f);
|
||||||
|
CREATE(f->in);
|
||||||
|
CREATE(f->out);
|
||||||
|
CREATE(f->Q);
|
||||||
|
CREATE(f->extratags);
|
||||||
|
if ( footnotes )
|
||||||
|
f->footnotes = footnotes;
|
||||||
|
else {
|
||||||
|
f->footnotes = calloc(1, sizeof f->footnotes[0]);
|
||||||
|
CREATE(f->footnotes->note);
|
||||||
|
}
|
||||||
|
if ( flags )
|
||||||
|
COPY_FLAGS(f->flags, *flags);
|
||||||
|
else
|
||||||
|
mkd_init_flags(&f->flags);
|
||||||
|
|
||||||
|
if ( is_flag_set(&f->flags, MKD_HTML5) )
|
||||||
|
mkd_add_html5_tags(f);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* free the contents of a MMIOT, but leave the object alone.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
___mkd_freemmiot(MMIOT *f, void *footnotes)
|
||||||
|
{
|
||||||
|
if ( f ) {
|
||||||
|
DELETE(f->in);
|
||||||
|
DELETE(f->out);
|
||||||
|
DELETE(f->Q);
|
||||||
|
DELETE(f->extratags);
|
||||||
|
if ( f->footnotes != footnotes )
|
||||||
|
___mkd_freefootnotes(f);
|
||||||
|
|
||||||
|
memset(f, 0, sizeof *f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* free lines up to an barrier.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
___mkd_freeLineRange(Line *anchor, Line *stop)
|
||||||
|
{
|
||||||
|
Line *r = anchor->next;
|
||||||
|
|
||||||
|
if ( r != stop ) {
|
||||||
|
while ( r && (r->next != stop) )
|
||||||
|
r = r->next;
|
||||||
|
if ( r ) r->next = 0;
|
||||||
|
___mkd_freeLines(anchor->next);
|
||||||
|
}
|
||||||
|
anchor->next = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* clean up everything allocated in __mkd_compile()
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
mkd_cleanup(Document *doc)
|
||||||
|
{
|
||||||
|
if ( doc && (doc->magic == VALID_DOCUMENT) ) {
|
||||||
|
if ( doc->ctx ) {
|
||||||
|
___mkd_freemmiot(doc->ctx, 0);
|
||||||
|
free(doc->ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( doc->code) ___mkd_freeParagraph(doc->code);
|
||||||
|
if ( doc->title) ___mkd_freeLine(doc->title);
|
||||||
|
if ( doc->author) ___mkd_freeLine(doc->author);
|
||||||
|
if ( doc->date) ___mkd_freeLine(doc->date);
|
||||||
|
if ( T(doc->content) ) ___mkd_freeLines(T(doc->content));
|
||||||
|
memset(doc, 0, sizeof doc[0]);
|
||||||
|
free(doc);
|
||||||
|
}
|
||||||
|
}
|
||||||
31
setup.c
Normal file
31
setup.c
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/* markdown: a C implementation of John Gruber's Markdown markup language.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007 Jessica L Parsons.
|
||||||
|
* The redistribution terms are provided in the COPYRIGHT file that must
|
||||||
|
* be distributed with this source code.
|
||||||
|
*/
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
#include "cstring.h"
|
||||||
|
#include "markdown.h"
|
||||||
|
#include "amalloc.h"
|
||||||
|
#include "tags.h"
|
||||||
|
|
||||||
|
static int need_to_initrng = 1;
|
||||||
|
|
||||||
|
void
|
||||||
|
mkd_initialize(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
if ( need_to_initrng ) {
|
||||||
|
need_to_initrng = 0;
|
||||||
|
INITRNG(time(0));
|
||||||
|
}
|
||||||
|
}
|
||||||
123
tags.c
Normal file
123
tags.c
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
/* block-level tags for passing html blocks through the blender
|
||||||
|
*/
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#define __WITHOUT_AMALLOC 1
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "markdown.h"
|
||||||
|
#include "cstring.h"
|
||||||
|
#include "tags.h"
|
||||||
|
|
||||||
|
/* the standard collection of tags are built and sorted when
|
||||||
|
* discount is configured, so all we need to do is pull them
|
||||||
|
* in and use them.
|
||||||
|
*
|
||||||
|
* Additional tags still need to be allocated, sorted, and deallocated.
|
||||||
|
*/
|
||||||
|
#include "blocktags"
|
||||||
|
|
||||||
|
|
||||||
|
/* define an additional html block tag
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
mkd_define_tag(MMIOT *doc, char *id, int selfclose)
|
||||||
|
{
|
||||||
|
struct kw *p;
|
||||||
|
|
||||||
|
/* only add the new tag if it doesn't exist in
|
||||||
|
* either the standard or extra tag tables.
|
||||||
|
*/
|
||||||
|
if ( !(p = mkd_search_tags(doc, id, strlen(id))) ) {
|
||||||
|
p = &EXPAND(doc->extratags);
|
||||||
|
p->id = strdup(id);
|
||||||
|
p->size = strlen(id);
|
||||||
|
p->selfclose = selfclose;
|
||||||
|
|
||||||
|
mkd_sort_tags(doc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* case insensitive string sort (for qsort() and bsearch() of block tags)
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
casort(struct kw *a, struct kw *b)
|
||||||
|
{
|
||||||
|
if ( a->size != b->size )
|
||||||
|
return a->size - b->size;
|
||||||
|
return strncasecmp(a->id, b->id, b->size);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* stupid cast to make gcc shut up about the function types being
|
||||||
|
* passed into qsort() and bsearch()
|
||||||
|
*/
|
||||||
|
typedef int (*stfu)(const void*,const void*);
|
||||||
|
|
||||||
|
|
||||||
|
/* sort the list of extra html block tags for later searching
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
mkd_sort_tags(MMIOT *doc)
|
||||||
|
{
|
||||||
|
if ( S(doc->extratags) )
|
||||||
|
qsort(T(doc->extratags), S(doc->extratags), sizeof(struct kw), (stfu)casort);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* look for a token in the html block tag list
|
||||||
|
*/
|
||||||
|
struct kw*
|
||||||
|
mkd_search_tags(MMIOT *doc, char *pat, int len)
|
||||||
|
{
|
||||||
|
struct kw key;
|
||||||
|
struct kw *ret;
|
||||||
|
|
||||||
|
key.id = pat;
|
||||||
|
key.size = len;
|
||||||
|
|
||||||
|
if ( (ret=bsearch(&key,blocktags,NR_blocktags,sizeof key,(stfu)casort)) )
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
if ( S(doc->extratags) )
|
||||||
|
return bsearch(&key,T(doc->extratags),S(doc->extratags),sizeof key,(stfu)casort);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* delete an extratags structure
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
___mkd_delete_extratags(MMIOT *doc)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for ( i=0; i<S(doc->extratags); i++ )
|
||||||
|
free(T(doc->extratags)[i].id);
|
||||||
|
|
||||||
|
S(doc->extratags) = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* duplicate an extratags structure
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
___mkd_copy_extratags(MMIOT *dst, MMIOT *src)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if ( (src == NULL) || (dst == NULL) )
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ( S(dst->extratags) )
|
||||||
|
___mkd_delete_extratags(dst);
|
||||||
|
|
||||||
|
for (i=0; i< S(src->extratags); i++ ) {
|
||||||
|
EXPAND(dst->extratags);
|
||||||
|
T(dst->extratags)[i].id = strdup(T(src->extratags)[i].id);
|
||||||
|
T(dst->extratags)[i].size = T(src->extratags)[i].size;
|
||||||
|
T(dst->extratags)[i].selfclose = T(src->extratags)[i].selfclose;
|
||||||
|
}
|
||||||
|
}
|
||||||
14
tags.h
Normal file
14
tags.h
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
/* block-level tags for passing html blocks through the blender
|
||||||
|
*/
|
||||||
|
#ifndef _TAGS_D
|
||||||
|
#define _TAGS_D
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
struct kw* mkd_search_tags(MMIOT*, char *, int);
|
||||||
|
void mkd_sort_tags(MMIOT *);
|
||||||
|
void mkd_define_tag(MMIOT*, char *, int);
|
||||||
|
void ___mkd_copy_extratags(MMIOT *dst, MMIOT *src);
|
||||||
|
void ___mkd_delete_extratags(MMIOT *doc);
|
||||||
|
|
||||||
|
#endif
|
||||||
27
tests/autolink.t
Normal file
27
tests/autolink.t
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
. tests/functions.sh
|
||||||
|
|
||||||
|
title 'Reddit-style automatic links'
|
||||||
|
rc=0
|
||||||
|
|
||||||
|
try -fautolink 'single link' \
|
||||||
|
'http://www.pell.portland.or.us/~orc/Code/discount' \
|
||||||
|
'<p><a href="http://www.pell.portland.or.us/~orc/Code/discount">http://www.pell.portland.or.us/~orc/Code/discount</a></p>'
|
||||||
|
|
||||||
|
try -fautolink '[!](http://a.com "http://b.com")' \
|
||||||
|
'[!](http://a.com "http://b.com")' \
|
||||||
|
'<p><a href="http://a.com" title="http://b.com">!</a></p>'
|
||||||
|
|
||||||
|
try -fautolink 'link surrounded by text' \
|
||||||
|
'here http://it is?' \
|
||||||
|
'<p>here <a href="http://it">http://it</a> is?</p>'
|
||||||
|
|
||||||
|
try -fautolink 'naked @' '@' '<p>@</p>'
|
||||||
|
|
||||||
|
try -fautolink 'parenthesised (url)' \
|
||||||
|
'(http://here)' \
|
||||||
|
'<p>(<a href="http://here">http://here</a>)</p>'
|
||||||
|
|
||||||
|
try -fautolink 'token with trailing @' 'orc@' '<p>orc@</p>'
|
||||||
|
|
||||||
|
summary $0
|
||||||
|
exit $rc
|
||||||
28
tests/automatic.t
Normal file
28
tests/automatic.t
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
. tests/functions.sh
|
||||||
|
|
||||||
|
title "automatic links"
|
||||||
|
|
||||||
|
rc=0
|
||||||
|
MARKDOWN_FLAGS=
|
||||||
|
|
||||||
|
try 'http url' '<http://here>' '<p><a href="http://here">http://here</a></p>'
|
||||||
|
try 'ftp url' '<ftp://here>' '<p><a href="ftp://here">ftp://here</a></p>'
|
||||||
|
try 'http://foo/bar' '<http://foo/bar>' '<p><a href="http://foo/bar">http://foo/bar</a></p>'
|
||||||
|
try 'http:/foo/bar' '<http:/foo/bar>' '<p><a href="http:/foo/bar">http:/foo/bar</a></p>'
|
||||||
|
try 'http:foo/bar' '<http:foo/bar>' '<p><a href="http:foo/bar">http:foo/bar</a></p>'
|
||||||
|
try '</foo/bar>' '</foo/bar>' '<p></foo/bar></p>'
|
||||||
|
match '<orc@pell.portland.or.us>' '<orc@pell.portland.or.us>' '<a href='
|
||||||
|
match '<orc@pell.com.>' '<orc@pell.com.>' '<a href='
|
||||||
|
try 'invalid <orc@>' '<orc@>' '<p><orc@></p>'
|
||||||
|
try 'invalid <@orc@eightpoint.app>' '<@orc@eightpoint.app>' '<p><@orc@eightpoint.app></p>'
|
||||||
|
try 'invalid <@pell>' '<@pell>' '<p><@pell></p>'
|
||||||
|
try 'invalid <orc@pell>' '<orc@pell>' '<p><orc@pell></p>'
|
||||||
|
try 'invalid <orc@.pell>' '<orc@.pell>' '<p><orc@.pell></p>'
|
||||||
|
try 'invalid <orc@pell.>' '<orc@pell.>' '<p><orc@pell.></p>'
|
||||||
|
match '<mailto:orc@pell>' '<mailto:orc@pell>' '<a href='
|
||||||
|
match '<mailto:orc@pell.com>' '<mailto:orc@pell.com>' '<a href='
|
||||||
|
match '<mailto:orc@>' '<mailto:orc@>' '<a href='
|
||||||
|
match '<mailto:@pell>' '<mailto:@pell>' '<a href='
|
||||||
|
|
||||||
|
summary $0
|
||||||
|
exit $rc
|
||||||
21
tests/backslash.t
Normal file
21
tests/backslash.t
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
. tests/functions.sh
|
||||||
|
|
||||||
|
title "backslash escapes"
|
||||||
|
|
||||||
|
rc=0
|
||||||
|
MARKDOWN_FLAGS=
|
||||||
|
|
||||||
|
try 'backslashes in []()' '[foo](http://\this\is\.a\test\(here\))' \
|
||||||
|
'<p><a href="http://\this\is.a\test(here)">foo</a></p>'
|
||||||
|
|
||||||
|
try -fautolink 'autolink url with trailing \' \
|
||||||
|
'http://a.com/\' \
|
||||||
|
'<p><a href="http://a.com/\">http://a.com/\</a></p>'
|
||||||
|
|
||||||
|
|
||||||
|
try 'backslashes before <text' '\<code>' '<p>\<code></p>'
|
||||||
|
try 'backslashes before <{EOF}' '\<' '<p><</p>'
|
||||||
|
try 'backslashes before <[space]' '\< j' '<p>< j</p>'
|
||||||
|
|
||||||
|
summary $0
|
||||||
|
exit $rc
|
||||||
17
tests/callbacks.t
Normal file
17
tests/callbacks.t
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
. tests/functions.sh
|
||||||
|
|
||||||
|
title "callbacks"
|
||||||
|
|
||||||
|
rc=0
|
||||||
|
MARKDOWN_FLAGS=
|
||||||
|
|
||||||
|
try -bZZZ 'url modification' \
|
||||||
|
'[a](/b)' \
|
||||||
|
'<p><a href="ZZZ/b">a</a></p>'
|
||||||
|
|
||||||
|
try -EYYY 'additional flags' \
|
||||||
|
'[a](/b)' \
|
||||||
|
'<p><a href="/b" YYY>a</a></p>'
|
||||||
|
|
||||||
|
summary $0
|
||||||
|
exit $rc
|
||||||
13
tests/centered.t
Normal file
13
tests/centered.t
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
. tests/functions.sh
|
||||||
|
|
||||||
|
title "block centering"
|
||||||
|
|
||||||
|
rc=0
|
||||||
|
MARKDOWN_FLAGS=
|
||||||
|
|
||||||
|
try 'centered single-line paragraph' \
|
||||||
|
'->center<-' \
|
||||||
|
'<div style="text-align:center;">center</div>'
|
||||||
|
|
||||||
|
summary $0
|
||||||
|
exit $rc
|
||||||
13
tests/chrome.text
Normal file
13
tests/chrome.text
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
->###chrome with my markdown###<-
|
||||||
|
|
||||||
|
1. `(c)` -> `©` (c)
|
||||||
|
2. `(r)` -> `®` (r)
|
||||||
|
3. `(tm)` -> `™` (tm)
|
||||||
|
4. `...` -> `…` ...
|
||||||
|
5. `--` -> `&emdash;` --
|
||||||
|
6. `-` -> `–` - (but not if it's between-words)
|
||||||
|
7. "fancy quoting"
|
||||||
|
8. 'fancy quoting (#2)'
|
||||||
|
9. don't do it unless it's a real quote.
|
||||||
|
10. `` (`) ``
|
||||||
|
|
||||||
35
tests/code.t
Normal file
35
tests/code.t
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
. tests/functions.sh
|
||||||
|
|
||||||
|
title "inline code"
|
||||||
|
|
||||||
|
rc=0
|
||||||
|
MARKDOWN_FLAGS=
|
||||||
|
|
||||||
|
try 'format for code block html' \
|
||||||
|
' this is
|
||||||
|
code' \
|
||||||
|
'<pre><code>this is
|
||||||
|
code
|
||||||
|
</code></pre>'
|
||||||
|
|
||||||
|
try 'mismatched backticks' '```tick``' '<p><code>`tick</code></p>'
|
||||||
|
try 'mismatched backticks(2)' '``tick```' '<p>``tick```</p>'
|
||||||
|
try 'unclosed single backtick' '`hi there' '<p>`hi there</p>'
|
||||||
|
try 'unclosed double backtick' '``hi there' '<p>``hi there</p>'
|
||||||
|
try 'triple backticks' '```hi there```' '<p><code>hi there</code></p>'
|
||||||
|
try 'quadruple backticks' '````hi there````' '<p><code>hi there</code></p>'
|
||||||
|
try 'remove space around code' '`` hi there ``' '<p><code>hi there</code></p>'
|
||||||
|
try 'code containing backticks' '`` a```b ``' '<p><code>a```b</code></p>'
|
||||||
|
try 'backslash before backtick' '`a\`' '<p><code>a\</code></p>'
|
||||||
|
try '`>`' '`>`' '<p><code>></code></p>'
|
||||||
|
try '`` ` ``' '`` ` ``' '<p><code>`</code></p>'
|
||||||
|
try '````` ``` `' '````` ``` `' '<p><code>``</code> `</p>'
|
||||||
|
try '````` ` ```' '````` ` ```' '<p><code>`` `</code></p>'
|
||||||
|
try 'backslashes in code(1)' ' printf "%s: \n", $1;' \
|
||||||
|
'<pre><code>printf "%s: \n", $1;
|
||||||
|
</code></pre>'
|
||||||
|
try 'backslashes in code(2)' '`printf "%s: \n", $1;`' \
|
||||||
|
'<p><code>printf "%s: \n", $1;</code></p>'
|
||||||
|
|
||||||
|
summary $0
|
||||||
|
exit $rc
|
||||||
250
tests/codeblock.t
Normal file
250
tests/codeblock.t
Normal file
@ -0,0 +1,250 @@
|
|||||||
|
. tests/functions.sh
|
||||||
|
|
||||||
|
title "traditional code blocks"
|
||||||
|
|
||||||
|
rc=0
|
||||||
|
MARKDOWN_FLAGS=
|
||||||
|
|
||||||
|
try 'format for code block html' \
|
||||||
|
' this is
|
||||||
|
code' \
|
||||||
|
'<pre><code>this is
|
||||||
|
code
|
||||||
|
</code></pre>'
|
||||||
|
|
||||||
|
summary $0
|
||||||
|
|
||||||
|
title "fenced code blocks"
|
||||||
|
|
||||||
|
try 'fenced code disabled backtick' \
|
||||||
|
'```
|
||||||
|
|
||||||
|
unrecognized code!
|
||||||
|
```' \
|
||||||
|
'<p>```</p>
|
||||||
|
|
||||||
|
<p>unrecognized code!
|
||||||
|
```</p>'
|
||||||
|
|
||||||
|
try 'fenced code disabled backtick as inline code' \
|
||||||
|
'```
|
||||||
|
inline code?
|
||||||
|
```' \
|
||||||
|
'<p><code>
|
||||||
|
inline code?
|
||||||
|
</code></p>'
|
||||||
|
|
||||||
|
try 'fenced code disabled tilde' \
|
||||||
|
'~~~
|
||||||
|
|
||||||
|
unrecognized code!
|
||||||
|
~~~' \
|
||||||
|
'<p>~~~</p>
|
||||||
|
|
||||||
|
<p>unrecognized code!
|
||||||
|
~~~</p>'
|
||||||
|
|
||||||
|
try -ffencedcode 'fenced code block with blank lines' \
|
||||||
|
'~~~
|
||||||
|
code!
|
||||||
|
|
||||||
|
still code!
|
||||||
|
~~~' \
|
||||||
|
'<p><pre><code>code!
|
||||||
|
|
||||||
|
still code!
|
||||||
|
</code></pre>
|
||||||
|
</p>'
|
||||||
|
|
||||||
|
try -ffencedcode 'fenced code block' \
|
||||||
|
'~~~
|
||||||
|
code!
|
||||||
|
~~~' \
|
||||||
|
'<p><pre><code>code!
|
||||||
|
</code></pre>
|
||||||
|
</p>'
|
||||||
|
|
||||||
|
try -ffencedcode 'fenced code block in list' \
|
||||||
|
'1. ~~~
|
||||||
|
code block
|
||||||
|
~~~' \
|
||||||
|
'<ol>
|
||||||
|
<li><pre><code>code block
|
||||||
|
</code></pre>
|
||||||
|
</li>
|
||||||
|
</ol>'
|
||||||
|
|
||||||
|
try -ffencedcode 'fenced code block in blockquote' \
|
||||||
|
'>~~~
|
||||||
|
code
|
||||||
|
~~~' \
|
||||||
|
'<blockquote><p><pre><code>code
|
||||||
|
</code></pre>
|
||||||
|
</p></blockquote>'
|
||||||
|
|
||||||
|
try -ffencedcode 'unterminated fenced code block' \
|
||||||
|
'~~~
|
||||||
|
code' \
|
||||||
|
'<p>~~~
|
||||||
|
code</p>'
|
||||||
|
|
||||||
|
try -ffencedcode 'fenced code block with tildes' \
|
||||||
|
'~~~~~
|
||||||
|
~~~
|
||||||
|
code with tildes
|
||||||
|
~~~
|
||||||
|
~~~~~' \
|
||||||
|
'<p><pre><code>~~~
|
||||||
|
code with tildes
|
||||||
|
~~~
|
||||||
|
</code></pre>
|
||||||
|
</p>'
|
||||||
|
|
||||||
|
try -ffencedcode 'paragraph with trailing fenced block' \
|
||||||
|
'text text text
|
||||||
|
text text text
|
||||||
|
~~~
|
||||||
|
code code code?
|
||||||
|
~~~' \
|
||||||
|
'<p>text text text
|
||||||
|
text text text
|
||||||
|
<pre><code>code code code?
|
||||||
|
</code></pre>
|
||||||
|
</p>'
|
||||||
|
|
||||||
|
try -ffencedcode 'fenced code blocks with backtick delimiters' \
|
||||||
|
'```
|
||||||
|
code
|
||||||
|
```' \
|
||||||
|
'<p><pre><code>code
|
||||||
|
</code></pre>
|
||||||
|
</p>'
|
||||||
|
|
||||||
|
try -ffencedcode 'fenced code block with mismatched delimters' \
|
||||||
|
'```
|
||||||
|
code
|
||||||
|
~~~' \
|
||||||
|
'<p>```
|
||||||
|
code
|
||||||
|
~~~</p>'
|
||||||
|
|
||||||
|
try -ffencedcode 'fenced code block with lang attribute' \
|
||||||
|
'```lang
|
||||||
|
code
|
||||||
|
```' \
|
||||||
|
'<p><pre><code class="lang">code
|
||||||
|
</code></pre>
|
||||||
|
</p>'
|
||||||
|
|
||||||
|
try -ffencedcode 'fenced code block with lang-name attribute' \
|
||||||
|
'```lang-name
|
||||||
|
code
|
||||||
|
```' \
|
||||||
|
'<p><pre><code class="lang-name">code
|
||||||
|
</code></pre>
|
||||||
|
</p>'
|
||||||
|
|
||||||
|
try -ffencedcode 'fenced code block with lang_name attribute' \
|
||||||
|
'```lang_name
|
||||||
|
code
|
||||||
|
```' \
|
||||||
|
'<p><pre><code class="lang_name">code
|
||||||
|
</code></pre>
|
||||||
|
</p>'
|
||||||
|
|
||||||
|
try -ffencedcode 'fenced code block with lang attribute and space' \
|
||||||
|
'``` lang
|
||||||
|
code
|
||||||
|
```' \
|
||||||
|
'<p><pre><code class="lang">code
|
||||||
|
</code></pre>
|
||||||
|
</p>'
|
||||||
|
|
||||||
|
try -ffencedcode 'fenced code block with lang attribute and multiple spaces' \
|
||||||
|
'``` lang
|
||||||
|
code
|
||||||
|
```' \
|
||||||
|
'<p><pre><code class="lang">code
|
||||||
|
</code></pre>
|
||||||
|
</p>'
|
||||||
|
|
||||||
|
try -ffencedcode 'fenced code block with lang-name attribute and space' \
|
||||||
|
'``` lang-name
|
||||||
|
code
|
||||||
|
```' \
|
||||||
|
'<p><pre><code class="lang-name">code
|
||||||
|
</code></pre>
|
||||||
|
</p>'
|
||||||
|
|
||||||
|
try -ffencedcode 'fenced code block with lang_name attribute and space' \
|
||||||
|
'``` lang_name
|
||||||
|
code
|
||||||
|
```' \
|
||||||
|
'<p><pre><code class="lang_name">code
|
||||||
|
</code></pre>
|
||||||
|
</p>'
|
||||||
|
|
||||||
|
try -ffencedcode 'fenced code block with blank line in the middle' \
|
||||||
|
'```
|
||||||
|
hello
|
||||||
|
|
||||||
|
sailor
|
||||||
|
```' \
|
||||||
|
'<p><pre><code>hello
|
||||||
|
|
||||||
|
sailor
|
||||||
|
</code></pre>
|
||||||
|
</p>'
|
||||||
|
|
||||||
|
|
||||||
|
try -ffencedcode 'fenced code block with html in the middle' \
|
||||||
|
'~~~~
|
||||||
|
<h1>hello, sailor</h1>
|
||||||
|
~~~~' \
|
||||||
|
'<p><pre><code><h1>hello, sailor</h1>
|
||||||
|
</code></pre>
|
||||||
|
</p>'
|
||||||
|
|
||||||
|
try -ffencedcode 'fenced code block with trailing spaces in list item' \
|
||||||
|
'1. ~~~~
|
||||||
|
test me
|
||||||
|
~~~~' \
|
||||||
|
'<ol>
|
||||||
|
<li><pre><code>test me
|
||||||
|
</code></pre>
|
||||||
|
</li>
|
||||||
|
</ol>'
|
||||||
|
|
||||||
|
try -ffencedcode 'unterminated fenced code block' \
|
||||||
|
'~~~~
|
||||||
|
foo' \
|
||||||
|
'<p>~~~~
|
||||||
|
foo</p>'
|
||||||
|
|
||||||
|
try -ffencedcode 'paragraph, then code block' \
|
||||||
|
'foo
|
||||||
|
|
||||||
|
~~~~
|
||||||
|
bar
|
||||||
|
~~~~' \
|
||||||
|
'<p>foo</p>
|
||||||
|
|
||||||
|
<p><pre><code>bar
|
||||||
|
</code></pre>
|
||||||
|
</p>'
|
||||||
|
|
||||||
|
|
||||||
|
try -ffencedcode 'checkline misparse as fenced code' \
|
||||||
|
'[`label`](#code)
|
||||||
|
```class
|
||||||
|
content
|
||||||
|
```
|
||||||
|
' \
|
||||||
|
'<p><a href="#code"><code>label</code></a>
|
||||||
|
<pre><code class="class">content
|
||||||
|
</code></pre>
|
||||||
|
</p>'
|
||||||
|
|
||||||
|
|
||||||
|
summary $0
|
||||||
|
exit $rc
|
||||||
34
tests/compat.t
Normal file
34
tests/compat.t
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
. tests/functions.sh
|
||||||
|
|
||||||
|
title "markdown 1.0 compatibility"
|
||||||
|
|
||||||
|
rc=0
|
||||||
|
MARKDOWN_FLAGS=
|
||||||
|
|
||||||
|
LINKY='[this] is a test
|
||||||
|
|
||||||
|
[this]: /this'
|
||||||
|
|
||||||
|
try 'implicit reference links' "$LINKY" '<p><a href="/this">this</a> is a test</p>'
|
||||||
|
try -f1.0 'implicit reference links (-f1.0)' "$LINKY" '<p>[this] is a test</p>'
|
||||||
|
|
||||||
|
WSP=' '
|
||||||
|
WHITESPACE="
|
||||||
|
white space$WSP
|
||||||
|
and more"
|
||||||
|
|
||||||
|
try 'trailing whitespace' "$WHITESPACE" '<pre><code>white space ''
|
||||||
|
and more
|
||||||
|
</code></pre>'
|
||||||
|
|
||||||
|
try -f1.0 'trailing whitespace (-f1.0)' "$WHITESPACE" '<pre><code>white space''
|
||||||
|
and more
|
||||||
|
</code></pre>'
|
||||||
|
|
||||||
|
for x in tests/data/m_*.text;do
|
||||||
|
result=`echo $x | sed -e 's/.text$/.html/'`
|
||||||
|
try -fstrict,nopants,nosuperscript "`basename $x`" "`cat $x`" "`cat $result`"
|
||||||
|
done
|
||||||
|
|
||||||
|
summary $0
|
||||||
|
exit $rc
|
||||||
103
tests/crash.t
Normal file
103
tests/crash.t
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
. tests/functions.sh
|
||||||
|
|
||||||
|
title "crashes"
|
||||||
|
|
||||||
|
rc=0
|
||||||
|
MARKDOWN_FLAGS=
|
||||||
|
|
||||||
|
try 'zero-length input' '' ''
|
||||||
|
|
||||||
|
try 'hanging quote in list' \
|
||||||
|
' * > this should not die
|
||||||
|
|
||||||
|
no.' \
|
||||||
|
'<ul>
|
||||||
|
<li><blockquote><p>this should not die</p></blockquote></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
|
||||||
|
<p>no.</p>'
|
||||||
|
|
||||||
|
try 'dangling list item' ' - ' \
|
||||||
|
'<ul>
|
||||||
|
<li></li>
|
||||||
|
</ul>'
|
||||||
|
|
||||||
|
try -bHOHO 'empty []() with baseurl' '[]()' '<p><a href=""></a></p>'
|
||||||
|
try 'unclosed html block' '<table></table' '<p><table></table</p>'
|
||||||
|
try 'unclosed style block' '<style>' '<p><style></p>'
|
||||||
|
|
||||||
|
try -ftoc 'empty header with toc' '##' '<a name="L-23-"></a>
|
||||||
|
<h1>#</h1>'
|
||||||
|
|
||||||
|
try '-x -E aloha' 'using -E to add attributes to links' '[]()' '<p><a href="" aloha></a></p>'
|
||||||
|
try '-b hello -E world' 'using both -E & -b' '[a](/b) [a](/b)' '<p><a href="hello/b" world>a</a> <a href="hello/b" world>a</a></p>'
|
||||||
|
try '-x -E aloha' 'using -E to add attributes, but with two links' '[](1.png) [](2.png)' '<p><a href="1.png" aloha></a> <a href="2.png" aloha></a></p>'
|
||||||
|
|
||||||
|
try '-T' 'excessively long ETX header prefix' '#######################################################################################################################################################################################################################################################################################################################################################################################################' \
|
||||||
|
'<ul>
|
||||||
|
<li>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<ul>
|
||||||
|
<li><a href="#L-23-">#</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<a name="L-23-"></a>
|
||||||
|
<h6>#</h6>'
|
||||||
|
|
||||||
|
try '-d' 'dump an empty document' '%
|
||||||
|
%
|
||||||
|
%' ''
|
||||||
|
|
||||||
|
|
||||||
|
RESULT='<ul>
|
||||||
|
<li><a href="#header">header</a></li>
|
||||||
|
</ul>
|
||||||
|
<a name="header"></a>
|
||||||
|
<h1>header</h1>'
|
||||||
|
|
||||||
|
./rep '#header' '\t' 400 | try -T 'a header with a bunch of trailing tabs' -heredoc "$RESULT"
|
||||||
|
|
||||||
|
./rep '#header' ' ' 400 | try -T 'a header with a bunch of trailing spaces' -heredoc "$RESULT"
|
||||||
|
|
||||||
|
RESULT='<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>: Y:</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td></td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>'
|
||||||
|
|
||||||
|
cat << \EOF | try '-F 0x03000000' 'random input that looks like a table' -heredoc "$RESULT"
|
||||||
|
: Y:|
|
||||||
|
```|
|
||||||
|
|
|
||||||
|
```|
|
||||||
|
EOF
|
||||||
|
|
||||||
|
summary $0
|
||||||
|
exit $rc
|
||||||
9
tests/data/README
Normal file
9
tests/data/README
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
This directory contains source (.text) & expected output (.html)
|
||||||
|
for various test that are too complicated for placing the results
|
||||||
|
inline.
|
||||||
|
|
||||||
|
The prefix characters show which test script runs the tests
|
||||||
|
|
||||||
|
f -- markdown extra footnotes (extrafootnotes.t)
|
||||||
|
(f01.text -> f01.html)
|
||||||
|
m -- Markdown.pl conformity (Markdown.pl.t)
|
||||||
22
tests/data/f01.html
Normal file
22
tests/data/f01.html
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
<p>is there a footnote here?<sup id="fnref:1"><a href="#fn:1" rel="footnote">1</a></sup></p>
|
||||||
|
|
||||||
|
<p>And this is not part of the footnote</p>
|
||||||
|
<div class="footnotes">
|
||||||
|
<hr/>
|
||||||
|
<ol>
|
||||||
|
<li id="fn:1">
|
||||||
|
<p>Yes, and it should have text</p>
|
||||||
|
|
||||||
|
<p><code>
|
||||||
|
code
|
||||||
|
</code></p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>And</li>
|
||||||
|
<li>A</li>
|
||||||
|
<li>List</li>
|
||||||
|
</ul>
|
||||||
|
<a href="#fnref:1" rev="footnote">↩</a></li>
|
||||||
|
</ol>
|
||||||
|
</div>
|
||||||
|
|
||||||
15
tests/data/f01.text
Normal file
15
tests/data/f01.text
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
is there a footnote here?[^1]
|
||||||
|
|
||||||
|
[^1]:
|
||||||
|
Yes, and it should have text
|
||||||
|
|
||||||
|
````
|
||||||
|
code
|
||||||
|
````
|
||||||
|
|
||||||
|
* And
|
||||||
|
* A
|
||||||
|
* List
|
||||||
|
|
||||||
|
|
||||||
|
And this is not part of the footnote
|
||||||
189
tests/data/m_embed.html
Normal file
189
tests/data/m_embed.html
Normal file
@ -0,0 +1,189 @@
|
|||||||
|
<p>32: <ab -it></p>
|
||||||
|
|
||||||
|
<p>33: <ab!-it></p>
|
||||||
|
|
||||||
|
<p>34: <ab"-it></p>
|
||||||
|
|
||||||
|
<p>35: <ab#-it></p>
|
||||||
|
|
||||||
|
<p>36: <ab$-it></p>
|
||||||
|
|
||||||
|
<p>37: <ab%-it></p>
|
||||||
|
|
||||||
|
<p>38: <ab&-it></p>
|
||||||
|
|
||||||
|
<p>39: <ab'-it></p>
|
||||||
|
|
||||||
|
<p>40: <ab(-it></p>
|
||||||
|
|
||||||
|
<p>41: <ab)-it></p>
|
||||||
|
|
||||||
|
<p>42: <ab*-it></p>
|
||||||
|
|
||||||
|
<p>43: <ab+-it></p>
|
||||||
|
|
||||||
|
<p>44: <ab,-it></p>
|
||||||
|
|
||||||
|
<p>45: <ab--it></p>
|
||||||
|
|
||||||
|
<p>46: <ab.-it></p>
|
||||||
|
|
||||||
|
<p>47: <ab/-it></p>
|
||||||
|
|
||||||
|
<p>48: <ab0-it></p>
|
||||||
|
|
||||||
|
<p>49: <ab1-it></p>
|
||||||
|
|
||||||
|
<p>50: <ab2-it></p>
|
||||||
|
|
||||||
|
<p>51: <ab3-it></p>
|
||||||
|
|
||||||
|
<p>52: <ab4-it></p>
|
||||||
|
|
||||||
|
<p>53: <ab5-it></p>
|
||||||
|
|
||||||
|
<p>54: <ab6-it></p>
|
||||||
|
|
||||||
|
<p>55: <ab7-it></p>
|
||||||
|
|
||||||
|
<p>56: <ab8-it></p>
|
||||||
|
|
||||||
|
<p>57: <ab9-it></p>
|
||||||
|
|
||||||
|
<p>58: <ab:-it></p>
|
||||||
|
|
||||||
|
<p>59: <ab;-it></p>
|
||||||
|
|
||||||
|
<p>60: <ab<-it></p>
|
||||||
|
|
||||||
|
<p>61: <ab=-it></p>
|
||||||
|
|
||||||
|
<p>62: <ab>-it></p>
|
||||||
|
|
||||||
|
<p>63: <ab?-it></p>
|
||||||
|
|
||||||
|
<p>64: <ab@-it></p>
|
||||||
|
|
||||||
|
<p>65: <abA-it></p>
|
||||||
|
|
||||||
|
<p>66: <abB-it></p>
|
||||||
|
|
||||||
|
<p>67: <abC-it></p>
|
||||||
|
|
||||||
|
<p>68: <abD-it></p>
|
||||||
|
|
||||||
|
<p>69: <abE-it></p>
|
||||||
|
|
||||||
|
<p>70: <abF-it></p>
|
||||||
|
|
||||||
|
<p>71: <abG-it></p>
|
||||||
|
|
||||||
|
<p>72: <abH-it></p>
|
||||||
|
|
||||||
|
<p>73: <abI-it></p>
|
||||||
|
|
||||||
|
<p>74: <abJ-it></p>
|
||||||
|
|
||||||
|
<p>75: <abK-it></p>
|
||||||
|
|
||||||
|
<p>76: <abL-it></p>
|
||||||
|
|
||||||
|
<p>77: <abM-it></p>
|
||||||
|
|
||||||
|
<p>78: <abN-it></p>
|
||||||
|
|
||||||
|
<p>79: <abO-it></p>
|
||||||
|
|
||||||
|
<p>80: <abP-it></p>
|
||||||
|
|
||||||
|
<p>81: <abQ-it></p>
|
||||||
|
|
||||||
|
<p>82: <abR-it></p>
|
||||||
|
|
||||||
|
<p>83: <abS-it></p>
|
||||||
|
|
||||||
|
<p>84: <abT-it></p>
|
||||||
|
|
||||||
|
<p>85: <abU-it></p>
|
||||||
|
|
||||||
|
<p>86: <abV-it></p>
|
||||||
|
|
||||||
|
<p>87: <abW-it></p>
|
||||||
|
|
||||||
|
<p>88: <abX-it></p>
|
||||||
|
|
||||||
|
<p>89: <abY-it></p>
|
||||||
|
|
||||||
|
<p>90: <abZ-it></p>
|
||||||
|
|
||||||
|
<p>91: <ab[-it></p>
|
||||||
|
|
||||||
|
<p>92: <ab\-it></p>
|
||||||
|
|
||||||
|
<p>93: <ab]-it></p>
|
||||||
|
|
||||||
|
<p>94: <ab^-it></p>
|
||||||
|
|
||||||
|
<p>95: <ab_-it></p>
|
||||||
|
|
||||||
|
<p>96: <ab`-it></p>
|
||||||
|
|
||||||
|
<p>97: <aba-it></p>
|
||||||
|
|
||||||
|
<p>98: <abb-it></p>
|
||||||
|
|
||||||
|
<p>99: <abc-it></p>
|
||||||
|
|
||||||
|
<p>100: <abd-it></p>
|
||||||
|
|
||||||
|
<p>101: <abe-it></p>
|
||||||
|
|
||||||
|
<p>102: <abf-it></p>
|
||||||
|
|
||||||
|
<p>103: <abg-it></p>
|
||||||
|
|
||||||
|
<p>104: <abh-it></p>
|
||||||
|
|
||||||
|
<p>105: <abi-it></p>
|
||||||
|
|
||||||
|
<p>106: <abj-it></p>
|
||||||
|
|
||||||
|
<p>107: <abk-it></p>
|
||||||
|
|
||||||
|
<p>108: <abl-it></p>
|
||||||
|
|
||||||
|
<p>109: <abm-it></p>
|
||||||
|
|
||||||
|
<p>110: <abn-it></p>
|
||||||
|
|
||||||
|
<p>111: <abo-it></p>
|
||||||
|
|
||||||
|
<p>112: <abp-it></p>
|
||||||
|
|
||||||
|
<p>113: <abq-it></p>
|
||||||
|
|
||||||
|
<p>114: <abr-it></p>
|
||||||
|
|
||||||
|
<p>115: <abs-it></p>
|
||||||
|
|
||||||
|
<p>116: <abt-it></p>
|
||||||
|
|
||||||
|
<p>117: <abu-it></p>
|
||||||
|
|
||||||
|
<p>118: <abv-it></p>
|
||||||
|
|
||||||
|
<p>119: <abw-it></p>
|
||||||
|
|
||||||
|
<p>120: <abx-it></p>
|
||||||
|
|
||||||
|
<p>121: <aby-it></p>
|
||||||
|
|
||||||
|
<p>122: <abz-it></p>
|
||||||
|
|
||||||
|
<p>123: <ab{-it></p>
|
||||||
|
|
||||||
|
<p>124: <ab|-it></p>
|
||||||
|
|
||||||
|
<p>125: <ab}-it></p>
|
||||||
|
|
||||||
|
<p>126: <ab~-it></p>
|
||||||
190
tests/data/m_embed.text
Normal file
190
tests/data/m_embed.text
Normal file
@ -0,0 +1,190 @@
|
|||||||
|
32: <ab -it>
|
||||||
|
|
||||||
|
33: <ab!-it>
|
||||||
|
|
||||||
|
34: <ab"-it>
|
||||||
|
|
||||||
|
35: <ab#-it>
|
||||||
|
|
||||||
|
36: <ab$-it>
|
||||||
|
|
||||||
|
37: <ab%-it>
|
||||||
|
|
||||||
|
38: <ab&-it>
|
||||||
|
|
||||||
|
39: <ab'-it>
|
||||||
|
|
||||||
|
40: <ab(-it>
|
||||||
|
|
||||||
|
41: <ab)-it>
|
||||||
|
|
||||||
|
42: <ab*-it>
|
||||||
|
|
||||||
|
43: <ab+-it>
|
||||||
|
|
||||||
|
44: <ab,-it>
|
||||||
|
|
||||||
|
45: <ab--it>
|
||||||
|
|
||||||
|
46: <ab.-it>
|
||||||
|
|
||||||
|
47: <ab/-it>
|
||||||
|
|
||||||
|
48: <ab0-it>
|
||||||
|
|
||||||
|
49: <ab1-it>
|
||||||
|
|
||||||
|
50: <ab2-it>
|
||||||
|
|
||||||
|
51: <ab3-it>
|
||||||
|
|
||||||
|
52: <ab4-it>
|
||||||
|
|
||||||
|
53: <ab5-it>
|
||||||
|
|
||||||
|
54: <ab6-it>
|
||||||
|
|
||||||
|
55: <ab7-it>
|
||||||
|
|
||||||
|
56: <ab8-it>
|
||||||
|
|
||||||
|
57: <ab9-it>
|
||||||
|
|
||||||
|
58: <ab:-it>
|
||||||
|
|
||||||
|
59: <ab;-it>
|
||||||
|
|
||||||
|
60: <ab<-it>
|
||||||
|
|
||||||
|
61: <ab=-it>
|
||||||
|
|
||||||
|
62: <ab>-it>
|
||||||
|
|
||||||
|
63: <ab?-it>
|
||||||
|
|
||||||
|
64: <ab@-it>
|
||||||
|
|
||||||
|
65: <abA-it>
|
||||||
|
|
||||||
|
66: <abB-it>
|
||||||
|
|
||||||
|
67: <abC-it>
|
||||||
|
|
||||||
|
68: <abD-it>
|
||||||
|
|
||||||
|
69: <abE-it>
|
||||||
|
|
||||||
|
70: <abF-it>
|
||||||
|
|
||||||
|
71: <abG-it>
|
||||||
|
|
||||||
|
72: <abH-it>
|
||||||
|
|
||||||
|
73: <abI-it>
|
||||||
|
|
||||||
|
74: <abJ-it>
|
||||||
|
|
||||||
|
75: <abK-it>
|
||||||
|
|
||||||
|
76: <abL-it>
|
||||||
|
|
||||||
|
77: <abM-it>
|
||||||
|
|
||||||
|
78: <abN-it>
|
||||||
|
|
||||||
|
79: <abO-it>
|
||||||
|
|
||||||
|
80: <abP-it>
|
||||||
|
|
||||||
|
81: <abQ-it>
|
||||||
|
|
||||||
|
82: <abR-it>
|
||||||
|
|
||||||
|
83: <abS-it>
|
||||||
|
|
||||||
|
84: <abT-it>
|
||||||
|
|
||||||
|
85: <abU-it>
|
||||||
|
|
||||||
|
86: <abV-it>
|
||||||
|
|
||||||
|
87: <abW-it>
|
||||||
|
|
||||||
|
88: <abX-it>
|
||||||
|
|
||||||
|
89: <abY-it>
|
||||||
|
|
||||||
|
90: <abZ-it>
|
||||||
|
|
||||||
|
91: <ab[-it>
|
||||||
|
|
||||||
|
92: <ab\-it>
|
||||||
|
|
||||||
|
93: <ab]-it>
|
||||||
|
|
||||||
|
94: <ab^-it>
|
||||||
|
|
||||||
|
95: <ab_-it>
|
||||||
|
|
||||||
|
96: <ab`-it>
|
||||||
|
|
||||||
|
97: <aba-it>
|
||||||
|
|
||||||
|
98: <abb-it>
|
||||||
|
|
||||||
|
99: <abc-it>
|
||||||
|
|
||||||
|
100: <abd-it>
|
||||||
|
|
||||||
|
101: <abe-it>
|
||||||
|
|
||||||
|
102: <abf-it>
|
||||||
|
|
||||||
|
103: <abg-it>
|
||||||
|
|
||||||
|
104: <abh-it>
|
||||||
|
|
||||||
|
105: <abi-it>
|
||||||
|
|
||||||
|
106: <abj-it>
|
||||||
|
|
||||||
|
107: <abk-it>
|
||||||
|
|
||||||
|
108: <abl-it>
|
||||||
|
|
||||||
|
109: <abm-it>
|
||||||
|
|
||||||
|
110: <abn-it>
|
||||||
|
|
||||||
|
111: <abo-it>
|
||||||
|
|
||||||
|
112: <abp-it>
|
||||||
|
|
||||||
|
113: <abq-it>
|
||||||
|
|
||||||
|
114: <abr-it>
|
||||||
|
|
||||||
|
115: <abs-it>
|
||||||
|
|
||||||
|
116: <abt-it>
|
||||||
|
|
||||||
|
117: <abu-it>
|
||||||
|
|
||||||
|
118: <abv-it>
|
||||||
|
|
||||||
|
119: <abw-it>
|
||||||
|
|
||||||
|
120: <abx-it>
|
||||||
|
|
||||||
|
121: <aby-it>
|
||||||
|
|
||||||
|
122: <abz-it>
|
||||||
|
|
||||||
|
123: <ab{-it>
|
||||||
|
|
||||||
|
124: <ab|-it>
|
||||||
|
|
||||||
|
125: <ab}-it>
|
||||||
|
|
||||||
|
126: <ab~-it>
|
||||||
|
|
||||||
189
tests/data/m_leading.html
Normal file
189
tests/data/m_leading.html
Normal file
@ -0,0 +1,189 @@
|
|||||||
|
<p>32: < -it></p>
|
||||||
|
|
||||||
|
<p>33: <!-it></p>
|
||||||
|
|
||||||
|
<p>34: <"-it></p>
|
||||||
|
|
||||||
|
<p>35: <#-it></p>
|
||||||
|
|
||||||
|
<p>36: <$-it></p>
|
||||||
|
|
||||||
|
<p>37: <%-it></p>
|
||||||
|
|
||||||
|
<p>38: <&-it></p>
|
||||||
|
|
||||||
|
<p>39: <'-it></p>
|
||||||
|
|
||||||
|
<p>40: <(-it></p>
|
||||||
|
|
||||||
|
<p>41: <)-it></p>
|
||||||
|
|
||||||
|
<p>42: <*-it></p>
|
||||||
|
|
||||||
|
<p>43: <+-it></p>
|
||||||
|
|
||||||
|
<p>44: <,-it></p>
|
||||||
|
|
||||||
|
<p>45: <--it></p>
|
||||||
|
|
||||||
|
<p>46: <.-it></p>
|
||||||
|
|
||||||
|
<p>47: </-it></p>
|
||||||
|
|
||||||
|
<p>48: <0-it></p>
|
||||||
|
|
||||||
|
<p>49: <1-it></p>
|
||||||
|
|
||||||
|
<p>50: <2-it></p>
|
||||||
|
|
||||||
|
<p>51: <3-it></p>
|
||||||
|
|
||||||
|
<p>52: <4-it></p>
|
||||||
|
|
||||||
|
<p>53: <5-it></p>
|
||||||
|
|
||||||
|
<p>54: <6-it></p>
|
||||||
|
|
||||||
|
<p>55: <7-it></p>
|
||||||
|
|
||||||
|
<p>56: <8-it></p>
|
||||||
|
|
||||||
|
<p>57: <9-it></p>
|
||||||
|
|
||||||
|
<p>58: <:-it></p>
|
||||||
|
|
||||||
|
<p>59: <;-it></p>
|
||||||
|
|
||||||
|
<p>60: <<-it></p>
|
||||||
|
|
||||||
|
<p>61: <=-it></p>
|
||||||
|
|
||||||
|
<p>62: <>-it></p>
|
||||||
|
|
||||||
|
<p>63: <?-it></p>
|
||||||
|
|
||||||
|
<p>64: <@-it></p>
|
||||||
|
|
||||||
|
<p>65: <A-it></p>
|
||||||
|
|
||||||
|
<p>66: <B-it></p>
|
||||||
|
|
||||||
|
<p>67: <C-it></p>
|
||||||
|
|
||||||
|
<p>68: <D-it></p>
|
||||||
|
|
||||||
|
<p>69: <E-it></p>
|
||||||
|
|
||||||
|
<p>70: <F-it></p>
|
||||||
|
|
||||||
|
<p>71: <G-it></p>
|
||||||
|
|
||||||
|
<p>72: <H-it></p>
|
||||||
|
|
||||||
|
<p>73: <I-it></p>
|
||||||
|
|
||||||
|
<p>74: <J-it></p>
|
||||||
|
|
||||||
|
<p>75: <K-it></p>
|
||||||
|
|
||||||
|
<p>76: <L-it></p>
|
||||||
|
|
||||||
|
<p>77: <M-it></p>
|
||||||
|
|
||||||
|
<p>78: <N-it></p>
|
||||||
|
|
||||||
|
<p>79: <O-it></p>
|
||||||
|
|
||||||
|
<p>80: <P-it></p>
|
||||||
|
|
||||||
|
<p>81: <Q-it></p>
|
||||||
|
|
||||||
|
<p>82: <R-it></p>
|
||||||
|
|
||||||
|
<p>83: <S-it></p>
|
||||||
|
|
||||||
|
<p>84: <T-it></p>
|
||||||
|
|
||||||
|
<p>85: <U-it></p>
|
||||||
|
|
||||||
|
<p>86: <V-it></p>
|
||||||
|
|
||||||
|
<p>87: <W-it></p>
|
||||||
|
|
||||||
|
<p>88: <X-it></p>
|
||||||
|
|
||||||
|
<p>89: <Y-it></p>
|
||||||
|
|
||||||
|
<p>90: <Z-it></p>
|
||||||
|
|
||||||
|
<p>91: <[-it></p>
|
||||||
|
|
||||||
|
<p>92: <-it></p>
|
||||||
|
|
||||||
|
<p>93: <]-it></p>
|
||||||
|
|
||||||
|
<p>94: <^-it></p>
|
||||||
|
|
||||||
|
<p>95: <_-it></p>
|
||||||
|
|
||||||
|
<p>96: <`-it></p>
|
||||||
|
|
||||||
|
<p>97: <a-it></p>
|
||||||
|
|
||||||
|
<p>98: <b-it></p>
|
||||||
|
|
||||||
|
<p>99: <c-it></p>
|
||||||
|
|
||||||
|
<p>100: <d-it></p>
|
||||||
|
|
||||||
|
<p>101: <e-it></p>
|
||||||
|
|
||||||
|
<p>102: <f-it></p>
|
||||||
|
|
||||||
|
<p>103: <g-it></p>
|
||||||
|
|
||||||
|
<p>104: <h-it></p>
|
||||||
|
|
||||||
|
<p>105: <i-it></p>
|
||||||
|
|
||||||
|
<p>106: <j-it></p>
|
||||||
|
|
||||||
|
<p>107: <k-it></p>
|
||||||
|
|
||||||
|
<p>108: <l-it></p>
|
||||||
|
|
||||||
|
<p>109: <m-it></p>
|
||||||
|
|
||||||
|
<p>110: <n-it></p>
|
||||||
|
|
||||||
|
<p>111: <o-it></p>
|
||||||
|
|
||||||
|
<p>112: <p-it></p>
|
||||||
|
|
||||||
|
<p>113: <q-it></p>
|
||||||
|
|
||||||
|
<p>114: <r-it></p>
|
||||||
|
|
||||||
|
<p>115: <s-it></p>
|
||||||
|
|
||||||
|
<p>116: <t-it></p>
|
||||||
|
|
||||||
|
<p>117: <u-it></p>
|
||||||
|
|
||||||
|
<p>118: <v-it></p>
|
||||||
|
|
||||||
|
<p>119: <w-it></p>
|
||||||
|
|
||||||
|
<p>120: <x-it></p>
|
||||||
|
|
||||||
|
<p>121: <y-it></p>
|
||||||
|
|
||||||
|
<p>122: <z-it></p>
|
||||||
|
|
||||||
|
<p>123: <{-it></p>
|
||||||
|
|
||||||
|
<p>124: <|-it></p>
|
||||||
|
|
||||||
|
<p>125: <}-it></p>
|
||||||
|
|
||||||
|
<p>126: <~-it></p>
|
||||||
190
tests/data/m_leading.text
Normal file
190
tests/data/m_leading.text
Normal file
@ -0,0 +1,190 @@
|
|||||||
|
32: < -it>
|
||||||
|
|
||||||
|
33: <!-it>
|
||||||
|
|
||||||
|
34: <"-it>
|
||||||
|
|
||||||
|
35: <#-it>
|
||||||
|
|
||||||
|
36: <$-it>
|
||||||
|
|
||||||
|
37: <%-it>
|
||||||
|
|
||||||
|
38: <&-it>
|
||||||
|
|
||||||
|
39: <'-it>
|
||||||
|
|
||||||
|
40: <(-it>
|
||||||
|
|
||||||
|
41: <)-it>
|
||||||
|
|
||||||
|
42: <*-it>
|
||||||
|
|
||||||
|
43: <+-it>
|
||||||
|
|
||||||
|
44: <,-it>
|
||||||
|
|
||||||
|
45: <--it>
|
||||||
|
|
||||||
|
46: <.-it>
|
||||||
|
|
||||||
|
47: </-it>
|
||||||
|
|
||||||
|
48: <0-it>
|
||||||
|
|
||||||
|
49: <1-it>
|
||||||
|
|
||||||
|
50: <2-it>
|
||||||
|
|
||||||
|
51: <3-it>
|
||||||
|
|
||||||
|
52: <4-it>
|
||||||
|
|
||||||
|
53: <5-it>
|
||||||
|
|
||||||
|
54: <6-it>
|
||||||
|
|
||||||
|
55: <7-it>
|
||||||
|
|
||||||
|
56: <8-it>
|
||||||
|
|
||||||
|
57: <9-it>
|
||||||
|
|
||||||
|
58: <:-it>
|
||||||
|
|
||||||
|
59: <;-it>
|
||||||
|
|
||||||
|
60: <<-it>
|
||||||
|
|
||||||
|
61: <=-it>
|
||||||
|
|
||||||
|
62: <>-it>
|
||||||
|
|
||||||
|
63: <?-it>
|
||||||
|
|
||||||
|
64: <@-it>
|
||||||
|
|
||||||
|
65: <A-it>
|
||||||
|
|
||||||
|
66: <B-it>
|
||||||
|
|
||||||
|
67: <C-it>
|
||||||
|
|
||||||
|
68: <D-it>
|
||||||
|
|
||||||
|
69: <E-it>
|
||||||
|
|
||||||
|
70: <F-it>
|
||||||
|
|
||||||
|
71: <G-it>
|
||||||
|
|
||||||
|
72: <H-it>
|
||||||
|
|
||||||
|
73: <I-it>
|
||||||
|
|
||||||
|
74: <J-it>
|
||||||
|
|
||||||
|
75: <K-it>
|
||||||
|
|
||||||
|
76: <L-it>
|
||||||
|
|
||||||
|
77: <M-it>
|
||||||
|
|
||||||
|
78: <N-it>
|
||||||
|
|
||||||
|
79: <O-it>
|
||||||
|
|
||||||
|
80: <P-it>
|
||||||
|
|
||||||
|
81: <Q-it>
|
||||||
|
|
||||||
|
82: <R-it>
|
||||||
|
|
||||||
|
83: <S-it>
|
||||||
|
|
||||||
|
84: <T-it>
|
||||||
|
|
||||||
|
85: <U-it>
|
||||||
|
|
||||||
|
86: <V-it>
|
||||||
|
|
||||||
|
87: <W-it>
|
||||||
|
|
||||||
|
88: <X-it>
|
||||||
|
|
||||||
|
89: <Y-it>
|
||||||
|
|
||||||
|
90: <Z-it>
|
||||||
|
|
||||||
|
91: <[-it>
|
||||||
|
|
||||||
|
92: <\-it>
|
||||||
|
|
||||||
|
93: <]-it>
|
||||||
|
|
||||||
|
94: <^-it>
|
||||||
|
|
||||||
|
95: <_-it>
|
||||||
|
|
||||||
|
96: <`-it>
|
||||||
|
|
||||||
|
97: <a-it>
|
||||||
|
|
||||||
|
98: <b-it>
|
||||||
|
|
||||||
|
99: <c-it>
|
||||||
|
|
||||||
|
100: <d-it>
|
||||||
|
|
||||||
|
101: <e-it>
|
||||||
|
|
||||||
|
102: <f-it>
|
||||||
|
|
||||||
|
103: <g-it>
|
||||||
|
|
||||||
|
104: <h-it>
|
||||||
|
|
||||||
|
105: <i-it>
|
||||||
|
|
||||||
|
106: <j-it>
|
||||||
|
|
||||||
|
107: <k-it>
|
||||||
|
|
||||||
|
108: <l-it>
|
||||||
|
|
||||||
|
109: <m-it>
|
||||||
|
|
||||||
|
110: <n-it>
|
||||||
|
|
||||||
|
111: <o-it>
|
||||||
|
|
||||||
|
112: <p-it>
|
||||||
|
|
||||||
|
113: <q-it>
|
||||||
|
|
||||||
|
114: <r-it>
|
||||||
|
|
||||||
|
115: <s-it>
|
||||||
|
|
||||||
|
116: <t-it>
|
||||||
|
|
||||||
|
117: <u-it>
|
||||||
|
|
||||||
|
118: <v-it>
|
||||||
|
|
||||||
|
119: <w-it>
|
||||||
|
|
||||||
|
120: <x-it>
|
||||||
|
|
||||||
|
121: <y-it>
|
||||||
|
|
||||||
|
122: <z-it>
|
||||||
|
|
||||||
|
123: <{-it>
|
||||||
|
|
||||||
|
124: <|-it>
|
||||||
|
|
||||||
|
125: <}-it>
|
||||||
|
|
||||||
|
126: <~-it>
|
||||||
|
|
||||||
189
tests/data/m_onechar.html
Normal file
189
tests/data/m_onechar.html
Normal file
@ -0,0 +1,189 @@
|
|||||||
|
<p>32: <ab it></p>
|
||||||
|
|
||||||
|
<p>33: <ab!it></p>
|
||||||
|
|
||||||
|
<p>34: <ab"it></p>
|
||||||
|
|
||||||
|
<p>35: <ab#it></p>
|
||||||
|
|
||||||
|
<p>36: <ab$it></p>
|
||||||
|
|
||||||
|
<p>37: <ab%it></p>
|
||||||
|
|
||||||
|
<p>38: <ab&it></p>
|
||||||
|
|
||||||
|
<p>39: <ab'it></p>
|
||||||
|
|
||||||
|
<p>40: <ab(it></p>
|
||||||
|
|
||||||
|
<p>41: <ab)it></p>
|
||||||
|
|
||||||
|
<p>42: <ab*it></p>
|
||||||
|
|
||||||
|
<p>43: <ab+it></p>
|
||||||
|
|
||||||
|
<p>44: <ab,it></p>
|
||||||
|
|
||||||
|
<p>45: <ab-it></p>
|
||||||
|
|
||||||
|
<p>46: <ab.it></p>
|
||||||
|
|
||||||
|
<p>47: <ab/it></p>
|
||||||
|
|
||||||
|
<p>48: <ab0it></p>
|
||||||
|
|
||||||
|
<p>49: <ab1it></p>
|
||||||
|
|
||||||
|
<p>50: <ab2it></p>
|
||||||
|
|
||||||
|
<p>51: <ab3it></p>
|
||||||
|
|
||||||
|
<p>52: <ab4it></p>
|
||||||
|
|
||||||
|
<p>53: <ab5it></p>
|
||||||
|
|
||||||
|
<p>54: <ab6it></p>
|
||||||
|
|
||||||
|
<p>55: <ab7it></p>
|
||||||
|
|
||||||
|
<p>56: <ab8it></p>
|
||||||
|
|
||||||
|
<p>57: <ab9it></p>
|
||||||
|
|
||||||
|
<p>58: <ab:it></p>
|
||||||
|
|
||||||
|
<p>59: <ab;it></p>
|
||||||
|
|
||||||
|
<p>60: <ab<it></p>
|
||||||
|
|
||||||
|
<p>61: <ab=it></p>
|
||||||
|
|
||||||
|
<p>62: <ab>it></p>
|
||||||
|
|
||||||
|
<p>63: <ab?it></p>
|
||||||
|
|
||||||
|
<p>64: <ab@it></p>
|
||||||
|
|
||||||
|
<p>65: <abAit></p>
|
||||||
|
|
||||||
|
<p>66: <abBit></p>
|
||||||
|
|
||||||
|
<p>67: <abCit></p>
|
||||||
|
|
||||||
|
<p>68: <abDit></p>
|
||||||
|
|
||||||
|
<p>69: <abEit></p>
|
||||||
|
|
||||||
|
<p>70: <abFit></p>
|
||||||
|
|
||||||
|
<p>71: <abGit></p>
|
||||||
|
|
||||||
|
<p>72: <abHit></p>
|
||||||
|
|
||||||
|
<p>73: <abIit></p>
|
||||||
|
|
||||||
|
<p>74: <abJit></p>
|
||||||
|
|
||||||
|
<p>75: <abKit></p>
|
||||||
|
|
||||||
|
<p>76: <abLit></p>
|
||||||
|
|
||||||
|
<p>77: <abMit></p>
|
||||||
|
|
||||||
|
<p>78: <abNit></p>
|
||||||
|
|
||||||
|
<p>79: <abOit></p>
|
||||||
|
|
||||||
|
<p>80: <abPit></p>
|
||||||
|
|
||||||
|
<p>81: <abQit></p>
|
||||||
|
|
||||||
|
<p>82: <abRit></p>
|
||||||
|
|
||||||
|
<p>83: <abSit></p>
|
||||||
|
|
||||||
|
<p>84: <abTit></p>
|
||||||
|
|
||||||
|
<p>85: <abUit></p>
|
||||||
|
|
||||||
|
<p>86: <abVit></p>
|
||||||
|
|
||||||
|
<p>87: <abWit></p>
|
||||||
|
|
||||||
|
<p>88: <abXit></p>
|
||||||
|
|
||||||
|
<p>89: <abYit></p>
|
||||||
|
|
||||||
|
<p>90: <abZit></p>
|
||||||
|
|
||||||
|
<p>91: <ab[it></p>
|
||||||
|
|
||||||
|
<p>92: <ab\it></p>
|
||||||
|
|
||||||
|
<p>93: <ab]it></p>
|
||||||
|
|
||||||
|
<p>94: <ab^it></p>
|
||||||
|
|
||||||
|
<p>95: <ab_it></p>
|
||||||
|
|
||||||
|
<p>96: <ab`it></p>
|
||||||
|
|
||||||
|
<p>97: <abait></p>
|
||||||
|
|
||||||
|
<p>98: <abbit></p>
|
||||||
|
|
||||||
|
<p>99: <abcit></p>
|
||||||
|
|
||||||
|
<p>100: <abdit></p>
|
||||||
|
|
||||||
|
<p>101: <abeit></p>
|
||||||
|
|
||||||
|
<p>102: <abfit></p>
|
||||||
|
|
||||||
|
<p>103: <abgit></p>
|
||||||
|
|
||||||
|
<p>104: <abhit></p>
|
||||||
|
|
||||||
|
<p>105: <abiit></p>
|
||||||
|
|
||||||
|
<p>106: <abjit></p>
|
||||||
|
|
||||||
|
<p>107: <abkit></p>
|
||||||
|
|
||||||
|
<p>108: <ablit></p>
|
||||||
|
|
||||||
|
<p>109: <abmit></p>
|
||||||
|
|
||||||
|
<p>110: <abnit></p>
|
||||||
|
|
||||||
|
<p>111: <aboit></p>
|
||||||
|
|
||||||
|
<p>112: <abpit></p>
|
||||||
|
|
||||||
|
<p>113: <abqit></p>
|
||||||
|
|
||||||
|
<p>114: <abrit></p>
|
||||||
|
|
||||||
|
<p>115: <absit></p>
|
||||||
|
|
||||||
|
<p>116: <abtit></p>
|
||||||
|
|
||||||
|
<p>117: <abuit></p>
|
||||||
|
|
||||||
|
<p>118: <abvit></p>
|
||||||
|
|
||||||
|
<p>119: <abwit></p>
|
||||||
|
|
||||||
|
<p>120: <abxit></p>
|
||||||
|
|
||||||
|
<p>121: <abyit></p>
|
||||||
|
|
||||||
|
<p>122: <abzit></p>
|
||||||
|
|
||||||
|
<p>123: <ab{it></p>
|
||||||
|
|
||||||
|
<p>124: <ab|it></p>
|
||||||
|
|
||||||
|
<p>125: <ab}it></p>
|
||||||
|
|
||||||
|
<p>126: <ab~it></p>
|
||||||
190
tests/data/m_onechar.text
Normal file
190
tests/data/m_onechar.text
Normal file
@ -0,0 +1,190 @@
|
|||||||
|
32: <ab it>
|
||||||
|
|
||||||
|
33: <ab!it>
|
||||||
|
|
||||||
|
34: <ab"it>
|
||||||
|
|
||||||
|
35: <ab#it>
|
||||||
|
|
||||||
|
36: <ab$it>
|
||||||
|
|
||||||
|
37: <ab%it>
|
||||||
|
|
||||||
|
38: <ab&it>
|
||||||
|
|
||||||
|
39: <ab'it>
|
||||||
|
|
||||||
|
40: <ab(it>
|
||||||
|
|
||||||
|
41: <ab)it>
|
||||||
|
|
||||||
|
42: <ab*it>
|
||||||
|
|
||||||
|
43: <ab+it>
|
||||||
|
|
||||||
|
44: <ab,it>
|
||||||
|
|
||||||
|
45: <ab-it>
|
||||||
|
|
||||||
|
46: <ab.it>
|
||||||
|
|
||||||
|
47: <ab/it>
|
||||||
|
|
||||||
|
48: <ab0it>
|
||||||
|
|
||||||
|
49: <ab1it>
|
||||||
|
|
||||||
|
50: <ab2it>
|
||||||
|
|
||||||
|
51: <ab3it>
|
||||||
|
|
||||||
|
52: <ab4it>
|
||||||
|
|
||||||
|
53: <ab5it>
|
||||||
|
|
||||||
|
54: <ab6it>
|
||||||
|
|
||||||
|
55: <ab7it>
|
||||||
|
|
||||||
|
56: <ab8it>
|
||||||
|
|
||||||
|
57: <ab9it>
|
||||||
|
|
||||||
|
58: <ab:it>
|
||||||
|
|
||||||
|
59: <ab;it>
|
||||||
|
|
||||||
|
60: <ab<it>
|
||||||
|
|
||||||
|
61: <ab=it>
|
||||||
|
|
||||||
|
62: <ab>it>
|
||||||
|
|
||||||
|
63: <ab?it>
|
||||||
|
|
||||||
|
64: <ab@it>
|
||||||
|
|
||||||
|
65: <abAit>
|
||||||
|
|
||||||
|
66: <abBit>
|
||||||
|
|
||||||
|
67: <abCit>
|
||||||
|
|
||||||
|
68: <abDit>
|
||||||
|
|
||||||
|
69: <abEit>
|
||||||
|
|
||||||
|
70: <abFit>
|
||||||
|
|
||||||
|
71: <abGit>
|
||||||
|
|
||||||
|
72: <abHit>
|
||||||
|
|
||||||
|
73: <abIit>
|
||||||
|
|
||||||
|
74: <abJit>
|
||||||
|
|
||||||
|
75: <abKit>
|
||||||
|
|
||||||
|
76: <abLit>
|
||||||
|
|
||||||
|
77: <abMit>
|
||||||
|
|
||||||
|
78: <abNit>
|
||||||
|
|
||||||
|
79: <abOit>
|
||||||
|
|
||||||
|
80: <abPit>
|
||||||
|
|
||||||
|
81: <abQit>
|
||||||
|
|
||||||
|
82: <abRit>
|
||||||
|
|
||||||
|
83: <abSit>
|
||||||
|
|
||||||
|
84: <abTit>
|
||||||
|
|
||||||
|
85: <abUit>
|
||||||
|
|
||||||
|
86: <abVit>
|
||||||
|
|
||||||
|
87: <abWit>
|
||||||
|
|
||||||
|
88: <abXit>
|
||||||
|
|
||||||
|
89: <abYit>
|
||||||
|
|
||||||
|
90: <abZit>
|
||||||
|
|
||||||
|
91: <ab[it>
|
||||||
|
|
||||||
|
92: <ab\it>
|
||||||
|
|
||||||
|
93: <ab]it>
|
||||||
|
|
||||||
|
94: <ab^it>
|
||||||
|
|
||||||
|
95: <ab_it>
|
||||||
|
|
||||||
|
96: <ab`it>
|
||||||
|
|
||||||
|
97: <abait>
|
||||||
|
|
||||||
|
98: <abbit>
|
||||||
|
|
||||||
|
99: <abcit>
|
||||||
|
|
||||||
|
100: <abdit>
|
||||||
|
|
||||||
|
101: <abeit>
|
||||||
|
|
||||||
|
102: <abfit>
|
||||||
|
|
||||||
|
103: <abgit>
|
||||||
|
|
||||||
|
104: <abhit>
|
||||||
|
|
||||||
|
105: <abiit>
|
||||||
|
|
||||||
|
106: <abjit>
|
||||||
|
|
||||||
|
107: <abkit>
|
||||||
|
|
||||||
|
108: <ablit>
|
||||||
|
|
||||||
|
109: <abmit>
|
||||||
|
|
||||||
|
110: <abnit>
|
||||||
|
|
||||||
|
111: <aboit>
|
||||||
|
|
||||||
|
112: <abpit>
|
||||||
|
|
||||||
|
113: <abqit>
|
||||||
|
|
||||||
|
114: <abrit>
|
||||||
|
|
||||||
|
115: <absit>
|
||||||
|
|
||||||
|
116: <abtit>
|
||||||
|
|
||||||
|
117: <abuit>
|
||||||
|
|
||||||
|
118: <abvit>
|
||||||
|
|
||||||
|
119: <abwit>
|
||||||
|
|
||||||
|
120: <abxit>
|
||||||
|
|
||||||
|
121: <abyit>
|
||||||
|
|
||||||
|
122: <abzit>
|
||||||
|
|
||||||
|
123: <ab{it>
|
||||||
|
|
||||||
|
124: <ab|it>
|
||||||
|
|
||||||
|
125: <ab}it>
|
||||||
|
|
||||||
|
126: <ab~it>
|
||||||
|
|
||||||
189
tests/data/m_paired.html
Normal file
189
tests/data/m_paired.html
Normal file
@ -0,0 +1,189 @@
|
|||||||
|
<p>32: <ab it>32</ab it></p>
|
||||||
|
|
||||||
|
<p>33: <ab!it>33</ab!it></p>
|
||||||
|
|
||||||
|
<p>34: <ab"it>34</ab"it></p>
|
||||||
|
|
||||||
|
<p>35: <ab#it>35</ab#it></p>
|
||||||
|
|
||||||
|
<p>36: <ab$it>36</ab$it></p>
|
||||||
|
|
||||||
|
<p>37: <ab%it>37</ab%it></p>
|
||||||
|
|
||||||
|
<p>38: <ab&it>38</ab&it></p>
|
||||||
|
|
||||||
|
<p>39: <ab'it>39</ab'it></p>
|
||||||
|
|
||||||
|
<p>40: <ab(it>40</ab(it></p>
|
||||||
|
|
||||||
|
<p>41: <ab)it>41</ab)it></p>
|
||||||
|
|
||||||
|
<p>42: <ab*it>42</ab*it></p>
|
||||||
|
|
||||||
|
<p>43: <ab+it>43</ab+it></p>
|
||||||
|
|
||||||
|
<p>44: <ab,it>44</ab,it></p>
|
||||||
|
|
||||||
|
<p>45: <ab-it>45</ab-it></p>
|
||||||
|
|
||||||
|
<p>46: <ab.it>46</ab.it></p>
|
||||||
|
|
||||||
|
<p>47: <ab/it>47</ab/it></p>
|
||||||
|
|
||||||
|
<p>48: <ab0it>48</ab0it></p>
|
||||||
|
|
||||||
|
<p>49: <ab1it>49</ab1it></p>
|
||||||
|
|
||||||
|
<p>50: <ab2it>50</ab2it></p>
|
||||||
|
|
||||||
|
<p>51: <ab3it>51</ab3it></p>
|
||||||
|
|
||||||
|
<p>52: <ab4it>52</ab4it></p>
|
||||||
|
|
||||||
|
<p>53: <ab5it>53</ab5it></p>
|
||||||
|
|
||||||
|
<p>54: <ab6it>54</ab6it></p>
|
||||||
|
|
||||||
|
<p>55: <ab7it>55</ab7it></p>
|
||||||
|
|
||||||
|
<p>56: <ab8it>56</ab8it></p>
|
||||||
|
|
||||||
|
<p>57: <ab9it>57</ab9it></p>
|
||||||
|
|
||||||
|
<p>58: <ab:it>58</ab:it></p>
|
||||||
|
|
||||||
|
<p>59: <ab;it>59</ab;it></p>
|
||||||
|
|
||||||
|
<p>60: <ab<it>60</ab<it></p>
|
||||||
|
|
||||||
|
<p>61: <ab=it>61</ab=it></p>
|
||||||
|
|
||||||
|
<p>62: <ab>it>62</ab>it></p>
|
||||||
|
|
||||||
|
<p>63: <ab?it>63</ab?it></p>
|
||||||
|
|
||||||
|
<p>64: <ab@it>64</ab@it></p>
|
||||||
|
|
||||||
|
<p>65: <abAit>65</abAit></p>
|
||||||
|
|
||||||
|
<p>66: <abBit>66</abBit></p>
|
||||||
|
|
||||||
|
<p>67: <abCit>67</abCit></p>
|
||||||
|
|
||||||
|
<p>68: <abDit>68</abDit></p>
|
||||||
|
|
||||||
|
<p>69: <abEit>69</abEit></p>
|
||||||
|
|
||||||
|
<p>70: <abFit>70</abFit></p>
|
||||||
|
|
||||||
|
<p>71: <abGit>71</abGit></p>
|
||||||
|
|
||||||
|
<p>72: <abHit>72</abHit></p>
|
||||||
|
|
||||||
|
<p>73: <abIit>73</abIit></p>
|
||||||
|
|
||||||
|
<p>74: <abJit>74</abJit></p>
|
||||||
|
|
||||||
|
<p>75: <abKit>75</abKit></p>
|
||||||
|
|
||||||
|
<p>76: <abLit>76</abLit></p>
|
||||||
|
|
||||||
|
<p>77: <abMit>77</abMit></p>
|
||||||
|
|
||||||
|
<p>78: <abNit>78</abNit></p>
|
||||||
|
|
||||||
|
<p>79: <abOit>79</abOit></p>
|
||||||
|
|
||||||
|
<p>80: <abPit>80</abPit></p>
|
||||||
|
|
||||||
|
<p>81: <abQit>81</abQit></p>
|
||||||
|
|
||||||
|
<p>82: <abRit>82</abRit></p>
|
||||||
|
|
||||||
|
<p>83: <abSit>83</abSit></p>
|
||||||
|
|
||||||
|
<p>84: <abTit>84</abTit></p>
|
||||||
|
|
||||||
|
<p>85: <abUit>85</abUit></p>
|
||||||
|
|
||||||
|
<p>86: <abVit>86</abVit></p>
|
||||||
|
|
||||||
|
<p>87: <abWit>87</abWit></p>
|
||||||
|
|
||||||
|
<p>88: <abXit>88</abXit></p>
|
||||||
|
|
||||||
|
<p>89: <abYit>89</abYit></p>
|
||||||
|
|
||||||
|
<p>90: <abZit>90</abZit></p>
|
||||||
|
|
||||||
|
<p>91: <ab[it>91</ab[it></p>
|
||||||
|
|
||||||
|
<p>92: <ab\it>92</ab\it></p>
|
||||||
|
|
||||||
|
<p>93: <ab]it>93</ab]it></p>
|
||||||
|
|
||||||
|
<p>94: <ab^it>94</ab^it></p>
|
||||||
|
|
||||||
|
<p>95: <ab_it>95</ab_it></p>
|
||||||
|
|
||||||
|
<p>96: <ab<code>it>96</ab</code>it></p>
|
||||||
|
|
||||||
|
<p>97: <abait>97</abait></p>
|
||||||
|
|
||||||
|
<p>98: <abbit>98</abbit></p>
|
||||||
|
|
||||||
|
<p>99: <abcit>99</abcit></p>
|
||||||
|
|
||||||
|
<p>100: <abdit>100</abdit></p>
|
||||||
|
|
||||||
|
<p>101: <abeit>101</abeit></p>
|
||||||
|
|
||||||
|
<p>102: <abfit>102</abfit></p>
|
||||||
|
|
||||||
|
<p>103: <abgit>103</abgit></p>
|
||||||
|
|
||||||
|
<p>104: <abhit>104</abhit></p>
|
||||||
|
|
||||||
|
<p>105: <abiit>105</abiit></p>
|
||||||
|
|
||||||
|
<p>106: <abjit>106</abjit></p>
|
||||||
|
|
||||||
|
<p>107: <abkit>107</abkit></p>
|
||||||
|
|
||||||
|
<p>108: <ablit>108</ablit></p>
|
||||||
|
|
||||||
|
<p>109: <abmit>109</abmit></p>
|
||||||
|
|
||||||
|
<p>110: <abnit>110</abnit></p>
|
||||||
|
|
||||||
|
<p>111: <aboit>111</aboit></p>
|
||||||
|
|
||||||
|
<p>112: <abpit>112</abpit></p>
|
||||||
|
|
||||||
|
<p>113: <abqit>113</abqit></p>
|
||||||
|
|
||||||
|
<p>114: <abrit>114</abrit></p>
|
||||||
|
|
||||||
|
<p>115: <absit>115</absit></p>
|
||||||
|
|
||||||
|
<p>116: <abtit>116</abtit></p>
|
||||||
|
|
||||||
|
<p>117: <abuit>117</abuit></p>
|
||||||
|
|
||||||
|
<p>118: <abvit>118</abvit></p>
|
||||||
|
|
||||||
|
<p>119: <abwit>119</abwit></p>
|
||||||
|
|
||||||
|
<p>120: <abxit>120</abxit></p>
|
||||||
|
|
||||||
|
<p>121: <abyit>121</abyit></p>
|
||||||
|
|
||||||
|
<p>122: <abzit>122</abzit></p>
|
||||||
|
|
||||||
|
<p>123: <ab{it>123</ab{it></p>
|
||||||
|
|
||||||
|
<p>124: <ab|it>124</ab|it></p>
|
||||||
|
|
||||||
|
<p>125: <ab}it>125</ab}it></p>
|
||||||
|
|
||||||
|
<p>126: <ab~it>126</ab~it></p>
|
||||||
190
tests/data/m_paired.text
Normal file
190
tests/data/m_paired.text
Normal file
@ -0,0 +1,190 @@
|
|||||||
|
32: <ab it>32</ab it>
|
||||||
|
|
||||||
|
33: <ab!it>33</ab!it>
|
||||||
|
|
||||||
|
34: <ab"it>34</ab"it>
|
||||||
|
|
||||||
|
35: <ab#it>35</ab#it>
|
||||||
|
|
||||||
|
36: <ab$it>36</ab$it>
|
||||||
|
|
||||||
|
37: <ab%it>37</ab%it>
|
||||||
|
|
||||||
|
38: <ab&it>38</ab&it>
|
||||||
|
|
||||||
|
39: <ab'it>39</ab'it>
|
||||||
|
|
||||||
|
40: <ab(it>40</ab(it>
|
||||||
|
|
||||||
|
41: <ab)it>41</ab)it>
|
||||||
|
|
||||||
|
42: <ab*it>42</ab*it>
|
||||||
|
|
||||||
|
43: <ab+it>43</ab+it>
|
||||||
|
|
||||||
|
44: <ab,it>44</ab,it>
|
||||||
|
|
||||||
|
45: <ab-it>45</ab-it>
|
||||||
|
|
||||||
|
46: <ab.it>46</ab.it>
|
||||||
|
|
||||||
|
47: <ab/it>47</ab/it>
|
||||||
|
|
||||||
|
48: <ab0it>48</ab0it>
|
||||||
|
|
||||||
|
49: <ab1it>49</ab1it>
|
||||||
|
|
||||||
|
50: <ab2it>50</ab2it>
|
||||||
|
|
||||||
|
51: <ab3it>51</ab3it>
|
||||||
|
|
||||||
|
52: <ab4it>52</ab4it>
|
||||||
|
|
||||||
|
53: <ab5it>53</ab5it>
|
||||||
|
|
||||||
|
54: <ab6it>54</ab6it>
|
||||||
|
|
||||||
|
55: <ab7it>55</ab7it>
|
||||||
|
|
||||||
|
56: <ab8it>56</ab8it>
|
||||||
|
|
||||||
|
57: <ab9it>57</ab9it>
|
||||||
|
|
||||||
|
58: <ab:it>58</ab:it>
|
||||||
|
|
||||||
|
59: <ab;it>59</ab;it>
|
||||||
|
|
||||||
|
60: <ab<it>60</ab<it>
|
||||||
|
|
||||||
|
61: <ab=it>61</ab=it>
|
||||||
|
|
||||||
|
62: <ab>it>62</ab>it>
|
||||||
|
|
||||||
|
63: <ab?it>63</ab?it>
|
||||||
|
|
||||||
|
64: <ab@it>64</ab@it>
|
||||||
|
|
||||||
|
65: <abAit>65</abAit>
|
||||||
|
|
||||||
|
66: <abBit>66</abBit>
|
||||||
|
|
||||||
|
67: <abCit>67</abCit>
|
||||||
|
|
||||||
|
68: <abDit>68</abDit>
|
||||||
|
|
||||||
|
69: <abEit>69</abEit>
|
||||||
|
|
||||||
|
70: <abFit>70</abFit>
|
||||||
|
|
||||||
|
71: <abGit>71</abGit>
|
||||||
|
|
||||||
|
72: <abHit>72</abHit>
|
||||||
|
|
||||||
|
73: <abIit>73</abIit>
|
||||||
|
|
||||||
|
74: <abJit>74</abJit>
|
||||||
|
|
||||||
|
75: <abKit>75</abKit>
|
||||||
|
|
||||||
|
76: <abLit>76</abLit>
|
||||||
|
|
||||||
|
77: <abMit>77</abMit>
|
||||||
|
|
||||||
|
78: <abNit>78</abNit>
|
||||||
|
|
||||||
|
79: <abOit>79</abOit>
|
||||||
|
|
||||||
|
80: <abPit>80</abPit>
|
||||||
|
|
||||||
|
81: <abQit>81</abQit>
|
||||||
|
|
||||||
|
82: <abRit>82</abRit>
|
||||||
|
|
||||||
|
83: <abSit>83</abSit>
|
||||||
|
|
||||||
|
84: <abTit>84</abTit>
|
||||||
|
|
||||||
|
85: <abUit>85</abUit>
|
||||||
|
|
||||||
|
86: <abVit>86</abVit>
|
||||||
|
|
||||||
|
87: <abWit>87</abWit>
|
||||||
|
|
||||||
|
88: <abXit>88</abXit>
|
||||||
|
|
||||||
|
89: <abYit>89</abYit>
|
||||||
|
|
||||||
|
90: <abZit>90</abZit>
|
||||||
|
|
||||||
|
91: <ab[it>91</ab[it>
|
||||||
|
|
||||||
|
92: <ab\it>92</ab\it>
|
||||||
|
|
||||||
|
93: <ab]it>93</ab]it>
|
||||||
|
|
||||||
|
94: <ab^it>94</ab^it>
|
||||||
|
|
||||||
|
95: <ab_it>95</ab_it>
|
||||||
|
|
||||||
|
96: <ab`it>96</ab`it>
|
||||||
|
|
||||||
|
97: <abait>97</abait>
|
||||||
|
|
||||||
|
98: <abbit>98</abbit>
|
||||||
|
|
||||||
|
99: <abcit>99</abcit>
|
||||||
|
|
||||||
|
100: <abdit>100</abdit>
|
||||||
|
|
||||||
|
101: <abeit>101</abeit>
|
||||||
|
|
||||||
|
102: <abfit>102</abfit>
|
||||||
|
|
||||||
|
103: <abgit>103</abgit>
|
||||||
|
|
||||||
|
104: <abhit>104</abhit>
|
||||||
|
|
||||||
|
105: <abiit>105</abiit>
|
||||||
|
|
||||||
|
106: <abjit>106</abjit>
|
||||||
|
|
||||||
|
107: <abkit>107</abkit>
|
||||||
|
|
||||||
|
108: <ablit>108</ablit>
|
||||||
|
|
||||||
|
109: <abmit>109</abmit>
|
||||||
|
|
||||||
|
110: <abnit>110</abnit>
|
||||||
|
|
||||||
|
111: <aboit>111</aboit>
|
||||||
|
|
||||||
|
112: <abpit>112</abpit>
|
||||||
|
|
||||||
|
113: <abqit>113</abqit>
|
||||||
|
|
||||||
|
114: <abrit>114</abrit>
|
||||||
|
|
||||||
|
115: <absit>115</absit>
|
||||||
|
|
||||||
|
116: <abtit>116</abtit>
|
||||||
|
|
||||||
|
117: <abuit>117</abuit>
|
||||||
|
|
||||||
|
118: <abvit>118</abvit>
|
||||||
|
|
||||||
|
119: <abwit>119</abwit>
|
||||||
|
|
||||||
|
120: <abxit>120</abxit>
|
||||||
|
|
||||||
|
121: <abyit>121</abyit>
|
||||||
|
|
||||||
|
122: <abzit>122</abzit>
|
||||||
|
|
||||||
|
123: <ab{it>123</ab{it>
|
||||||
|
|
||||||
|
124: <ab|it>124</ab|it>
|
||||||
|
|
||||||
|
125: <ab}it>125</ab}it>
|
||||||
|
|
||||||
|
126: <ab~it>126</ab~it>
|
||||||
|
|
||||||
25
tests/defects.t
Normal file
25
tests/defects.t
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
. tests/functions.sh
|
||||||
|
|
||||||
|
title "reported defects"
|
||||||
|
|
||||||
|
rc=0
|
||||||
|
MARKDOWN_FLAGS=
|
||||||
|
|
||||||
|
try 'masses of non-block html' \
|
||||||
|
'<span>foo</span><br>
|
||||||
|
<br>
|
||||||
|
<span>bar</span><br>' \
|
||||||
|
'<p><span>foo</span><br>
|
||||||
|
<br>
|
||||||
|
<span>bar</span><br></p>'
|
||||||
|
|
||||||
|
try -fautolink -G 'autolink + github-flavoured markdown' \
|
||||||
|
'http://foo
|
||||||
|
bar' \
|
||||||
|
'<p><a href="http://foo">http://foo</a><br/>
|
||||||
|
bar</p>'
|
||||||
|
|
||||||
|
try 'unterminated <p> block' '<p></>*' '<p><p></>*</p>'
|
||||||
|
|
||||||
|
summary $0
|
||||||
|
exit $rc
|
||||||
54
tests/div.t
Normal file
54
tests/div.t
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
. tests/functions.sh
|
||||||
|
|
||||||
|
title "%div% blocks"
|
||||||
|
|
||||||
|
rc=0
|
||||||
|
MARKDOWN_FLAGS=
|
||||||
|
|
||||||
|
try 'simple >%div% block' \
|
||||||
|
'>%this%
|
||||||
|
this this' \
|
||||||
|
'<div class="this"><p>this this</p></div>'
|
||||||
|
|
||||||
|
try 'two >%div% blocks in a row' \
|
||||||
|
'>%this%
|
||||||
|
this this
|
||||||
|
|
||||||
|
>%that%
|
||||||
|
that that' \
|
||||||
|
'<div class="this"><p>this this</p></div>
|
||||||
|
|
||||||
|
<div class="that"><p>that that</p></div>'
|
||||||
|
|
||||||
|
try 'a >%div% block with two classes' \
|
||||||
|
'>%this that%
|
||||||
|
this that' \
|
||||||
|
'<div class="this that"><p>this that</p></div>'
|
||||||
|
|
||||||
|
try '>%class:div%' \
|
||||||
|
'>%class:this%
|
||||||
|
this this' \
|
||||||
|
'<div class="this"><p>this this</p></div>'
|
||||||
|
|
||||||
|
try '>%id:div%' \
|
||||||
|
'>%id:this%
|
||||||
|
this this' \
|
||||||
|
'<div id="this"><p>this this</p></div>'
|
||||||
|
|
||||||
|
try 'nested >%div%' \
|
||||||
|
'>%this%
|
||||||
|
>>%that%
|
||||||
|
>>that
|
||||||
|
|
||||||
|
>%more%
|
||||||
|
more' \
|
||||||
|
'<div class="this"><div class="that"><p>that</p></div></div>
|
||||||
|
|
||||||
|
<div class="more"><p>more</p></div>'
|
||||||
|
|
||||||
|
try '%class% with _' '>%class:this_that%' '<div class="this_that"></div>'
|
||||||
|
try '%class% with -' '>%class:this-that%' '<div class="this-that"></div>'
|
||||||
|
try 'illegal %class%' '>%class:0zip%' '<blockquote><p>%class:0zip%</p></blockquote>'
|
||||||
|
|
||||||
|
summary $0
|
||||||
|
exit $rc
|
||||||
101
tests/dl.t
Normal file
101
tests/dl.t
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
. tests/functions.sh
|
||||||
|
|
||||||
|
title "definition lists"
|
||||||
|
|
||||||
|
rc=0
|
||||||
|
MARKDOWN_FLAGS=
|
||||||
|
|
||||||
|
SRC='
|
||||||
|
=this=
|
||||||
|
is an ugly
|
||||||
|
=test=
|
||||||
|
eh?'
|
||||||
|
|
||||||
|
RSLT='<dl>
|
||||||
|
<dt>this</dt>
|
||||||
|
<dd>is an ugly</dd>
|
||||||
|
<dt>test</dt>
|
||||||
|
<dd>eh?</dd>
|
||||||
|
</dl>'
|
||||||
|
|
||||||
|
# discount style
|
||||||
|
try -fdldiscount '=tag= generates definition lists' "$SRC" "$RSLT"
|
||||||
|
|
||||||
|
try -fdldiscount 'one item with two =tags=' \
|
||||||
|
'=this=
|
||||||
|
=is=
|
||||||
|
A test, eh?' \
|
||||||
|
'<dl>
|
||||||
|
<dt>this</dt>
|
||||||
|
<dt>is</dt>
|
||||||
|
<dd>A test, eh?</dd>
|
||||||
|
</dl>'
|
||||||
|
|
||||||
|
# extra style
|
||||||
|
try -fdlextra,nodldiscount '=tag= does nothing' "$SRC" \
|
||||||
|
'<p>=this=
|
||||||
|
is an ugly
|
||||||
|
=test=
|
||||||
|
eh?</p>'
|
||||||
|
|
||||||
|
try -fdlextra 'markdown extra-style definition lists' \
|
||||||
|
'foo
|
||||||
|
: bar' \
|
||||||
|
'<dl>
|
||||||
|
<dt>foo</dt>
|
||||||
|
<dd>bar</dd>
|
||||||
|
</dl>'
|
||||||
|
|
||||||
|
try -fdlextra '... with two <dt>s in a row' \
|
||||||
|
'foo
|
||||||
|
bar
|
||||||
|
: baz' \
|
||||||
|
'<dl>
|
||||||
|
<dt>foo</dt>
|
||||||
|
<dt>bar</dt>
|
||||||
|
<dd>baz</dd>
|
||||||
|
</dl>'
|
||||||
|
|
||||||
|
try -fdlextra '... with two <dd>s in a row' \
|
||||||
|
'foo
|
||||||
|
: bar
|
||||||
|
: baz' \
|
||||||
|
'<dl>
|
||||||
|
<dt>foo</dt>
|
||||||
|
<dd>bar</dd>
|
||||||
|
<dd>baz</dd>
|
||||||
|
</dl>'
|
||||||
|
|
||||||
|
try -fdlextra '... with blanks between list items' \
|
||||||
|
'foo
|
||||||
|
: bar
|
||||||
|
|
||||||
|
zip
|
||||||
|
: zap' \
|
||||||
|
'<dl>
|
||||||
|
<dt>foo</dt>
|
||||||
|
<dd>bar</dd>
|
||||||
|
<dt>zip</dt>
|
||||||
|
<dd>zap</dd>
|
||||||
|
</dl>'
|
||||||
|
|
||||||
|
# Hmm, redundancy...
|
||||||
|
SRC='foo
|
||||||
|
: bar
|
||||||
|
|
||||||
|
=this=
|
||||||
|
is ugly'
|
||||||
|
RSLT='<p>foo
|
||||||
|
: bar</p>
|
||||||
|
|
||||||
|
<p>=this=
|
||||||
|
is ugly</p>'
|
||||||
|
try -fdlist,nodldiscount,nodlextra '... with definitionlists enabled but all styles disabled' \
|
||||||
|
"$SRC" \
|
||||||
|
"$RSLT"
|
||||||
|
#try -fnodefinitionlist,dldiscount,dlextra '... with definitionlists disabled but all styles enabled' \
|
||||||
|
# "$SRC" \
|
||||||
|
# "$RSLT"
|
||||||
|
|
||||||
|
summary $0
|
||||||
|
exit $rc
|
||||||
13
tests/e_url.t
Normal file
13
tests/e_url.t
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
. tests/functions.sh
|
||||||
|
|
||||||
|
title "mkd_basename (e_url)"
|
||||||
|
|
||||||
|
rc=0
|
||||||
|
MARKDOWN_FLAGS=
|
||||||
|
|
||||||
|
try -bHOHO 'empty []() with baseurl' '[]()' '<p><a href=""></a></p>'
|
||||||
|
try -bHOHO '[]() with full url' '[](http://foo)' '<p><a href="http://foo"></a></p>'
|
||||||
|
try -bHOHO '[]() with url fragment' '[](/foo)' '<p><a href="HOHO/foo"></a></p>'
|
||||||
|
|
||||||
|
summary $0
|
||||||
|
exit $rc
|
||||||
9
tests/embedlinks.text
Normal file
9
tests/embedlinks.text
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
* [] (http://dustmite.org)
|
||||||
|
* [[an embedded link](http://wontwork.org)](http://willwork.org)
|
||||||
|
* [![dustmite][]] (http:/dustmite.org)
|
||||||
|
* ![dustmite][]
|
||||||
|
* ![dustmite][dustmite]
|
||||||
|
* [<a href="http://cheating.us">cheat me</a>](http://I.am.cheating)
|
||||||
|
|
||||||
|
[dustmite]: http://dustmite.org/mite.jpg =25x25 "here I am!"
|
||||||
|
|
||||||
19
tests/emphasis.t
Normal file
19
tests/emphasis.t
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
. tests/functions.sh
|
||||||
|
|
||||||
|
title "emphasis"
|
||||||
|
|
||||||
|
rc=0
|
||||||
|
MARKDOWN_FLAGS=
|
||||||
|
|
||||||
|
try '*hi* -> <em>hi</em>' '*hi*' '<p><em>hi</em></p>'
|
||||||
|
try '* -> *' 'A * A' '<p>A * A</p>'
|
||||||
|
try -fstrict '***A**B*' '***A**B*' '<p><em><strong>A</strong>B</em></p>'
|
||||||
|
try -fstrict '***A*B**' '***A*B**' '<p><strong><em>A</em>B</strong></p>'
|
||||||
|
try -fstrict '**A*B***' '**A*B***' '<p><strong>A<em>B</em></strong></p>'
|
||||||
|
try -fstrict '*A**B***' '*A**B***' '<p><em>A<strong>B</strong></em></p>'
|
||||||
|
|
||||||
|
try -frelax '_A_B with -frelax' '_A_B' '<p>_A_B</p>'
|
||||||
|
try -fstrict '_A_B with -fstrict' '_A_B' '<p><em>A</em>B</p>'
|
||||||
|
|
||||||
|
summary $0
|
||||||
|
exit $rc
|
||||||
40
tests/exercisers/flags.c
Normal file
40
tests/exercisers/flags.c
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <mkdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
void
|
||||||
|
say(char *what)
|
||||||
|
{
|
||||||
|
fputs(what,stdout);
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
main(void)
|
||||||
|
{
|
||||||
|
mkd_flag_t *flags = mkd_flags();
|
||||||
|
|
||||||
|
|
||||||
|
say("check flag functions: ");
|
||||||
|
say("set ");
|
||||||
|
mkd_set_flag_num(flags, MKD_DLDISCOUNT);
|
||||||
|
|
||||||
|
say("set(0) ");
|
||||||
|
mkd_set_flag_num(0, MKD_DLDISCOUNT);
|
||||||
|
|
||||||
|
say("clear ");
|
||||||
|
mkd_clr_flag_num(flags, MKD_DLDISCOUNT);
|
||||||
|
|
||||||
|
say("clear(0) ");
|
||||||
|
mkd_clr_flag_num(0, MKD_DLDISCOUNT);
|
||||||
|
|
||||||
|
say("copy ");
|
||||||
|
(void)mkd_copy_flags(flags);
|
||||||
|
|
||||||
|
say("copy(0) ");
|
||||||
|
(void)mkd_copy_flags(0);
|
||||||
|
|
||||||
|
say("ok\n");
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
16
tests/exercisers/make.include
Normal file
16
tests/exercisers/make.include
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
exercisers=tests/exercisers
|
||||||
|
|
||||||
|
EXERCISE=$(exercisers)/flags
|
||||||
|
|
||||||
|
TESTFRAMEWORK += $(EXERCISE)
|
||||||
|
|
||||||
|
$(exercisers)/flags: $(exercisers)/flags.o $(MKDLIB)
|
||||||
|
$(LINK) -o $@ $@.o -lmarkdown
|
||||||
|
|
||||||
|
all_subdirs:: $(EXERCISE)
|
||||||
|
|
||||||
|
verify_subdirs:: $(EXERCISE)
|
||||||
|
@for x in $(EXERCISE); do LD_LIBRARY_PATH="." $$x || exit 1; done
|
||||||
|
|
||||||
|
clean_subdirs::
|
||||||
|
rm -f $(exercisers)/*.o
|
||||||
140
tests/extrafootnotes.t
Normal file
140
tests/extrafootnotes.t
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
. tests/functions.sh
|
||||||
|
|
||||||
|
title "markdown extra-style footnotes"
|
||||||
|
|
||||||
|
rc=0
|
||||||
|
MARKDOWN_FLAGS=
|
||||||
|
|
||||||
|
FOOTIE='I haz a footnote[^1]
|
||||||
|
[^1]: yes?'
|
||||||
|
|
||||||
|
try -ffootnote 'footnotes (-ffootnote)' "$FOOTIE" \
|
||||||
|
'<p>I haz a footnote<sup id="fnref:1"><a href="#fn:1" rel="footnote">1</a></sup></p>
|
||||||
|
<div class="footnotes">
|
||||||
|
<hr/>
|
||||||
|
<ol>
|
||||||
|
<li id="fn:1">
|
||||||
|
yes?<a href="#fnref:1" rev="footnote">↩</a></li>
|
||||||
|
</ol>
|
||||||
|
</div>'
|
||||||
|
|
||||||
|
try -ffootnote -Cfoot 'footnotes (-ffootnote -Cfoot)' "$FOOTIE" \
|
||||||
|
'<p>I haz a footnote<sup id="footref:1"><a href="#foot:1" rel="footnote">1</a></sup></p>
|
||||||
|
<div class="footnotes">
|
||||||
|
<hr/>
|
||||||
|
<ol>
|
||||||
|
<li id="foot:1">
|
||||||
|
yes?<a href="#footref:1" rev="footnote">↩</a></li>
|
||||||
|
</ol>
|
||||||
|
</div>'
|
||||||
|
|
||||||
|
try -ffootnote 'footnotes(two adjacent footnotes)' 'Hello[^1][^2]
|
||||||
|
|
||||||
|
[^1]: world
|
||||||
|
[^2]: from Hamburg' '<p>Hello<sup id="fnref:1"><a href="#fn:1" rel="footnote">1</a></sup><sup id="fnref:2"><a href="#fn:2" rel="footnote">2</a></sup></p>
|
||||||
|
<div class="footnotes">
|
||||||
|
<hr/>
|
||||||
|
<ol>
|
||||||
|
<li id="fn:1">
|
||||||
|
world<a href="#fnref:1" rev="footnote">↩</a></li>
|
||||||
|
<li id="fn:2">
|
||||||
|
from Hamburg<a href="#fnref:2" rev="footnote">↩</a></li>
|
||||||
|
</ol>
|
||||||
|
</div>'
|
||||||
|
|
||||||
|
try -fnofootnote 'footnotes (-fnofootnote)' "$FOOTIE" \
|
||||||
|
'<p>I haz a footnote<a href="yes?">^1</a></p>'
|
||||||
|
|
||||||
|
|
||||||
|
TSRC='Alpha[^AlphaF].
|
||||||
|
|
||||||
|
Column 1 | Column 2
|
||||||
|
---------------------------------|--------------------------
|
||||||
|
Beta[^BetaF] | cell
|
||||||
|
|
||||||
|
[^AlphaF]: Alpha Footnote
|
||||||
|
|
||||||
|
[^BetaF]: Beta Footnote'
|
||||||
|
|
||||||
|
TOUT='<p>Alpha<sup id="fnref:1"><a href="#fn:1" rel="footnote">1</a></sup>.</p>
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Column 1 </th>
|
||||||
|
<th> Column 2</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>Beta<sup id="fnref:2"><a href="#fn:2" rel="footnote">2</a></sup> </td>
|
||||||
|
<td> cell</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<div class="footnotes">
|
||||||
|
<hr/>
|
||||||
|
<ol>
|
||||||
|
<li id="fn:1">
|
||||||
|
Alpha Footnote<a href="#fnref:1" rev="footnote">↩</a></li>
|
||||||
|
<li id="fn:2">
|
||||||
|
Beta Footnote<a href="#fnref:2" rev="footnote">↩</a></li>
|
||||||
|
</ol>
|
||||||
|
</div>'
|
||||||
|
|
||||||
|
try -ffootnote 'footnotes inside table elements' "$TSRC" "$TOUT"
|
||||||
|
|
||||||
|
|
||||||
|
TSRC='[Test test[^test]](class:test)
|
||||||
|
|
||||||
|
<span class="test">
|
||||||
|
Test2[^testtwo]
|
||||||
|
</span>
|
||||||
|
|
||||||
|
Test3[^testthree]
|
||||||
|
|
||||||
|
<span class="test">
|
||||||
|
Test4[^testfour]
|
||||||
|
</span>
|
||||||
|
|
||||||
|
[^test]: Test footnote
|
||||||
|
[^testtwo]: Test2 footnote
|
||||||
|
[^testthree]: Test3 footnote
|
||||||
|
[^testfour]: Test4 footnote'
|
||||||
|
|
||||||
|
TOUT='<p><span class="test">Test test<sup id="fnref:1"><a href="#fn:1" rel="footnote">1</a></sup></span></p>
|
||||||
|
|
||||||
|
<p><span class="test">
|
||||||
|
Test2<sup id="fnref:2"><a href="#fn:2" rel="footnote">2</a></sup>
|
||||||
|
</span></p>
|
||||||
|
|
||||||
|
<p>Test3<sup id="fnref:3"><a href="#fn:3" rel="footnote">3</a></sup></p>
|
||||||
|
|
||||||
|
<p><span class="test">
|
||||||
|
Test4<sup id="fnref:4"><a href="#fn:4" rel="footnote">4</a></sup>
|
||||||
|
</span></p>
|
||||||
|
<div class="footnotes">
|
||||||
|
<hr/>
|
||||||
|
<ol>
|
||||||
|
<li id="fn:1">
|
||||||
|
Test footnote<a href="#fnref:1" rev="footnote">↩</a></li>
|
||||||
|
<li id="fn:2">
|
||||||
|
Test2 footnote<a href="#fnref:2" rev="footnote">↩</a></li>
|
||||||
|
<li id="fn:3">
|
||||||
|
Test3 footnote<a href="#fnref:3" rev="footnote">↩</a></li>
|
||||||
|
<li id="fn:4">
|
||||||
|
Test4 footnote<a href="#fnref:4" rev="footnote">↩</a></li>
|
||||||
|
</ol>
|
||||||
|
</div>'
|
||||||
|
|
||||||
|
try -ffootnote 'footnotes inside spans' "$TSRC" "$TOUT"
|
||||||
|
|
||||||
|
for x in tests/data/f??.text;do
|
||||||
|
result=`echo $x | sed -e 's/.text$/.html/'`
|
||||||
|
try -ffootnote "`basename $x`" "`cat $x`" "`cat $result`"
|
||||||
|
done
|
||||||
|
|
||||||
|
|
||||||
|
summary $0
|
||||||
|
exit $rc
|
||||||
33
tests/flow.t
Normal file
33
tests/flow.t
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
. tests/functions.sh
|
||||||
|
|
||||||
|
title "paragraph flow"
|
||||||
|
|
||||||
|
rc=0
|
||||||
|
MARKDOWN_FLAGS=
|
||||||
|
|
||||||
|
try 'header followed by paragraph' \
|
||||||
|
'###Hello, sailor###
|
||||||
|
And how are you today?' \
|
||||||
|
'<h3>Hello, sailor</h3>
|
||||||
|
|
||||||
|
<p>And how are you today?</p>'
|
||||||
|
|
||||||
|
try 'two lists punctuated with a HR' \
|
||||||
|
'* A
|
||||||
|
* * *
|
||||||
|
* B
|
||||||
|
* C' \
|
||||||
|
'<ul>
|
||||||
|
<li>A</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
|
||||||
|
<hr />
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>B</li>
|
||||||
|
<li>C</li>
|
||||||
|
</ul>'
|
||||||
|
|
||||||
|
summary $0
|
||||||
|
exit $rc
|
||||||
33
tests/footnotes.t
Normal file
33
tests/footnotes.t
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
. tests/functions.sh
|
||||||
|
|
||||||
|
title "footnotes"
|
||||||
|
|
||||||
|
rc=0
|
||||||
|
MARKDOWN_FLAGS=
|
||||||
|
|
||||||
|
try 'a line with multiple []s' '[a][] [b][]:' '<p>[a][] [b][]:</p>'
|
||||||
|
try 'a valid footnote' \
|
||||||
|
'[alink][]
|
||||||
|
|
||||||
|
[alink]: link_me' \
|
||||||
|
'<p><a href="link_me">alink</a></p>'
|
||||||
|
|
||||||
|
try 'a valid footnote, but encased in <>' \
|
||||||
|
'[alink][]
|
||||||
|
|
||||||
|
[alink]: <link_me>' \
|
||||||
|
'<p><a href="link_me">alink</a></p>'
|
||||||
|
|
||||||
|
try 'a prefixed footnote, but encased in <>' \
|
||||||
|
'[alink][]
|
||||||
|
|
||||||
|
[alink]: <http://link.me>' \
|
||||||
|
'<p><a href="http://link.me">alink</a></p>'
|
||||||
|
|
||||||
|
try -fextended_attributes 'A footnote with extended attributes' \
|
||||||
|
'[alink]
|
||||||
|
|
||||||
|
[alink]: link.me {rel=_nofollow}' \
|
||||||
|
'<p><a href="link.me" rel=_nofollow>alink</a></p>'
|
||||||
|
summary $0
|
||||||
|
exit $rc
|
||||||
93
tests/functions.sh
Normal file
93
tests/functions.sh
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
__tests=0
|
||||||
|
__passed=0
|
||||||
|
__failed=0
|
||||||
|
__title=
|
||||||
|
|
||||||
|
___COLS=60
|
||||||
|
|
||||||
|
title() {
|
||||||
|
__title="$*"
|
||||||
|
if [ "$VERBOSE" ]; then
|
||||||
|
./echo "$__title"
|
||||||
|
else
|
||||||
|
./echo -n "$__title" \
|
||||||
|
'.................................................................' | ./cols $(( $___COLS + 4 ))
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
summary() {
|
||||||
|
if [ -z "$VERBOSE" ]; then
|
||||||
|
if [ $__failed -eq 0 ]; then
|
||||||
|
./echo " OK"
|
||||||
|
else
|
||||||
|
./echo
|
||||||
|
./echo "$1: $__tests tests; $__failed failed/$__passed passed"
|
||||||
|
./echo
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
try_header() {
|
||||||
|
testcase=`./echo -n " $1" '........................................................' | ./cols $___COLS `
|
||||||
|
__tests=`expr $__tests + 1`
|
||||||
|
|
||||||
|
test "$VERBOSE" && ./echo -n "$testcase"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
try() {
|
||||||
|
unset FLAGS
|
||||||
|
while [ "$1" ]; do
|
||||||
|
case "$1" in
|
||||||
|
-*) FLAGS="$FLAGS $1"
|
||||||
|
shift ;;
|
||||||
|
*) break ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
try_header "$1"
|
||||||
|
|
||||||
|
case "$2" in
|
||||||
|
-h*) Q=`./markdown $FLAGS` ;;
|
||||||
|
-t*) Q=`./markdown $FLAGS "$2"` ;;
|
||||||
|
*) Q=`./echo "$2" | ./markdown $FLAGS` ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if [ "$3" = "$Q" ]; then
|
||||||
|
__passed=`expr $__passed + 1`
|
||||||
|
test $VERBOSE && ./echo " ok"
|
||||||
|
else
|
||||||
|
__failed=`expr $__failed + 1`
|
||||||
|
if [ -z "$VERBOSE" ]; then
|
||||||
|
./echo
|
||||||
|
./echo "$1"
|
||||||
|
fi
|
||||||
|
./echo "source:"
|
||||||
|
./echo "$2" | sed -e 's/^/ /'
|
||||||
|
./echo "diff:"
|
||||||
|
(./echo "$3" >> $$.w
|
||||||
|
./echo "$Q" >> $$.g
|
||||||
|
diff $$.w $$.g ) | sed -e 's/^/ /'
|
||||||
|
rm -f $$.w $$.g
|
||||||
|
rc=1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
match() {
|
||||||
|
testcase=`./echo -n " $1" '........................................................' | ./cols $___COLS`
|
||||||
|
|
||||||
|
test $VERBOSE && ./echo -n "$testcase"
|
||||||
|
|
||||||
|
if ./echo "$2" | ./markdown | grep "$3" >/dev/null; then
|
||||||
|
test $VERBOSE && ./echo " ok"
|
||||||
|
else
|
||||||
|
if [ -z "$VERBOSE" ]; then
|
||||||
|
./echo
|
||||||
|
./echo "$testcase"
|
||||||
|
fi
|
||||||
|
rc=1
|
||||||
|
fi
|
||||||
|
}
|
||||||
23
tests/githubtags.t
Normal file
23
tests/githubtags.t
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
. tests/functions.sh
|
||||||
|
|
||||||
|
title "github tags"
|
||||||
|
|
||||||
|
rc=0
|
||||||
|
MARKDOWN_FLAGS=
|
||||||
|
|
||||||
|
SRC='<element-name>content</element-name>'
|
||||||
|
|
||||||
|
# try 'github tags disabled by default' \
|
||||||
|
# "$SRC" \
|
||||||
|
# '<p><element-name>content</element-name></p>'
|
||||||
|
|
||||||
|
try -fgithubtags 'github tags' \
|
||||||
|
"$SRC" \
|
||||||
|
'<p><element-name>content</element-name></p>'
|
||||||
|
|
||||||
|
try 'normal tags pass through' \
|
||||||
|
'<a>sdf</a>' \
|
||||||
|
'<p><a>sdf</a></p>'
|
||||||
|
|
||||||
|
summary $0
|
||||||
|
exit $rc
|
||||||
26
tests/header.t
Normal file
26
tests/header.t
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
. tests/functions.sh
|
||||||
|
|
||||||
|
title "headers"
|
||||||
|
|
||||||
|
rc=0
|
||||||
|
MARKDOWN_FLAGS=
|
||||||
|
|
||||||
|
try 'single #' '#' '<p>#</p>'
|
||||||
|
try 'empty ETX' '##' '<h1>#</h1>'
|
||||||
|
try 'single-char ETX (##W)' '##W' '<h2>W</h2>'
|
||||||
|
try 'single-char ETX (##W )' '##W ' '<h2>W</h2>'
|
||||||
|
try 'single-char ETX (## W)' '## W' '<h2>W</h2>'
|
||||||
|
try 'single-char ETX (## W )' '## W ' '<h2>W</h2>'
|
||||||
|
try 'single-char ETX (##W##)' '##W##' '<h2>W</h2>'
|
||||||
|
try 'single-char ETX (##W ##)' '##W ##' '<h2>W</h2>'
|
||||||
|
try 'single-char ETX (## W##)' '## W##' '<h2>W</h2>'
|
||||||
|
try 'single-char ETX (## W ##)' '## W ##' '<h2>W</h2>'
|
||||||
|
|
||||||
|
try 'multiple-char ETX (##Hello##)' '##Hello##' '<h2>Hello</h2>'
|
||||||
|
|
||||||
|
try 'SETEXT with trailing whitespace' \
|
||||||
|
'hello
|
||||||
|
===== ' '<h1>hello</h1>'
|
||||||
|
|
||||||
|
summary $0
|
||||||
|
exit $rc
|
||||||
115
tests/html.t
Normal file
115
tests/html.t
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
. tests/functions.sh
|
||||||
|
|
||||||
|
title "html blocks"
|
||||||
|
|
||||||
|
rc=0
|
||||||
|
MARKDOWN_FLAGS=
|
||||||
|
|
||||||
|
try 'self-closing block tags (hr)' \
|
||||||
|
'<hr>
|
||||||
|
|
||||||
|
text' \
|
||||||
|
'<hr>
|
||||||
|
|
||||||
|
|
||||||
|
<p>text</p>'
|
||||||
|
|
||||||
|
try 'self-closing block tags (hr/)' \
|
||||||
|
'<hr/>
|
||||||
|
|
||||||
|
text' \
|
||||||
|
'<hr/>
|
||||||
|
|
||||||
|
|
||||||
|
<p>text</p>'
|
||||||
|
|
||||||
|
try 'no smartypants inside tags (#1)' \
|
||||||
|
'<img src="linky">' \
|
||||||
|
'<p><img src="linky"></p>'
|
||||||
|
|
||||||
|
try 'no smartypants inside tags (#2)' \
|
||||||
|
'<img src="linky" alt=":)" />' \
|
||||||
|
'<p><img src="linky" alt=":)" /></p>'
|
||||||
|
|
||||||
|
try -fnohtml 'block html with -fnohtml' '<b>hi!</b>' '<p><b>hi!</b></p>'
|
||||||
|
try -fnohtml 'malformed tag injection' '<x <script>' '<p><x <script></p>'
|
||||||
|
try -fhtml 'allow html with -fhtml' '<b>hi!</b>' '<p><b>hi!</b></p>'
|
||||||
|
|
||||||
|
|
||||||
|
# check that nested raw html blocks terminate properly.
|
||||||
|
#
|
||||||
|
BLOCK1SRC='Markdown works fine *here*.
|
||||||
|
|
||||||
|
*And* here.
|
||||||
|
|
||||||
|
<div><pre>
|
||||||
|
</pre></div>
|
||||||
|
|
||||||
|
Markdown here is *not* parsed by RDiscount.
|
||||||
|
|
||||||
|
Nor in *this* paragraph, and there are no paragraph breaks.'
|
||||||
|
|
||||||
|
BLOCK1OUT='<p>Markdown works fine <em>here</em>.</p>
|
||||||
|
|
||||||
|
<p><em>And</em> here.</p>
|
||||||
|
|
||||||
|
<div><pre>
|
||||||
|
</pre></div>
|
||||||
|
|
||||||
|
|
||||||
|
<p>Markdown here is <em>not</em> parsed by RDiscount.</p>
|
||||||
|
|
||||||
|
<p>Nor in <em>this</em> paragraph, and there are no paragraph breaks.</p>'
|
||||||
|
|
||||||
|
try 'nested html blocks (1)' "$BLOCK1SRC" "$BLOCK1OUT"
|
||||||
|
|
||||||
|
try 'nested html blocks (2)' \
|
||||||
|
'<div>This is inside a html block
|
||||||
|
<div>This is, too</div>and
|
||||||
|
so is this</div>' \
|
||||||
|
'<div>This is inside a html block
|
||||||
|
<div>This is, too</div>and
|
||||||
|
so is this</div>'
|
||||||
|
|
||||||
|
try 'unfinished tags' '<foo bar' '<p><foo bar</p>'
|
||||||
|
|
||||||
|
|
||||||
|
try 'block with trailing text' '<p>this is</p>a test' \
|
||||||
|
'<p>this is</p>
|
||||||
|
|
||||||
|
|
||||||
|
<p>a test</p>'
|
||||||
|
|
||||||
|
try 'unclosed block' '<p>here we go!' '<p><p>here we go!</p>'
|
||||||
|
|
||||||
|
|
||||||
|
try '<form> block' '<form>
|
||||||
|
|
||||||
|
pie?
|
||||||
|
|
||||||
|
</form>' '<form>
|
||||||
|
|
||||||
|
pie?
|
||||||
|
|
||||||
|
</form>'
|
||||||
|
|
||||||
|
try 'code inside a blockquote' \
|
||||||
|
'><form stuff>
|
||||||
|
stuff
|
||||||
|
</form>' \
|
||||||
|
'<blockquote><form stuff>
|
||||||
|
stuff
|
||||||
|
</form>
|
||||||
|
</blockquote>'
|
||||||
|
|
||||||
|
try 'multi-line html with trailing text' \
|
||||||
|
'<p>test test test
|
||||||
|
test test test</p>+' \
|
||||||
|
'<p>test test test
|
||||||
|
test test test</p>
|
||||||
|
|
||||||
|
|
||||||
|
<p>+</p>'
|
||||||
|
|
||||||
|
summary $0
|
||||||
|
exit $rc
|
||||||
17
tests/html5.t
Normal file
17
tests/html5.t
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
. tests/functions.sh
|
||||||
|
|
||||||
|
title "html5 blocks (mkd_with_html5_tags)"
|
||||||
|
|
||||||
|
rc=0
|
||||||
|
MARKDOWN_FLAGS=
|
||||||
|
|
||||||
|
try -5 'html5 block elements enabled' \
|
||||||
|
'<aside>html5 does not suck</aside>' \
|
||||||
|
'<aside>html5 does not suck</aside>'
|
||||||
|
|
||||||
|
try 'html5 block elements disabled' \
|
||||||
|
'<aside>html5 sucks</aside>' \
|
||||||
|
'<p><aside>html5 sucks</aside></p>'
|
||||||
|
|
||||||
|
summary $0
|
||||||
|
exit $rc
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user