When parsing a "checkbox" item or image dimensions, recognize
a U+00D7 Multiplication Sign character as equivalent to an "x".
The real "x" is preferred (and still recognized along with "X"),
but in the case where a U+00D7 (×) ends up in there, just go
with it and recognize it as the intent remains clear.
Signed-off-by: Kyle J. McKay <mackyle@gmail.com>
Add an explanation of XML comments for those who may not be familiar
with them including a link to the relevant specification, examples,
and exacting details about where they are and are not recognized.
Signed-off-by: Kyle J. McKay <mackyle@gmail.com>
Combine adjacent (i.e. no separating blank line) standalone
XML comments into the same "block".
This is more efficient, better preserves the original comment
formatting and avoids an unfortunate side-effect that could
introduce unwanted extra paragraphs into the output.
Signed-off-by: Kyle J. McKay <mackyle@gmail.com>
Make use of more of the Getopt::Long::GetOptions API capabilities
to avoid needing extra, awkward code checks.
With this change, options that support negation (e.g. "stylesheet")
or have variants (e.g. "validate-xml-internal") now work as intended
such that the last option given wins.
Additionally, help/version options are now handled immediately
when encountered.
Signed-off-by: Kyle J. McKay <mackyle@gmail.com>
The XML standard section 2.5 is quite specific:
the string "--" (double-hyphen) MUST NOT occur within comments
In fact, xmllint will complain about any comments that
incorrectly contain an internal "--" sequence as they are
not valid XML.
Adjust the sanitation code to only pass through valid XML
comments using the same pattern that _HashHTMLBlocks uses
to recognize them.
With this change, invalid XML comments will be treated as
literal text by the sanitizer and have the initial "<" escaped
to < thus rendering them as not a comment at all.
Also take this opportunity to correct the comments in the
_HashHTMLBlocks function from "HTML" to "XML" to reflect
what it actually matches.
Signed-off-by: Kyle J. McKay <mackyle@gmail.com>
When using `--stub` and picking up the value of the first "H1" tag
to use as the title, remove markup (such as links, italic, bold,
etc.) from the value before using it.
Since <title>...</title> value cannot contain links or other markup
this makes the displayed title look much better where such markup
is present in the original document.
Signed-off-by: Kyle J. McKay <mackyle@gmail.com>
This works to hook up a fragment link to its section:
# Section 1
Link to [Top](#Section_1).
Make the same thing work when written like this:
# Section 1
Link to [Top][id].
[id]: #Section_1
Or even like this:
# Section 1
Link to [id].
[id]: #Section_1
Signed-off-by: Kyle J. McKay <mackyle@gmail.com>
A link reference may have the URL actually split onto the next line,
not just the title attribute.
Mention this in the syntax description for links.
Signed-off-by: Kyle J. McKay <mackyle@gmail.com>
Any absolute path URLs (but not // ones) have the prefix prepended.
If that makes the resulting URL a fully absolute URL it will not
be processed by any --htmlroot and/or --imageroot options.
With this option, site-relative absolute path URLs can be re-written
so that the site is made explicit in order to support viewing on
a different site.
Signed-off-by: Kyle J. McKay <mackyle@gmail.com>
The "s" option of the --wiki format strips the final extension
before applying the template.
Enhance the "s" option to optionally take a list of extensions
and to only strip the extension if it's one from the list.
Provide a "shortcut" extension that represents all known markdown
extensions.
Change the default --wiki format to now be "%{s(:md)}.html" instead
of the previous default which means it will no longer strip arbitrary
extensions, but only known markdown ones.
Signed-off-by: Kyle J. McKay <mackyle@gmail.com>
During initial processing, explict "block" tags are set aside to
avoid creating problems in the output later.
Adjust the matches to be case insensitive.
Also relax the extra-blank line before and after that only
prevents them being recognized where they need to be.
Signed-off-by: Kyle J. McKay <mackyle@gmail.com>
Add new `--base` option that allows a prefix to be specified to be
added to all bare fragment-only URL links.
Use of this option may be required in order for intra-document
fragment links to function properly within a document that makes
use of the `<base>` tag.
Make sure explicitly specified fragment-only URLs (i.e. given in
verbatim `<a>` tags) get hooked up to the proper destination if
possible.
They obviously are trying to refer to something in the same document
so make sure they get the same treatment to hook them up.
Do the same for fragment-only links inside wiki `[[`...`]]` links.
And for both of these (explicit `<a>` tags and `[[`...`]]` links)
make sure the new bare fragment-only URL prefix gets added if given.
While in there, adjust whitespace to match coding convention for
this file where needed in the sections that have been changed.
Signed-off-by: Kyle J. McKay <mackyle@gmail.com>
When processing something like this:
* first
> quoted
* second
It's imperative that the list tags and blockquote tags do not
become intermingled resulting in invalid output like so:
<p><ul>
<li>first</p>
<blockquote>
<p>quoted</li>
<li>second</li>
</ul></p>
</blockquote>
Instead, process the lists together with code blocks and
blockquotes so that cannot happen and instead we get the
correct output like so:
<ul>
<li>first
<blockquote>
<p>quoted</p>
</blockquote>
</li>
<li>second</li>
</ul>
Signed-off-by: Kyle J. McKay <mackyle@gmail.com>
Now that the recognition requirements for atx-style headers have
been tightened a bit, process them ahead of setext-style headers
to avoid having a horizontal rule immediately after one of the
atx-style headers being grabbed as a setext-style header.
Previously this:
##### My H5
---
Would end up as a single `<h2>##### My H5</h2>`. Now it will more
correctly become `<h5>My H5</h5><hr />` instead.
This has been a longstanding problem that goes at least as far
back as version 1.0.1 and probably further.
Signed-off-by: Kyle J. McKay <mackyle@gmail.com>
Treat more than 6 consecutive '#'s as not a header.
Allow blank headers to be recognized which can be used for
spacers and/or formatting breaks.
Signed-off-by: Kyle J. McKay <mackyle@gmail.com>
In b62cef825e (Markdown.pl: recognize top-level lists better,
2017-01-09, markdown_1.1.0), an attempt was made to recognize
obvious lists that were improperly being treated as wrapped paragraphs.
While that change offers a number of improvements (i.e. more lists
are recognized properly than were before), it does not go far enough.
Further enhance it to only require a single list marker to start a
list provided it's one of the unordered list markers. While it's
certainly possible that a lone "*", "+" or "-" got wrapped onto the
beginning of a line by itself, it's easy to correct; since lone
occurrences of those characters seems highly unlikely, choose the
list starting interpretation instead.
In addition, if the prior line ends with a colon (:) do not require
two markers to start the list, just one.
Furthermore, allow a single, optional, blank line between two markers
that do start a list.
With these changes, the vast majority of lists are recognized properly.
Signed-off-by: Kyle J. McKay <mackyle@gmail.com>
Previously, to match setext-style headers, only the top
three levels of atx-style headers were hooked up with ids.
Change this and hook up h4, h5 and h6 atx-style headers using
the same rules as for the others.
Signed-off-by: Kyle J. McKay <mackyle@gmail.com>
The language name specified for syntax highlighting generally has
to be composed of "word" characters (alphanumeric and "_") plus
"+", "-" and ".".
Allow a final trailing "#" on the language name so that c# and f#
can be used as language names.
Signed-off-by: Kyle J. McKay <mackyle@gmail.com>
The $g_nested_brackets recursive regular expression is already being
used to match nested and balanced '['...']' sequences.
Introduce a $g_nested_parens recursive regular expression that
matches nested and balanced '('...')' sequences; use it to match
the parenthesized portion of `[...](...)` and `![...](...)` links.
This eliminates a number of previous issues with links that contained
embedded parentheses and non-reference image links nested within
non-reference non-image links.
Signed-off-by: Kyle J. McKay <mackyle@gmail.com>
While a bit unusual, the reference id part of a reference link can
have nested '['...']' if wanted.
Therefore use $g_nested_brackets to match that side too.
Signed-off-by: Kyle J. McKay <mackyle@gmail.com>
Revise _DeTab yet again to provide a minor boost.
This really does currently seem to be the fastest detab mechanism
available.
Signed-off-by: Kyle J. McKay <mackyle@gmail.com>
The recursive regex `$g_nested_brackets` (see the source) correctly
matches properly balanced nested `[`...`]` text.
The normal anchor parsing already makes use of it.
Use it for the image parsing too so that this:
[![Alt](img.png)][link]
[link]:example.txt
Does not become the very broken:
<a href="img.png"><img src="example.txt" alt="Alt</a>" />
But instead becomes the correct:
<a href="example.txt"><img src="img.png" alt="Alt" /></a>
This problem has been present all the way back to Markdown.pl version
1.0.1 (2004-12-14) and likely earlier too.
Signed-off-by: Kyle J. McKay <mackyle@gmail.com>
Avoid starting a new list when seeing only one single orphan
list item that appears to be either a year or an initial (only
UPPERCASE though).
Signed-off-by: Kyle J. McKay <mackyle@gmail.com>
When list items are using paragraphs, make sure they do not cuddle
up too closely to the surrounding closing "</li>" when they contain
nested lists. Also include a "hint" for text-only browsers that
super compact cuddling is not wanted at that spot.
Signed-off-by: Kyle J. McKay <mackyle@gmail.com>
Be very careful to make sure that this:
open **FILE*** with *write*
Does not turn into the broken:
open <strong>FILE<em></strong> with *write</em>
But instead turns into the correct:
open <strong>FILE*</strong> with <em>write</em>
Handle italics inside bold by nesting a callout that finishes
up by "hiding" any leftover bold/italics markup characters.
Signed-off-by: Kyle J. McKay <mackyle@gmail.com>
Try very much harder to find a match for explicit `#anchorhere`
links in the document.
The implicit link shortcut works so much better and is far less
error prone.
Nevertheless, attempt to connect the stray anchor links via
extraordinary means.
Signed-off-by: Kyle J. McKay <mackyle@gmail.com>
This, for example:
[Looking at a*](#something) is *good*
Must not produce this broken output:
<a href="#something">Looking at a<em></a> is *good</em>
But instead this:
<a href="#something">Looking at a*</a> is <em>good</em>
Achieve this by making a special pass to handle bold, italic and
strikethrough on the anchor text and then "hiding" any remaining
markup characters that might be confusingly matched up with characters
outside the anchor text.
Signed-off-by: Kyle J. McKay <mackyle@gmail.com>
Certain start tags (a, area, img, map) do not make sense unless
they have at least one attribute present.
If a completely attribute barren start tag for one of these elements
is found, treat it as invalid and escape the leading '<'.
This is an heuristic that shouldn't cause too many problems while
silently "correcting" incorrect input.
Either way (leaving the bare start tag with no attributes or escaping
it and potentially causing a fault as its end tag no longer has
anything to match up with), it's broken.
The question becomes then which breakage is more common in order
to handle that one in preference to the other.
With this change, the "it wasn't really a tag after all" situation
will now be considered more common than the "it was deliberatly an
invalid start tag with a matching end tag" situation.
Signed-off-by: Kyle J. McKay <mackyle@gmail.com>
With `--sanitize`, minimized empty tags that should not be for XHTML
(e.g. "<p/>") have been automatically split into separate start and
end tags (e.g. "<p></p>").
Do the same in reverse for separate start and end tags that should
not be for XHTML (e.g. "<hr></hr>") and turn them into a single
minimized tag (e.g. "<hr />").
Additionally, when `--validate-xml-internal` is active, automatically
insert omitted optional end tags in (hopefully) the right places.
For example, "<ul><li>foo<li>bar</ul>" will automatically become
"<ul><li>foo</li><li>bar</li></ul>" thus making it valid XHTML.
When there are multiple errors reported (can only happen when there
are multiple opening tags missing their ending tags), report the
errors in reverse order (i.e. the first one reported will be the
largest line number) because that will often identify the source
of the trouble as the first error line due to the nature of tag
nesting.
Make a few related wordsmithing changes at the same time.
Signed-off-by: Kyle J. McKay <mackyle@gmail.com>
Add missing info for tfoot and thead.
Add "summary" to attributes for table.
Add "col" to list of empty element tags.
Add some explanatory comments to hash tables.
Add more text to `--sanitize` help.
Signed-off-by: Kyle J. McKay <mackyle@gmail.com>
Enhance the sanitation process slightly in order to perform simple
tag missing/mismatch validation. Almost all the work needed was
already being performed with the exception of keeping a tag stack.
Keep an active tag stack when `--validate-xml-internal` is active
and use it to find mismatched and/or missing open/closing tags.
Enable this by default unless `--no-sanitize` has been given (the
sanitize machinery does the validation and is required) or
`--validate-xml` or `--no-validate-xml` has been given explicitly.
Unlike the more comprehensive `--validate-xml`, this option operates
very quickly and does not require any additional XML modules to be
present. It's also compatible with `--html4tags`.
Signed-off-by: Kyle J. McKay <mackyle@gmail.com>
Avoid using Pod::Usage unless it's actually needed.
Avoid using XML::Simple or XML::Parser without --validate-xml.
Also correct the sense of the MT tests while in there.
Signed-off-by: Kyle J. McKay <mackyle@gmail.com>
With `--raw`, no actual Markdown processing takes place, but the
input will still be sanitized (by default) and may optionally also
have --html4tags or --validate-xml used on it too.
The output's line endings will be normalized and the encoding
converted to UTF-8.
Signed-off-by: Kyle J. McKay <mackyle@gmail.com>
The old tab expansion code exhibits very poor performance when
passed the contents of entire files as input.
Mitigate this inefficiency by operating on one line at a time.
Signed-off-by: Kyle J. McKay <mackyle@gmail.com>
When `--sanitize` is active (the default), tags have been "sanitized"
as they were encountered. Unfortunately, not all tags get "encountered"
by the sanitation section.
Pre-existing "block" tags in the input are squirreled away to prevent
unintentional formatting "accidents".
Such tags were evading the sanitation engineer.
Instead of "sterlizing" when the tags are encountered during normal
formatting processing, perform full sanitation sterlization (provided
`--sanitize` is active) on the final, fully-formatted output.
By waiting until the end, all tags will be fully sterilized (even
those produced by Markdown.pl itself), no tag shall escape.
If `--validate-xml` has been requested (it's off by default), that
will happen _after_ full sanitation.
Signed-off-by: Kyle J. McKay <mackyle@gmail.com>
Rework the code that iterates through all the files given on
the command line and make sure any errors are reported with
a fatal result.
Signed-off-by: Kyle J. McKay <mackyle@gmail.com>
Given a table like this:
| H1 | H2 | H3 |
|----|----|----|
| x1 | x2 | x3 |
| y1 |too long|y3|
| z1 | z2 | z3 |
The problematic second row can now be split across mulitple lines
like this:
| H1 | H2 | H3 |
|----|----|----|
| x1 | x2 | x3 |
| y1 |too | y3 |\
| |long| |
| z1 | z2 | z3 |
While the example is contrived, even with "sloppy" tables, having
the ability to merge row data like this usually avoids the need for
unsightly long lines when an exceptional cell overflows excessively.
Signed-off-by: Kyle J. McKay <mackyle@gmail.com>
When `--validate-xml` has been given and XML::Simple does not appear
to be present but XML::Parser does, use it instead.
The output messages are slightly different on errors, but they're
still clear and validation still happens.
Even though XML::Parser is one of the possible backends for
XML::Simple, either one can be present without the other.
This change makes `--validate-xml` more widely available.
Signed-off-by: Kyle J. McKay <mackyle@gmail.com>
A "backticks-delimited code block" must be at the left margin,
however, the entire block can be shifted 1, 2 or 3 characters to
the right using spaces. These are all the same:
```
line
```
```
line
```
```
line
```
```
line
```
When support for the slightly shifted code blocks was originally
added, the effect on tab expansion was overlooked.
The shifting in of the code block serves to make the raw markdown
source perhaps a tiny bit more readable, but the shifting in is NOT
a logical part of the lines in the code block themselves.
Therefore, remove any "shift in" spaces before expanding tabs within
the code block so that the result ends up looking exactly the same
no matter whether the code block has been shifted in at all or not.
Signed-off-by: Kyle J. McKay <mackyle@gmail.com>
Introduce a new `--validate-xml` (and corresponding `--no-validate-xml`)
option that performs a simple XML validation of the output using
`XML::Simple` and fails with an error if any problems are found.
Because a new module (`XML::Simple`) is required to do this, it's
NOT the default option (in which case `XML::Simple` need not be
present).
When `--validate-xml` is combined with `--sanitize` (which is the
default) the output can be included in an XHTML page with confidence
it will not invalidate the page's XML.
Because the `--html4tags` option produces non-XML output, it is
incompatible with `--validate-xml` and if both are given an immediate
error will be reported.
Signed-off-by: Kyle J. McKay <mackyle@gmail.com>
Unless the new `--no-sanitize` option is given, then inspect each
raw tag encountered in the input and "sanitize" it before outputting
it. The new `--sanitize` option is now the default.
As before, any tags not on the "approved" list have their "<" escaped
and become ordinary text in the output. With this commit, two new
tags are now on the "approved" list: `<map>` and `<area>`.
Each "approved" tag encountered has all of its attributes inspected
and any that are not on the "approved" list for that tag are expunged.
Any others that aren't in canonical form are corrected.
Empty tags are normalized as well (e.g. "<p/>" becomes "<p></p>"
but "<img ...>" becomes "<img ... />" etc.).
With this change, Markdown.pl output should be reasonably "safe"
for use as no code tags or attributes are permitted.
While client-side image maps are now allowed, server-side are not
(the "ismap" attribute will be silently expunged). Client-side
image maps should always be preferred to server-side anyway, that's
why they were created in the first place.
Signed-off-by: Kyle J. McKay <mackyle@gmail.com>