Giter Site home page Giter Site logo

pml-lang / pml-companion Goto Github PK

View Code? Open in Web Editor NEW
22.0 5.0 1.0 23.11 MB

Java source code of the 'PML Companion (PMLC)'

Home Page: https://www.pml-lang.dev

License: GNU General Public License v2.0

Batchfile 0.29% Shell 0.41% CSS 1.73% Java 97.56%
markup-language pml practical-markup-language pml-to-html-converter markup-converter

pml-companion's Introduction

PML Companion Java Source Code

This repository contains the source code files of the PML Companion (PMLC), written in Java.

For more information about PML please visit its website.

pml-companion's People

Contributors

celtic-coder avatar coemgenuslcp avatar pml-lang avatar ppl-lang avatar tajmone avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

Forkers

tajmone

pml-companion's Issues

Resources directory written for non-action commands like help

In PML 3.0.0, with the resources directory being written to ~/.config/PML_Companion/, this happens even when you run non-action commands such as pml -version.

INFO: Creating shared data directory ?/.config/PML_Companion/3_0
PMLC 3.0.0 2022-08-19

I can maybe see why you might desire contextual information on the resources (including overrides) available for the help messages, but I can't imagine you would need the resources directory for getting the version. In scripting, version checking is often a smoke test for checking a command-line tool is runnable, so the result here is that the check is not read-only.

Resources directory written to '?/.config' when inside Docker container

When I run PMLC 3.0.0 inside a Docker container on Linux, the resources directory gets written to ?/.config. It may be something in how the resources directory string determines home or wherever, when it is inside the container context.

# Dockerfile
FROM alpine:latest
RUN wget "https://github.com/pml-lang/pml-companion/releases/download/v3.0.0/pmlc" && chmod +x pmlc
RUN pmlc -version
# or
ENTRYPOINT ["/pmlc", "-version"]
docker build --tag "pmlc" - < Dockerfile
docker run "pmlc" -version
INFO: Creating shared data directory ?/.config/PML_Companion/3_0
PMLC 3.0.0 2022-08-19

The ? folder appears to be created relative to the current directory. As a side effect, if you mount the current directory to the container and WORKDIR into it inside the Dockerfile, the ? folder with the .config/PML resources subdirectory will be generated inside the current directory, with root:root as the owner.

Error Log Bug: Incorrect File Coordinates due to Line-Continuation '\'

I was doing some preparation work to enhance Sublime PML build system so that it would parse error logs and extract info to enable to navigate through the various errors in their source files (see: tajmone/Sublime-PML#16).

While doing some tests, I've encountered a problem with pmlc error reports pertaining incorrect positional information being reported for errors that are located after a line-continuation \.

The following snippet from the beginning of a PML source:

[doc title = Malformed Document (standalone) \
    authors = tajmone \
    date = YYYY-MM-DD

is reported as:

Error: 'YYYY-MM-DD' is an invalid value for parameter 'date'. Reason:
'YYYY-MM-DD' is not a valid ISO date.

[ >>> doc title = Malformed Document (standalone) \
line 1, column 2
X:\<obscured path>\standalone.pml

the positional info line 1, column 2 is incorrect — should be line 3, column 12.

To be on the safe side, I've tested this first using Tab indentation (one Tab) and then converting each Tab to 4 spaces, but the result didn't change.

It seems that the problem here is the line continuation \, which is not being accounted for when reporting the error position, because other tests that don't use line-continuation were reporting error positions correctly.

New Nodes to Handle Edge Cases: word-joiner and blank/empty

I've noticed that in the PML User Manual, section Anatomy of a PML Document » Attributes, the line code for the escape character is forced to contain a trailing space (\ ) — in the source file 05_anatomy.pml:

must be terminated by a backslash ([c \\ ]),

The problem here is that using [c \\] instead of [c \\ ] won't work because it would be parsed as [c+\+\], i.e. the second slash is being interpreted as escaping the closing bracket.

To avoid similar problems (which are typical edge cases found on all lightweight syntaxes) I suggest adding some extra special characters:

  • [empty or [blank — replaced by nothing (empty string), post-parsing. It's sole role is to feed a token separator to the parser.
  • [wjword-joiner character (&#8288;); a code point in Unicode that prevents a line break at its position.

(obviously, no closing bracket required for either)

The above example from the PML User Manual could then be fixed via:

must be terminated by a backslash ([c \\[empty]),

Both of these are useful hacks to handle edge-cases where the PML parser could be faced with ambiguities like the above example, and they would be the equivalents of Asciidoctor's predefined characters-substitutions attributes {empty}/{blank} and {wj}, which are extremely useful to handle all sort of edge-cases in AsciiDoc sources.

In Asciidoctor, {empty} and {blank} are identical, one is just an alias of the other; I personally prefer [empty to [blank, for I believe it's clearer, and I'd avoid having having both, since it's redundant.

The [wj is also very useful in situations where you need to prevent the browser from wrapping a table column during auto-adjustment (e.g. because one column contains words separated by boundaries like spaces, hyphens, brackets, etc.). Or to prevent wrapping a line between a word and its footnote marker, e.g. someword[1]someword+\n+[1], whereas someword[wj[1]

and sometimes they can just improve source readability

These would be consistent with the current [nl and [sp substitutions available in PML.

References

Error when comment on first line of inserted file

Version 1.5.0 2021-06-08

When I call [insert file="other file.pml"], if the first line of the other file is a comment like so:

[- Here is a comment. -]
Here is a paragraph.

the converter errs with this error:

Error: '-' is an invalid node tag.
Valid tags are: [...].
[ >>> - Here is a comment. -]
line 1, column 2

If the comment is on later lines, there is no error.

Add New Discussion Category: "Editors Support"

Could you please add a new "Editors Support" category in the repository Discussions, and move therein Discussion #7?

Since editors/IDEs support is an important topic, it might worth dedicating to it its own category, and I was thinking of publishing some posts covering topics like scopes naming and strategies for PML syntaxes, where I wanted to share my experience from the Sublime PML package and the tricks I've learned, which can be useful for anyone creating a PML syntax plug-in in any modern editor based on TextMate grammars.

E.g. I've finally managed to come up with a smart and maintainable system to properly handle node attributes so that Sublime PML will only suggest auto-completions for attributes that are pertinent to a given tag, and only when the cursor is right after the opening node tag, or after another attribute definition — i.e. the syntax is now able to define exactly where tags attributes can go, with awareness of \ for line continuations extending the valid insertion area, and that attributes completions suggestions should end at the first EOL or after encountering text which is not an attribute definition. It took me some trial and error to achieve this, but finally I've managed to come up with a single syntax context which is shared by all nodes, which makes maintenance much easier.

The real trick was to allow the syntax to highlight attributes regardless of whether they are supported by a tag, but restrict completions suggestions only to valid attributes for any tags. This satisfies the criteria of an error-tolerant syntax, and at the same time provides an enhanced editing experience through context-aware completions.

Now that this mechanism is in place, it's just a matter of implementing the remaining tags, attributes and completions — this system even catches unimplemented tags and attributes via (temporary) fallback node/attributes catch-all definitions, which makes the syntax immediately usable in production, even if incomplete.

I believe that the lessons learned here can also apply to other editors that use TextMate-like grammars (e.g. VSCode and Atom), and possibly even apply to Language Servers in some degree. So it might be worth sharing them in the repository Discussions, for the benefits of future contributors — we might also get useful feedback on how to improve this approach.

Creating editor packages can often be confusing, especially when it comes to semantic scoping and choosing appropriate scope names for a syntax like PML (which doesn't fit the paradigm of languages like C, Java, Python, etc., around which these scope naming conventions were designed). Many developers focus only on the syntax highlighting aspect, which is merely aesthetic, but the real power of scopes is their ability to enable/disable various plug-in features according to context: auto-completions, symbols indexing, key-bound actions/macros, etc., which can all be implemented smartly, providing a very smooth editing experience where the syntax is tuned to editing needs.

I'd also like to create a thread on the PML Language Server, where to share links on useful articles and tools, and general thoughts, because a PML Lang Server is definitely the ultimate goal in terms of editors support (albeit still faraway).

It's always nice to have quick access to links and past discussion on such topics.

Div node ID not referenceable

In version 2.1.0 2021-09-09, the following code

Body of text with a footnote here[sup
    [xref node_id="footnote1" text="1"]
].

[div id="footnote1" 1
    Footnote contents
]

yields the following error from the compiler.

Error      A node with id 'footnote1' does not exist.                                                                  
Code       [xref node_id="footnote1" text="1"]

The order of [xref] and [div] does not make a difference.

Possibly related to #58.

Why Multiple Heading IDs?

@pml-lang, I'm a bit confused about the fact that the [ch [title and [subtitle nodes all support the id attribute. For all these nodes, the documentation is identical:

Description: A unique identifier for the node.

An id can be used to:

  • identify a node so that an internal link can be done with an 'xref' (cross reference) node.
  • identify a node so that it can be styled individually with CSS
  • create an HTML anchor so that it can be accessed with the # (hash) sign (e.g. writing id=foo will enable you to have an HTML link ending with #foo.

Usually a heading has only one ID in documents, and supporting an ID (anchor) in both the [ch and [title nodes seems redundant and confusion prone, especially since you can't have a titleless chapter heading.

The [doc node doesn't support an ID because obviously it doesn't need one (at least not semantically), since the doc title is the top of the page, although one might argue that assigning an ID to the [doc [title node could be useful for providing xrefs to jump back to the top of the document.

My argument is that chapter titles only need one.

The following PML source:

    [ch (id=chapter_id) [title (id=title_id) Chapter With Double-ID]

produces this HTML code:

<section id="chapter_id" class="pml-chapter">
  <h2 id="title_id" class="pml-chapter-title">Chapter With Double-ID</h2>
</section>

What's the point in having double anchors here? They will both jump to the same document position, but they can confuse users as to which one is the idiomatic way of assigning an anchor for cross references — especially if you consider that each ID must be unique.

In collaborative editing, contributors need to know where to place the ID/anchor, should it go on the [ch or [title node? Ending up with large documents where the heading IDs are sometimes on the [ch node and other time on [title leads to messy documents, especially if editors rely on editor scripts that target attributes by nodes (e.g. to enforce naming conventions), since these scripts might miss any IDs on the other node.

Since the [doc node doesn't support an ID directly, but only via the [title subnode, it seems to me that the most reasonable approach would be to drop the id attribute from [ch and only keep it on the [title node, since the latter is shared between both [doc and [ch.

Even more confusing is the fact that the [subtitle node supports the id attribute too — meaning that a section heading can have up to three IDs! What's the use of placing an ID/anchor on a subtitle? The position of a title and its subtitle within a document are basically one and the same (nothing else should be placed between them) and since you can't have a subtitle without a title, the [subtitle node is merely an extension of the [title node, practically speaking, just as [title is an extension of [doc or [ch, since [title never stands on its own but always leans on a section heading (be it the main doc title or one of its sub-sections headings).

I think these questions should be addressed before v3.0 is out:

  • If there are good reasons why headings support multiple IDs (up to three per heading, if you include subtitles) then these reasons need to be documented, and it should be made clear which is the idiomatic way of providing an ID to a section heading.
  • If my arguments for deprecating the id attribute on [ch and [subtitle are valid, then they should be dropped before PML 3.0 is out — otherwise we'll be seeing another MAJOR release cycle with breaking changes within the same MAJOR release (unacceptable under Semantic Versioning).

So, am I missing out something here about the reasons for supporting multiple IDs in section headings?

I know that technically speaking this is all valid HTML (you can place anchors wherever you want, including <strong> and <em>), but from a documentation writers' perspective it doesn't make much sense (whereas it might for HTML based GUI designers). Since PML is all about documents, IMO we should stick to writers semantics and best practices, so that PML idiomacy is unambiguous to its users.

PML Docs: Add Version Info to Ref Man & Create Docs Archive

PML Reference Manual: Add Version Info

Please, add to the online PML Reference Manual the PML version it refers to, like it's done with the PML User Manual.

Currently, it's hard to tell what PML version the Ref Man refers to, since it only mentions the publishing (last edited?) date.

The way the User Man displays the info summary via a table just below the document title is very helpful, the same should be done for the Ref Man too.

Docs Archive

It would also be quite useful if you could provide an online archive of all the documents and JSON-tags files of the various PML releases, for consultation and comparison purposes — especially useful for developers of PML related projects, so they can keep track of the syntax changes across releases, but also for users who need to migrate documentation projects created for older versions of PML and need to focus on the syntax changes.

Since each version of the documentation source files is specific to the PML syntax of the release it refers to, building them from source is not an option for it would require to install each PML release (for pre-3.0.0 PML versions, which relied on an installer) — hence the need for their pre-converted HTML versions to be stored somewhere accessible.

Under PML Website …

If space on the official PML website is not a concern, you could just add the HTML docs adopting a version-based naming convention, e.g.:

In Dedicated Repository …

Alternatively, you could just create a dedicated repository with all these HTML and JSON docs (e.g. pml-docs-archive) and serve them online via GitHub Pages, so end users can either consult them online or clone the repository locally.

Enhance Repository and Org Visibility on GitHub

To enhance the repository visibility:

Repository Details

Edit About box setting (repository details):

  • Website field, add: https://www.pml-lang.dev
  • Topics field, add: pml practical-markup-language html-converter (etc.)
  • Include in the homepage field, remove "Package" (if not needed).

GitHub topics are a powerful feature, they don't just simplifying find repositories on GitHub: by adding PML keywords to the topics you're actually promoting PML's visibility on GitHub, and once a keyword reaches a certain numbers of repository that are using it you automatically obtain visibility on various GitHub services and sub-pages.

Media Preview Card

  • Add repository media preview.

In Settings » Options: "Social preview" you can add a social media preview card for the PML repository, which will be showed whenever the repository is linked in websites, blogs and forums that support media cards. You'll also find a link to a graphic template there, to build your card with.

You can use the SocialSharePreview.com or Twitter Card Validator
services to check how your card looks like. E.g., here's the link to the media preview card of Sublime-PML; and here's a screenshot from Twitter:

Sublime-PML-social-card-preview

If you need any help with the graphics, just buzz me via PM. I work a lot of graphics.

Add pml-lang Profile README

To enhance the landing page of the pml-lang GitHub profile, add a profile README:

  • Create new repository: pml-lang/pml-lang
    • Add README.md (or .asciidoc, etc.) with a brief presentation of PML (not 100% sure, but I think you can include images in the repository too).

Needless to say, the same tips apply to any other repository and to the pxml-lang as well.

CSS Option Treats Everything As CSS

Not really a bug in PMLC itself, but a potential cause of bugs in the generated HTML files.

When invoking PMLC 3.1.0 with command PML_to_HTML and option --CSS_files followed by a directory, PMLC then treats any file within that directory as if it was a CSS file, regardless of its extension (or lack thereof), so in the generated HTML file you have something like this:

<meta name="generator" content="PML 3.1.0 (www.pml-lang.dev)" />
<title>Style Sheet Demo Document</title>
<link rel="stylesheet" href="css/demo.html">
<link rel="stylesheet" href="css/extended.html">
<link rel="stylesheet" href="css/pml-default.css">
<link rel="stylesheet" href="css/pml-default.css.map">
<link rel="stylesheet" href="css/pml-default.scss">
<link rel="stylesheet" href="css/pml-print-default.css" media="print">
<link rel="stylesheet" href="css/pml-print-default.css.map" media="print">
<link rel="stylesheet" href="css/pml-print-default.scss" media="print">

This is extremely inconvenient for any developer, since it forces them to specify CSS files individually, whereas it would be convenient to just pass a folder path and expect PMLC to selectively include only files with the .css extensions.

Having a folder with CSS files only is counter intuitive for a developer, since Sass files, along with generated CSS maps for debugging stylesheets are usually kept in the same directory. So, the idea of having a "pure CSS folder" is rather naive, and in any case there's always the risk of end users forgetting some file behind, or temporary and system files (often hidden from the end user) in that folder ending up in the generated HTML being linked as a stylesheet.

In other words, it makes sense that PMLC should natively filter directory contents by the .css extension, and accept any individually specified file as is, regardless of its extension. This is IMO a sensible default, since it applies reasonable file-extension conventions for folder contents filtering, without preventing custom extensions being explicitly used for individual files.

Right now, passing a folder path doesn't seem neither practical nor safe, for it only makes sense if the folder contains CSS files only — which is rarely the case, and hard to guarantee since temporary files (including hidden files) can easily end up there, especially since browsers tend to create temporary files next to the CSS stylesheets when accessing the advanced developer tools (e.g. Chrome).

Blindly linking to any files in the CSS target folder could even potentially result in accidentally revealing personal data, or divulging source files (e.g. if the toolchain tracks the linked stylesheets to post-process them, etc.).

JSON Tag Info: Add "child_nodes_allowed"

In Lenient Parsing we read:

If a formal node has only attributes (no child nodes) the parenthesis around attributes can be omitted.

The problem is knowing which nodes are childless an which aren't — both for taking advantage of this feature while editing, as well as for implementing its support in editor syntaxes/packages.

The User Manual mentions the [image node as an example, but having access to the full list of these nodes types would be really useful (as opposed to guess work or trial and error).

It would be really helpful if you could add to the JSON file generated via pmlc tag_info a dedicated entry for each node, specifying whether is allows child nodes or not, along the lines of "is_raw_text_block" and HTML_attributes_allowed". This would also allow easily auto-generating a list of such nodes (e.g. via Mustache), which could be added as an Appendix to the PML Reference Manual.

I'm not sure how this key should be named but, based on the current keys names, I think that something like "child_nodes_allowed" might be appropriate, especially for a boolean key.

As a general rule, bear in mind that when it comes to creating packages for editor support, having access to similar info is essential in order to implement syntaxes properly.

E.g. knowing which nodes are allowed inside each and every node, and which are not, is another essential piece of info for being able to detect invalid sub-nodes within the syntax — one you know which nodes are supported, you only need to include them, and treat the rest as invalidly placed nodes.

Currently this type of info is not accessible, which only leaves trial and error — with current number of nodes supported by PML, their possible combinations amounts to a huge number.

In most modern editors' syntax definitions, each node is implemented as independent "context" (JSON/YMAL block) which can then be included wherever required (at the root level, within other nodes, etc.). Knowing in advance what other nodes each node can take as its child is a huge helper in task of building PML syntaxes.

Problems with [text Node

The generated pml_tags.json file of PML 2.3.0 contains a reference to the [text tag which has no corresponding entry in the PML Reference Manual:

            {
                "id":"text",
                "type":"inline",
                "title":"Text",
                "description":null,
                "examples":"It's a good day.",
                "attributes":null,
                "default_attribute_id":null,
                "HTML_attributes_allowed":false,
                "is_inline_type":true,
                "is_raw_text_block":false,
                "child_nodes_allowed":false,
                "opening_tag":"[text",
                "closing_tag":"]",
                "latest_doc_url":"https://www.pml-lang.dev/docs/reference_manual/index.html#node_text"
            },

Its docs links point to a non-existing anchor:

https://www.pml-lang.dev/docs/reference_manual/index.html#node_text

Which one is wrong, the JSON file or the Ref.Man? i.e. does this [text node really exist, or is it just undocumented?

Enable Discussions

Please enable Discussion for the repository, so that end user might freely discuss topics that don't directly affect the repo's development (e.g. the pros and cons of adding new features, comparisons to other syntaxes, etc.) and avoid polluting Issues (which should be reserved for practical maintenance).

Stylesheets Copy-&-Subfolder Prevents CSS Debugging

PMLC 3.1.0 | Win 10

NOTE — Although this was already mentioned in a side comment of Issues #93, I'm creating a dedicated Issue for this matter so we can link it specifically and track its status.

Problem Description

As of PMLC 3.1.0, the new --CSS_files option always copies the specified stylesheets into a css/ subfolder created by PMLC, which hinders development of custom stylesheets when using CSS compilers like Sass, LESS, etc.

When compiling to CSS, Sass also generates the required .css.map files, and at the end of each output CSS adds a comment containing a link to its corresponding map file, e.g.:

/*# sourceMappingURL=pml-default.css.map */

These CSS map files allow developers to inspect and debug their stylesheets directly in their browser via its Developer Tools, which in most modern browsers include support for CSS maps and Sass/Less sources, which means that the end users are shown the real-use effect of custom CSS definitions directly pointing to their Sass sources and modules, not just the compiled CSS output.

But because the PMLC generated HTML documents are using a copy of the .css files (located in the css/ subfolder) instead of the original CSS files generated by Sass, the CSS map links in these comments won't be pointing to the correct .css.map files, thus breaking the advanced debugging features of browsers Dev Tools (e.g. Chrome).

Required Solutions

We need either:

  1. A new parameter for the PMLC p2h option, allowing end users to bypass the CSS-copying stage by having PMLC simply link to the original files specified in the --CSS_files parameter, as they are, without creating copies.
  2. Change the default PMLC p2h behavior when custom CSS files are specified via the --CSS_files parameter — i.e. achieving the same as point (1) but without requiring additional CLI parameters.

Solution (2) is probably a bad idea, since in most cases end users just want to employ the default stylesheets, or some custom stylesheets stored in PMLC data folders, where in both cases the idea is to create a copy of these stylesheet, which are just multi-use templates.
But even in these cases, it might be useful to be able to control where the CSS file copies end up — i.e. being able to bypass the css/ subfoldering convention by either storing them in the same path as the HTML file, or in a custom folder with any arbitrary name.

But it's clearly important to be able to inform PMLC when a set of custom CSS files need to be copied and linked in the final HTML docs, and when they need to be linked only instead — ideally, PMLC should allow even a combination of both, via different parameters that can be used alongside.

Current Workarounds

Currently there are three possible workarounds to this, all of which require post-PMLC interventions:

  1. Tweak the generated HTML files, substituting all CSS paths within their headers, e.g.:

    <link rel="stylesheet" href="css/pml-default.css">
    <link rel="stylesheet" href="css/pml-print-default.css" media="print">

    by stripping the css/ path segment:

    <link rel="stylesheet" href="pml-default.css">
    <link rel="stylesheet" href="pml-print-default.css" media="print">
  2. Tweak the CSS copies within the css/ subfolder, substituting all CSS map paths within their end comment, e.g.:

    /*# sourceMappingURL=pml-default.css.map */

    by adding a ../ to the CSS path in order to seek for it in the parent-directory, where the Sass sources are usually located too, along with the original CSS files:

    /*# sourceMappingURL=../pml-default.css.map */
  3. Copy into the css/ folder all the Sass sources too (including their modules), so that the CSS map paths can be matched to their sources again.

Solution (1) is usually better, since it then allows to view changes to the Sass-generated CSS files by simply refreshing the HTML test docs. The only downside is when there are more HTML test documents involved than CSS files.

Solutions (2) and (3) both result in duplicate files, especially the latter which creates redundant copies not just of the CSS files but also all their Sass sources. Solution (3) also requires rebuilding the HTML test documents via PMLC and then copying again all Sass/CSS file when there are significant changes within the Sass sources and/or their modular structure.

As you can imagine, all of these solution are nothing more than hack-&-slash workarounds to the current limitation imposed by the PMLC native subfoldering conventions. Needless to say, in automated projects any of the above solutions is far from ideal and requires considerate extra scripting work to implement as a post PMLC conversion fix.

Links URL and Relative Paths

@pml-lang, while working on the pandoc PML Writer I've started including test documents from pandoc's test suite. These are documents in various formats covering many formatting elements and their possible combinations.

Although the Lua filter is correct, many of these documents fail conversion via PMLC because they either contain images pointing to the Internet, or links with relative paths, etc., which PMLC doesn't support.

Example, a document containing a link pointing to /url results in the following PMLC error:

pmlc writer.pml
Error      '/url' is an invalid value for parameter 'url'. Reason:
           '/url' is an invalid URL Reason:
           '/url' is not a valid URL. Reason:
           no protocol: /url
Code       [ch [title Level 2 with an [link url=/url text="embedded link"]]

Error id   INVALID_ATTRIBUTE

I really can't understand why PMLC enforces these restrictions on links and images paths, acting like a sort of validator.

The inability to use images stored on the web, or provide links that use relative paths, or protocols others than those accepted by PMLC (from gopher:// to MS res://, up to custom URL Monikers) is a huge impediment in the adoption of PML for many domain specific applications:

  • Relative URLs are essential for publishing web pages, and an /url link like the one from the above error message would be a normal link on a custom server.
  • Support for the res:// protocol is essential for storing HTML documents (or images and other assets) into DLLs, and then accessing them from within an application (e.g. via the WebControl).
  • Custom URL Monikers are essential for launching installed apps (with options) from a webpage (Skype, GitHub Desktop, etc.) or to implement applications like Executable eBooks (which serve pages via URL monikers to protect contents).
  • PML only recognizes as valid protocols a very limited number of the existing protocols — I've tested them, but don't have the full list here, but I remember that legacy protocols like gopher, telnet, and many others cause conversion to fail.

When I think of the HTML format and it's innumerable applications (from HTML based eBook formats to software using WebComponent GUIs) I really struggle with these limitations, especially not being able to include images from the web.

Also, why should PMLC check if an image exists at all? In many documentation toolchains the images are generated on the fly, from ASCII blocks within the source document (or elsewhere), so they are deleted before each, and not available until after the conversion. Procedurally generated images are such a strong component of software documentation that I can hardly imagine working without them (think of railroad diagrams, etc.).

You should really consider either revising the way PMLC handles URL attributes, or at least provide some alternative attributes that allow handling relating paths within any URI scheme and/or custom protocols or monikers.

I fail to see the reasons for the current errors, since all of the above mentioned cases adopt the same convention for how a protocol/moniker is expressed in terms of <name>://path/segmented/by/slashes/.

The fact that so many basic test docs from pandoc test suite are failing to build with PMLC — not due to failed pandoc to PML conversion, but because of unsupported paths/URLs in PMLC — is a strong indicator that there's something wrong with how PMLC approaches resources paths and links. All the markup syntaxes I've worked with don't attempt to validate paths and URLs (unless you specify options like embedding images as Data URIs), for they assume the author knows what he/she's doing — it could be just a document template, or the image is temporarily unreachable due to a server being done, or the HTML page is intended to be used inside a running executable app, from a DLL ... you name it, there could be hundreds of reasons why an external asset is not reachable at the specified path/URL.

I think these problems have to be solved natively, i.e. in the vanilla PML syntax, as opposed to via custom scripts or extensions.

What are the reasons behind the current way PMLC handles images paths and links? Why links are expected to be expressed via protocols, when an HTML page might simply want to link to another page in the same folder (possibly without having to resort to the file:// protocol)?

PML Convert 1.3.0: GUI screen bug

Step to reproduce:

Clicking in the GUI at the point indicated by the arrow, clears the screen:

Clears-the-screen

Result:

This results in a blank screen with just the window title:

Blank-Screen

Comment:

The black dot seems to be part of a background window mostly hidden by the main window. Clicking anywhere else on the thin border does not cause any problems. Just the black dot clears the screen.

Is this background window required for the GUI to function? In any case, the GUI has to be closed as there is nothing with which to interact.

PML Convert 1.4.0: Broken Link

The download link in the download page for Windows is broken:

https://www.pml-lang.dev/downloads/windows/PML%20to%20HTML%20Converter-1.4.0.exe

any attempts to download the PML to HTML Converter-1.4.0.exe file result in a non-existing file error.

Also, it's currently hard to learn which is the latest PML Converter version, since it's no mentioned anywhere in the website, not even in the downloads or install pages — to learn which is the latest version one has to actually hover on the download button and check the URL in the browser status bar.

It would be better if the website were to display the latest PML converter version in the shared top banner, and mention it explicitly in all the download related pages.

Also, since there's no auto-update feature, it would be nice to have some mechanism to be informed on new binary releases, e.g. an RSS feed to which one could subscribe (so any updates will be notified on email clients, etc.).

PMLC 3.1.0 Crashes on Empty [options Node

Converting the following PML document with empty [options node:

[doc [title Test] [options ]]

results in the following crash error:

ERROR:
The operation has been aborted due to the following unexpected application error:
java.lang.NullPointerException: Cannot invoke "dev.pp.parameters.textTokenParameter.TextTokenParameters.getList()" because "parameters" is null
    at dev.pp.parameters.textTokenParameter.TextTokenParameters.merge(TextTokenParameters.java:112)
    at dev.pmlc.ext.utilities.pmltohtml.options.PMLToHTMLOptionsHelper.createMergedOptions(PMLToHTMLOptionsHelper.java:71)
    at dev.pmlc.commands.pmltohtml.PMLToHTMLCommand.convertDocumentNode(PMLToHTMLCommand.java:147)
    at dev.pmlc.commands.pmltohtml.PMLToHTMLCommand$Executor.execute(PMLToHTMLCommand.java:120)
    at dev.pmlc.commands.pmltohtml.PMLToHTMLCommand$Executor.execute(PMLToHTMLCommand.java:39)
    at dev.pp.commands.command.CommandExecutor.execute(CommandExecutor.java:17)
    at dev.pp.commands.command.FormalCommand.execute(FormalCommand.java:159)
    at dev.pp.commands.picocli.PicocliCommandLineExecutor.executeSubCommand(PicocliCommandLineExecutor.java:72)
    at dev.pp.commands.picocli.PicocliCommandLineExecutor.executeCommand(PicocliCommandLineExecutor.java:41)
    at dev.pmlc.commands.PMLCommands.runCommand(PMLCommands.java:29)
    at dev.pmlc.commands.Start.main(Start.java:20)

Please consider sending the above message to the developers of the application, so that this problem can be fixed.
[Finished in 1.7s]

Empty options should be acceptable, e.g. for procedurally generated documents which might or might not inject options into the node, and in any case PMLC should at the most produce a warning but still convert the rest of the document (if valid).

HTML Attributes Ignored on Images

I noticed that with PMLC 3.1.0 I'm failing to render HTML Attributes for images alt or title text:

[image source="./apple.png" html_alt="Some text"]
[image source="./apple.png" html_title="Some text"]

both statements will just produce the following HTML snippet:

<figure style="text-align: left">
    <img class="pml-image" src="./apple.png">
</figure>

As far as I can remember, both used to work fine in my previous tests with PML 2.x, and the html_alt is even mentioned in the PML User Manual examples.

I haven't had a chance to test whether this is affecting just images or other elements too, but it definitely looks like a bug that crept in with the latest updates (either 3.0 or 3.1.0).

Discrete Headings to Exclude Sections from TOC

Add an attribute to the [title node that allows excluding an heading from the TOC — something toc_exclude = true, where the default would be false, or toc_include if that's more inline with the way attributes are defined.

This is inspired by AsciiDoc's discrete headings, which can be enabled via the discrete attribute on any heading:

[discrete]
== Discrete Heading

In Asciidoctor a discrete heading is still generated as an heading tag (<h1>..<h6>), but it's excluded from the TOC, and furthermore:

A discrete heading is declared and styled in a manner similar to that of a section title, but:

  • it’s not part of the section hierarchy,
  • it can be nested in other blocks,
  • it cannot have any child blocks,
  • it’s not included in the table of contents.

The above points are important in Asciidoctor, because with real headings you can't skip levels (e.g. jump from <h1> to <h3>) or use headings inside blocks (e.g. a quotation block, etc.).

As for PML, I think that the goal should be to simply exclude these headings from the TOC generation and computation process (i.e. as if the discrete headings were simply not there).

It might be worth considering whether any child headings of a discrete heading should be computed or not in the TOC. E.g. the problem is that by excluding a Level-2 heading via discrete, if that section has sub-sections then all the sub-headings would need to be manually set as discrete too, otherwise there would be a level-gap in the final TOC, where the discrete heading results in a direct jump from Level-1 to Level-3 because it's not being considered in the TOC generation. Unless the TOC ends up considering the next [ch node as being Level-2 (since in PML chapter nodes don't contain level info, but the level is deduced from their nesting level), which probably doesn't make sense.

So, probably it makes more sense to consider any children of a discrete heading as being discrete too, otherwise the computation of nested TOC levels gets all out of synch.

In any case, this needs to be considered because PML differs from other lightweight markups in this respect, where AsciiDoc and Markdown headings contain in themselves their heading-level info (=, ==) whereas in PML is the actual nesting in the final document tree that determines their level.

References

Default CSS: Add PMLC Version Info

Pleas inject into default CSS styles the version number of the pmlc tool that generated them, i.e. within the stylesheets commented header, at the beginning.

This might be a safer practice, in case end users are manually modifying copies of these CSS files for substituting the default CSS generated by pmlc. Having pmlc version info might warn end users of possible changes in class names or the HTML template structure.

List Enhancements

PMLC 3.1.0 | Windows 10 (x64)

The PML source line:

[list (html_style="list-style-type:decimal" html_start=3)

caused the following PARSER_EVENT_HANDLER_ERROR crash error:

pmlc p2h pandoc.pml
ERROR:
Message    An error occurred in the parser's event handler.
Code       [list (html_style="list-style-type:decimal" html_start=3)
                                                                    ^
Location   pandoc.pml (OMITTED_PATH\pandoc.pml)
           Line 113, column 58
Error id   PARSER_EVENT_HANDLER_ERROR

Cause:
The operation has been aborted due to the following unexpected application error:
java.util.ConcurrentModificationException
        at java.base/java.util.LinkedHashMap$LinkedHashIterator.nextNode(LinkedHashMap.java:756)
        at java.base/java.util.LinkedHashMap$LinkedValueIterator.next(LinkedHashMap.java:783)
        at dev.pmlc.core.parser.PMLParserEventHandler.setHTMLAttributes(PMLParserEventHandler.java:410)
        at dev.pmlc.core.parser.PMLParserEventHandler.setAttributes(PMLParserEventHandler.java:332)
        at dev.pmlc.core.parser.PMLParserEventHandler.onAttributes(PMLParserEventHandler.java:262)
        at dev.pmlc.core.parser.PMLParserEventHandler.onAttributes(PMLParserEventHandler.java:48)
        at dev.pdml.core.parser.PDMLParser.parseAttributes(PDMLParser.java:281)
        at dev.pdml.core.parser.PDMLParser.requireNode(PDMLParser.java:150)
        at dev.pdml.core.parser.PDMLParser.parseChildNodes(PDMLParser.java:296)
        at dev.pdml.core.parser.PDMLParser.requireNode(PDMLParser.java:159)
        at dev.pdml.core.parser.PDMLParser.parseChildNodes(PDMLParser.java:296)
        at dev.pdml.core.parser.PDMLParser.requireNode(PDMLParser.java:159)
        at dev.pdml.core.parser.PDMLParser.parseChildNodes(PDMLParser.java:296)
        at dev.pdml.core.parser.PDMLParser.requireNode(PDMLParser.java:159)
        at dev.pdml.core.parser.PDMLParser.parseChildNodes(PDMLParser.java:296)
        at dev.pdml.core.parser.PDMLParser.requireNode(PDMLParser.java:159)
        at dev.pdml.core.parser.PDMLParser.requireRootNode(PDMLParser.java:107)
        at dev.pdml.core.parser.PDMLParser.parse(PDMLParser.java:84)
        at dev.pdml.core.parser.PDMLParser.parsePDMLReader(PDMLParser.java:71)
        at dev.pmlc.core.parser.PMLParser.parseReaderWithoutThrowingIfNonCancellingErrorDetected(PMLParser.java:97)
        at dev.pmlc.core.parser.PMLParser.parseReader(PMLParser.java:65)
        at dev.pmlc.commands.pmltohtml.PMLToHTMLCommand$Executor.execute(PMLToHTMLCommand.java:112)
        at dev.pmlc.commands.pmltohtml.PMLToHTMLCommand$Executor.execute(PMLToHTMLCommand.java:39)
        at dev.pp.commands.command.CommandExecutor.execute(CommandExecutor.java:17)
        at dev.pp.commands.command.FormalCommand.execute(FormalCommand.java:159)
        at dev.pp.commands.picocli.PicocliCommandLineExecutor.executeSubCommand(PicocliCommandLineExecutor.java:72)
        at dev.pp.commands.picocli.PicocliCommandLineExecutor.executeCommand(PicocliCommandLineExecutor.java:41)
        at dev.pmlc.commands.PMLCommands.runCommand(PMLCommands.java:29)
        at dev.pmlc.commands.Start.main(Start.java:20)

Please consider sending the above message to the developers of the application, so that this problem can be fixed.

See also my recent bug report about other problems with HTML attributes handling: #90

PMLC: Add Opts to Launch Manuals

Christian, it would be nice to have dedicated options in PMLC to open up a bundled version of the PML Reference Manual and PML User Manual, respectively, which always matches the PMLC version.

Since the online version of these docs don't always match the latest release, and because end users might be sticking to a specific (older) version of PML for their work, it would be a great service to grant quick access to local copies of the docs, matching the exact PMLC version being used.

I'm aware that the PML package does contain the PML Reference Manual sources (but not the PML User Manual) and that users could build the document themselves in a few steps, but having a PMLC option to open up both docs in the browser would be a much easier way to go about it.

Something like:

pmlc userman
pmlc refman

Add Alternative Text for <img> tags

Hi Christian (@pml-lang),

I noticed that the online version of the manual was generated by PML 1.2.0 and that one of the differences from the current 1.3.0 version is that tag has a closing "/" character.

As a further enhancement, in terms of accessibility, it is recommended that each image has a text alternative. Even in cases where there is no valid alternative, an empty alt tag is still recommended.

In the PML Reference Manual, in the section for the image node, there are attributes for captions, node title, etc. but nothing for alternative text. Should this be included? Could alt="" be added as a default value for this attribute of the tag?

Kind Regards,
Liam

Generated JSON: Add New Boolean Keys "is_block_type" and "is_inline_type"

Currently the PMLC generated JSON provides a "type" key with a value either "block" or "inline". That's great, and it should be kept as is.

But for mustache templates processing, it would be very useful to also have two new boolean keys representing the node type:

  • "is_block_type"
  • "is_inline_type"

where (obviously) one will always be true and the other false.

The rationale for this addition is that mustache is logic-less, so it can't filter tags by comparing their values against expected values, but only filter them by boolean states true/false or null/non-null.

Having these (redundant) keys would allow mustache template to filter tags according to types, without having to introduce Lambdas (which would render templates language-specific).

I know that having these redundant keys is not DRY, but hopefully it won't hurt either — after all, this auto-generated JSON document has a wide range of potential uses, ranging from tools that fully parse the JSON file to carry out complex operations, down to simpler uses like mustache templates, which operate at a simpler level.

The current "type" key is still useful in mustache templates, e.g. when generating a markdown table resuming all nodes proprieties, where it can be used to fill-in the cells of a "node type" column with either "block" or "inline". Whereas the proposed boolean keys would be used to produced filtered tags list, i.e. showing all tags of either block or inline type.

This principle of having a double standard in the generated JSON file, i.e. both a key+value and boolean variants thereof holds true for any PML node/tag/attribute which might be worth filtering — obviously, within reason, since if the possible values are in excess of three or four variants it might involve too many additional boolean keys to represent them in a filterable way.

Hopefully, the size of the JSON file shouldn't really matter, since it's intended for machine-processing rather than human consumption, and as long as the newly requested keys are easy to handle on the PMLC code generator side it should be fine.

Now that PML has grown mature, I'm seeing how the autogenerated JSON file is starting to become increasingly useful in a wide range of applications — from self-updating reference documents in lightweight markup languages, to syntax highlighter and editor syntax templates.

Each tool and application domain will probably focus on specific keys, ignoring the rest, so having too many keys/entries shouldn't be a problem either. Again, which keys are "important" is relative to the task at hand.

It's one of these tools that it's either very useful or totally useless, depending on the context, and in the case of mustache templates the lack of boolean alternative keys for filtering tags can make a huge difference in the usability of the JSON file.

So I guess that as time goes by, we'll be seeing more needed keys additions, based on new real case uses.

Word Boundaries in Opening Node Tags

The line An [c\[admon] block raises a conversion error:

Error: 'c\' is an invalid node tag.

Forcing to change the line to An [c \[admon] block.

I would expect the pmlc parser to consider any invalid token ID character (i.e. [^a-z_]) as a word boundary, making it unnecessary to insert a space when a tag is followed by an escape, the [ of a nested node, etc.

At least, this is how I've implemented most tags in Sublime PML, where nodes are usually captured via a RegEx like (?<!\\)\[c\b. This seems the natural way to handle opening node tags, for it will cover all sort of contexts — e.g. the tag being followed by spaces, tabs, or even a new line:

Some [c
    inline
    code
]

which is perfectly valid PML code.

In any case, these details are important to know to correctly implement editor syntaxes that correctly mimic pmlc's behaviour — as the saying goes, "The devil is in the details".

Table of Contents entries cut off on mobile

Hi Christian (@pml-lang),

I was checking the PML User Manual on my mobile phone and found that the Table of Contents was not appearing correctly. Several words were being cut-off as seen in the screenshots below.

To see this effect using Firefox on my desktop, I went into Developer Tools and selected the Responsive Design Mode icon over on the top-right of the panel:

Responsive-Design-Mode

The alternative method is to select the Web Developer option from the "burger" menu, which gives these options:

Web-Developer-Menu

In Responsive Design Mode, several Device Settings are available in the drop-down. For example:

  • Galaxy S9/S9+
  • iPhone 6/7/8
  • Kindle Fire HDX Linux

Other device settings can be chosen by using the "Edit List..." option at the bottom of the drop-down.

The Galaxy S9/S9+ view in Landscape mode gives this:

Galaxy-S9-Landscape

The iPhone 6/7/8, again in Landscape mode, has a similar problem:

iPhone-6-Landscape

I know little about responsive design or how the CSS, perhaps, might have an impact on the layout of the page. In any case, the default HTML / CSS might need to be reviewed for how the Table of Contents is displayed on various mobile platforms.

Kind Regards,
Liam

PML v2.1.0 Download Results in v2.0.0

I've just downloaded PML v2.1.0 (for Windows), but after installation I get v2.0.0:

$ pmlc -version
PML version: 2.0.0 2021-09-03

Although the PML Changelog mentions v2.1.0 being a bug fix release, the date is supposed to be 2021-09-09, so it looks like I've downloaded again v2.0.0.

Where can I get the installer for v2.1.0?

Fatal Conversion Error: [text Inside [title

While experimenting nodes-nesting with PML 2.3.0 I came across a fatal error when a [text node is nested within a [title node.

Trying to convert the following source document:

[doc [title Error Sample]
  [ch [title Title With [text Text] Node ]]
]

results in the following error:

THE FOLLOWING APPLICATION ERROR OCCURRED (2022-07-27T04:36:09.8544301):
Should never be called
See file 'D:\some_path\errors.log' for more information.

[Finished in 1.2s]
Click here to view the contents of the `errors.log` file...
THE FOLLOWING APPLICATION ERROR OCCURRED (2022-07-27T04:36:09.8544301):

Error         : Should never be called
Location      : Factory PML_text_node_creator.create_node (dev.pml.converter.tree_creator.node_creator.creators.inline_n
                ode.text)
                line 9
Time          : 2022-07-27 04:36:09
Info          : Should never be called

Trace:
> Factory PML_text_node_creator.create_node, line 9 (dev.pml.converter.tree_creator.node_creator.creators.inline_node.text)
> Factory PML_tree_creator.create_inline_child_nodes, line 412 (dev.pml.converter.tree_creator)
> Factory PML_tree_creator.create_node_creator_context, line 92 (dev.pml.converter.tree_creator)
> Factory PML_tree_creator.create_block_child_nodes, line 257 (dev.pml.converter.tree_creator)
> Factory PML_tree_creator.create_node_creator_context, line 97 (dev.pml.converter.tree_creator)
> Factory PML_tree_creator.create_block_child_nodes, line 257 (dev.pml.converter.tree_creator)
> Factory PML_tree_creator.create_node_creator_context, line 97 (dev.pml.converter.tree_creator)
> Factory PML_tree_creator.try_create_tree_2, line 56 (dev.pml.converter.tree_creator)
> Factory PML_tree_creator.try_create_tree, line 17 (dev.pml.converter.tree_creator)
> Service PML_to_HTML_Converter.try_create_HTML_file, line 106 (dev.pml.converter)
> Service PML_to_HTML_Converter.try_convert, line 29 (dev.pml.converter)
> Service PML_convert_command.execute, line 210 (dev.pml.converter.PAIOM_commands)
> Service PML_convert_command.execute, line 165 (dev.pml.converter.PAIOM_commands)
> Factory single_command_executor.execute_command, line 11 (org.ppl.paiom.config.execution.single_command_executor)
> Service execute_command_meta_command.execute_command, line 102 (org.ppl.paiom.meta_commands.commands.execute_command)
> Factory paiom.execute_meta_command, line 156 (org.ppl.paiom)
> Factory paiom.execute_command_from_string_data_2, line 87 (org.ppl.paiom)
> Factory paiom.execute_command_from_string_data, line 43 (org.ppl.paiom)
> Factory paiom.execute_command_from_command_line_arguments, line 14 (org.ppl.paiom)
> Service PAIOM_command_executor.execute_command_line_arguments, line 18 (org.ppl.paiom)
> Service PAIOM_command_executor.execute_command_line_arguments_2, line 35 (org.ppl.paiom)
> Service PAIOM_command_executor.execute_command_line_arguments_3, line 60 (org.ppl.paiom)
> Service CLI_start.execute_command_line_arguments, line 72 (dev.pml.converter)
> Service CLI_start.start, line 34 (dev.pml.converter)
> Service start.start, line 10 (dev.pml.converter)

I wanted to verify which kind of nodes can be used within a [title, so I tried nesting various block nodes to see which errors they would produce.

So far, it seems that only the [text node results in PMLC failure, all the other block nodes I've tried failed with a meaningful error message, and even non-existing node (e.g. [xyz fail gracefully), so it seems to be a problem specific to [text nodes.

PDML vs PML Docs Bug: Different ID Patterns

BUG: ID pattern mentioned in PDML and PML differ!

PDML:  [a-zA-Z_][a-zA-Z1-9_\.-]*
PML:   [a-zA-Z][a-zA-Z0-9_-]*

@pml-lang, in #56 you mentioned:

Yes. To cover all cases, the plugin should use the regex shown in the PDML Specification: [a-zA-Z_][a-zA-Z1-9_\.-]*

which prompted me to check the PML docs on how ID patterns are defined, and I immediately noticed that in the PML Manual and PML Reference whenever the custom ID pattern is mentioned it's: [a-zA-Z][a-zA-Z0-9_-]* and not [a-zA-Z_][a-zA-Z1-9_\.-]* — i.e.:

  1. the dot \. mentioned in the PDML Specification is missing).
  2. The first character can be an underscore _ according to PDML (but not PML).

The same when invoking PMLC for tags info:

> pmlc ti -t admon

    Admonition
----------
Tag            : admon
[...]
Attributes:
1.
Id             : id
Title          : Node Identifier
Type           : string or null
Description    : A unique identifier for the node.
                [...]

                 Note for programmers: The regex of an identifier is: [a-zA-Z]
                 [a-zA-Z0-9_]*. Identifiers are case-sensitive.

So which one is correct? the one with the . and _ or the one without them?

Add Inline Node for <kbd> HTML Tag

It would be useful to have an inline node for keystrokes, to generate the <kbd> HTML tag.

Possible node tags: [key or just [k.

Example:

[k Ctrl] [k Shift] [k Z]

which would be rendered as:

Ctrl Shift Z

with HTML code:

<kbd>Ctrl</kbd> <kbd>Shift</kbd> <kbd>Z</kbd>

(see below for an alternative node syntax)

Note that in the above example I've inserted spaces between the keys, but many people don't, while others insert the + symbol:

[k Ctrl][k Shift][k Z]

[k Ctrl]+[k Shift]+[k Z]

rendered as:

CtrlShiftZ

Ctrl+Shift+Z

... it's a matter of personal taste, but it should be kept into account in the implementation.

Multi-Keys Node

Also, not how Asciidoctor implements it via the Keyboard Macro:

kbd:[Ctrl+Shift+Z]

(rendered as: Ctrl+Shift+Z)

It's smart because it uses just one keyword to handle multiple keys, using + as a separator (two pluses + + will produce the + key).

So PML could also do that, and instead of the above proposed implementation, could instead:

[k Ctrl+Shift+Z]

CSS Styling

For some nice styling of the keys via ready-to-us CSS stylesheets, see:

IMO, the first link offers the best CSS effects for keys, and also provided different styles.

The second on is beautiful looking, but maybe not so practical for inline styling (keys are too big).

Simulated run option

I propose a "simulated run" option that will show the results of a command without truly executing it. Hypothetical example:

Normal run:
pmlc convert --input_file "$inputFilePath" --output_directory "$outputFolderPath"

Simulated run:
pmlc convert --input_file "$inputFilePath" --output_directory "$outputFolderPath" --simulate

The new argument would look like this:

Id             : simulate
Title          : Simulate
Type           : yes_no
Description    : If this parameter is set to 'yes' then:
                 - the output directory is not generated if it doesn't already exist
                 - no files are copied to the output directory
                 - the intended changes are revealed to the console output
                 By default this parameter is set to 'no'.
Required       : no
Default value  : no
Examples       : --simulate

The simulated run can show the intended changes to the generated output, similar to Ansible's --check or --diff argument or Terraform's plan command.

An alternatve implementation might be like Terraform's --auto-approve option, wherewith the intended changes are revealed, and the executable by default pauses for user input ("Do you want to continue?") before applying the changes, with the auto-approve argument overriding that behavior to not pause.

The console output might also helpfully reveal the locations of the output_directory, resources_directory, etc. as they will appear on your file system after the command is run for real. This in turn can help you know whether your arguments are set correctly. Sample output might include this information, for instance:

Input file                      : my project/my input file.pml
Input file resolves to          : /home/user/my workspace/my project/my input file.pml
Output directory                : ../../my generated HTML
Output directory resolves to    : /home/user/my generated HTML/
Resources directory             : null
Resources directory resolves to : (not generated: resource references will be dangling) <-- (bad wording on my part, but you get the idea)

For inspiration by similarity, see also pmlc command_info --command convert which appears to dynamically show certain "default values" as resolved relative to your file system:

2.
Id             : HTML_header, html_header, header
Type           : absolute_or_relative_file_path or null
Required       : no
Default value  : /home/user/myapps/PML/pml-to-html-converter_1.5.0-1_amd64/lib/runtime/resources/html/default_html_header.txt

Edge Case BUG: Paragraph Emitted Twice

I've come across a very odd bug with PML 1.5.0...

The following source:

[doc title = PML BUGS Test \
    authors = Tristano Ajmone \
    date = 2021-06-26

[ch title = "Miscellanea" \
    id = chapter_id
    Hello



]

]

will produce an HTML doc where the Hello paragraph is shown twice in a row — but only if:

  • There's no blank line between the id = line and "Hello" line.
  • There are at least 3 blank lines between the "Hello" line and the closing ].

List element with parentheses errs

If the el node begins with an open parenthesis, the compiler errs as below. What is the error message talking about when it says it expects a =? Are parentheses special?

[el (some) text here]
Error: Expecting attribute assignment operator '='.
                [el (some >>> ) text here]

Node Repetition via Asterisk

Instead of writing a chain of multiple non-breaking-space [sp] or newline [nl] nodes:

[sp][sp][sp]
[nl][nl]

we could instead adopt a multiplier-style syntax to indicate node repetitions:

[sp*3]
[nl*2]

Usually when one needs to use the [sp] node is because a single space is not enough, so this notation would allow to save space by using a single node to represent multiple spaces. Probably the need for multiple [nl] nodes is less frequent, since it's usually employed just to hard-break within a paragraph, but there might be cases where multiple newlines are needed — and, in any case, it might be worth supporting this notation for both nodes, for consistency sake.

Although this notation doesn't align with the general PML syntax adopted so far, IMO it makes sense in this context due to its simplicity and inactivity — since it resembles the customary multiplication syntax it's very easy to remember.

Both of these nodes are childless and don't support any type of attributes, which might further justify this notation applying to them as an exception to the rule.

The only other context where a similar notation might make sense it's table cells, where the [tc] node could adopt the x*y notation to indicate columns and rows spanning — e.g. [tc 2*3] for a cell spanning two columns and three rows; [tc 4*0]/[tc 4*] for spanning four columns; [tc 0*5]/[tc *5] spanning five rows, etc.; where a zero-value can be simply omitted, since the position of the other value in respect to the asterisk clearly indicates whether it refers to a column (lhs) or a row (rhs).

Parser Inconsistency with Quoted IDs

PMLC 3.1.0 | Win 10

According to documentation an ID must abide to the RE pattern:

[a-zA-Z_][a-zA-Z0-9_\.-]*

but if you try to compile the following document:

[doc [title ( id = "valid-ID  " ) Quoted ID]]

the actual ID in the generated HTML includes the trailing spaces:

<h1 id="valid-ID  " class="pml-doc-title">Quoted ID</h1>

PMLC should either (1) emit an error due to invalid ID definition, or (2) strip away the extra spaces from the final ID. IMO solution 1 is better because it enforces stricter documents.

Side Note

I've come across this inconsistency while implementing quoted IDs in Sublime PML — originally I didn't add support for them, because I though no one would use them since IDs can't contain spaces, but then I noticed that the PML documentation frequently quotes IDs so I started to work on this feature.

Quoted IDs add various extra layers of complexity to editor syntaxes, because of the many edge cases that can encountered — e.g. if there isn't a closing quote on the same line, the syntax needs to gracefully recover so it doesn't break the whole document; along with other cases such as a valid ID followed by spaces, etc.

Whenever I work on a new syntax feature I always carry out some practical experiments with PMLC, just to check how the parser handles edge cases, so that I can find the right balance between how far Sublime PML can support edge cases and how PMLC handles them in real document conversion. This is how I came across this parser bug, i.e. by testing for edge cases handling.

I was quite surprised that such a parsing inconsistency/bug could have slipped by unnoticed, I would have expected the PMLC repository to have a test suite to cover IDs edge cases. Without a solid test suite it's going to be hard to ensure a linear and bug-proof growth of PML — even with Sublime PML, which is just an editor syntax, I wouldn't be able to work on it without covering each feature with extensive tests, to ensure that new features don't break previous ones.

Even though I'm not a Java expert, I know that Java has probably more test libraries than any other language out there, so it shouldn't be hard to add a solid test suite to PMLC.

PMLC v3.1.0 Segfault on Linux

Description
Immediate segfault on startup.

Reproducing
Download standalone pmlc binary v3.1.0.
Run pmlc.

Expected vs actual behavior
Expect the app to run.
Actually segfaults.

Application version
PMLC v3.1.0 (standalone)

Your OS name and version
Arch Linux (Garuda)

Linux 5.18.3-zen1-1-zen #1 ZEN SMP PREEMPT_DYNAMIC Thu, 09 Jun 2022 16:14:13 +0000 x86_64 GNU/Linux
openjdk 18.0.1.1 2022-04-22
OpenJDK Runtime Environment (build 18.0.1.1+2)
OpenJDK 64-Bit Server VM (build 18.0.1.1+2, mixed mode)

Log

❯ pmlc

[ [ SubstrateSegfaultHandler caught a segfault in thread 0x000000000b3cec00 ] ]
siginfo: si_signo: 11, si_code: 1, si_addr: 0x00000000000000e5

Current timestamp: 1665367364174

General purpose register values:
  RAX 0x0000000000000072 is an unknown value
  RBX 0x000000000b3cefd0 is an unknown value
  RCX 0x0000000000000000
  RDX 0x0000000000000072 is an unknown value
  RBP 0x00007f6eca5f42a0 is an unknown value
  RSI 0x00007f6eca5f4481 is an unknown value
  RDI 0x000000000b3cefd1 is an unknown value
  RSP 0x00007fff735ac2c0 points into the stack for thread 0x000000000b3cec00
  R8  0x00007f6eca5f449c is an unknown value
  R9  0x0000000000000000
  R10 0x0000000000001000 is an unknown value
  R11 0x0000000000000246 is an unknown value
  R12 0x00007fff735ac310 points into the stack for thread 0x000000000b3cec00
  R13 0x000000000b3cf3cf is an unknown value
  R14 0x0000000000000400 is an unknown value
  R15 0x000000000b3cefd0 is an unknown value
  EFL 0x0000000000010246 is an unknown value
  RIP 0x00007f6eca830ec5 is an unknown value

Printing Instructions (ip=0x00007f6eca830ec5):
  0x00007f6eca830ea5: 0x41 0x80 0x7d 0x00 0xff 0x0f 0x85 0xbc 0x00 0x00 0x00 0x48 0x8b 0x05 0xa1 0xfe
  0x00007f6eca830eb5: 0x0b 0x00 0x49 0x0f 0xbe 0x17 0x4c 0x89 0xfb 0x64 0x48 0x8b 0x08 0x48 0x89 0xd0
  0x00007f6eca830ec5: 0xf6 0x44 0x51 0x01 0x20 0x74 0x17 0x0f 0x1f 0x40 0x00 0x48 0x0f 0xbe 0x53 0x01
  0x00007f6eca830ed5: 0x48 0x83 0xc3 0x01 0x48 0x89 0xd0 0xf6 0x44 0x51 0x01 0x20 0x75 0xed 0x84 0xc0

Top of stack (sp=0x00007fff735ac2c0):
  0x00007fff735ac2c0: 0x00007f6e00000000 0x000000000b3cefd0
  0x00007fff735ac2d0: 0x0000000000000400 0x00007f6eca5f42a0
  0x00007fff735ac2e0: 0x000000000b3cd830 0x0000000000000400
  0x00007fff735ac2f0: 0x00007fff735ac310 0x00007f6eca835d8d
  0x00007fff735ac300: 0x0000000009734b40 0x00000000ca775bf3
  0x00007fff735ac310: 0x0000000000000000 0x12f852641483b600
  0x00007fff735ac320: 0x00000000000003e8 0x00000000000003e8
  0x00007fff735ac330: 0x00007f6eca5f42a0 0x0000000009734b40
  0x00007fff735ac340: 0x0000000000000400 0x000000000b3cefd0
  0x00007fff735ac350: 0x00000000000003e8 0x00007f6eca836016
  0x00007fff735ac360: 0x00007fff735ac3d8 0x000000000b3cd830
  0x00007fff735ac370: 0x0000000003bed921 0x00000000000003e8
  0x00007fff735ac380: 0x0000000000000400 0x0000000009734b40
  0x00007fff735ac390: 0x00000000000003e8 0x000000000b3cefd0
  0x00007fff735ac3a0: 0x000000000b3cd830 0x0000000003b77053
  0x00007fff735ac3b0: 0xffffffffffffffb0 0x0000000000000000
  0x00007fff735ac3c0: 0x0000000000000000 0x00007fff735ac430
  0x00007fff735ac3d0: 0x00007f6ecb310918 0x000000000b3d05a0
  0x00007fff735ac3e0: 0x00007f6eca835fc0 0x12f852641483b600
  0x00007fff735ac3f0: 0x000000004e800000 0x00000000000003e8
  0x00007fff735ac400: 0x0000000009734b40 0x0000000000000400
  0x00007fff735ac410: 0x00007fff735ac430 0x00007f6ecb500000
  0x00007fff735ac420: 0x000000000b3cec00 0x0000000003b76ddb
  0x00007fff735ac430: 0x0000000043400000 0x12f852641483b600
  0x00007fff735ac440: 0x0000000002717570 0x00007f6ece633cf8
  0x00007fff735ac450: 0x00000000008cd5be 0x00007fff735ac480
  0x00007fff735ac460: 0x00007f6ecb500000 0x00000000008cd5d1
  0x00007fff735ac470: 0x00007fff735ac500 0x0000000002a2fe79
  0x00007fff735ac480: 0x00000000008cd5be 0x00007fff735ac470
  0x00007fff735ac490: 0x0000000000000000 0x00007f6ece646868
  0x00007fff735ac4a0: 0x00007f6ecd4b1d50 0x00000000008b6896
  0x00007fff735ac4b0: 0x000000100000000f 0x00007f6ecdf34798

DeoptStubPointer address: 0x000000000083b7b0

Top frame info:
  Does not look like a Java Frame. Use JavaFrameAnchors to find LastJavaSP:
  Found matching Anchor:0x00007fff735ac480
  LastJavaSP 0x00007fff735ac470
  LastJavaIP 0x00000000008cd5be

Threads:
  0x00007f6ec4000b80 STATUS_IN_NATIVE (ALLOW_SAFEPOINT) "Reference Handler" - 0x00007f6ecde96138, daemon, stack(0x00007f6ecab01000,0x00007f6ecb300000)
  0x000000000b3cec00 STATUS_IN_JAVA (PREVENT_VM_FROM_REACHING_SAFEPOINT) "main" - 0x00007f6ecde96080, stack(0x00007fff72db1000,0x00007fff735ae000)

VM thread locals for the failing thread 0x000000000b3cec00:
  0 (8 bytes): JNIThreadLocalEnvironment.jniFunctions = (bytes)
    0x000000000b3cec00: 0x00007f6ecd8b5010
  8 (8 bytes): SubstrateFastThreadLocal.CONTEXT = (Object) null
  16 (8 bytes): SubstrateThreadLocalHandshake.STATE = (Object) null
  24 (8 bytes): StackOverflowCheckImpl.stackBoundaryTL = (Word) 1 (0x0000000000000001)
  32 (4 bytes): Safepoint.safepointRequested = (int) 2147449334 (0x7fff79f6)
  36 (4 bytes): StatusSupport.statusTL = (int) 1 (0x00000001)
  40 (4 bytes): SubstrateThreadLocalHandshake.PENDING = (int) 0 (0x00000000)
  48 (32 bytes): ThreadLocalAllocation.regularTLAB = (bytes)
    0x000000000b3cec30: 0x00007f6ecb300000 0x00007f6ecb400000
    0x000000000b3cec40: 0x00007f6ecb320ae0 0x0000000000000000
  80 (8 bytes): PlatformThreads.currentThread = (Object) java.lang.Thread (0x00007f6ecde96080)
  88 (8 bytes): JavaFrameAnchors.lastAnchor = (Word) 140735128716416 (0x00007fff735ac480)
  96 (8 bytes): AccessControlContextStack = (Object) java.util.ArrayDeque (0x00007f6ecb302298)
  104 (8 bytes): ExceptionUnwind.currentException = (Object) null
  112 (8 bytes): IdentityHashCodeSupport.hashCodeGeneratorTL = (Object) java.util.SplittableRandom (0x00007f6ecb308258)
  120 (8 bytes): IsolatedCompileClient.currentClient = (Object) null
  128 (8 bytes): IsolatedCompileContext.currentContext = (Object) null
  136 (8 bytes): JNIObjectHandles.handles = (Object) com.oracle.svm.core.handles.ThreadLocalHandles (0x00007f6ecb3011f0)
  144 (8 bytes): JNIThreadLocalPendingException.pendingException = (Object) null
  152 (8 bytes): JNIThreadLocalPinnedObjects.pinnedObjectsListHead = (Object) null
  160 (8 bytes): JNIThreadOwnedMonitors.ownedMonitors = (Object) null
  168 (8 bytes): NoAllocationVerifier.openVerifiers = (Object) null
  176 (8 bytes): ThreadingSupportImpl.activeTimer = (Object) null
  184 (8 bytes): SubstrateDiagnostics.threadOnlyAttachedForCrashHandler = (bytes)
    0x000000000b3cecb8: 0x0000000000000000
  192 (8 bytes): ThreadLocalAllocation.allocatedBytes = (Word) 0 (0x0000000000000000)
  200 (8 bytes): VMThreads.IsolateTL = (Word) 140113834147840 (0x00007f6ecb500000)
  208 (8 bytes): VMThreads.OSThreadHandleTL = (Word) 188536960 (0x000000000b3cd880)
  216 (8 bytes): VMThreads.OSThreadIdTL = (Word) 188536960 (0x000000000b3cd880)
  224 (8 bytes): VMThreads.StackBase = (Word) 140735128723456 (0x00007fff735ae000)
  232 (8 bytes): VMThreads.StackEnd = (Word) 140735120347136 (0x00007fff72db1000)
  240 (8 bytes): VMThreads.StartedByCurrentIsolate = (bytes)
    0x000000000b3cecf0: 0x0000000000000000
  248 (8 bytes): VMThreads.nextTL = (Word) 0 (0x0000000000000000)
  256 (8 bytes): VMThreads.unalignedIsolateThreadMemoryTL = (Word) 188541952 (0x000000000b3cec00)
  264 (4 bytes): ActionOnExitSafepointSupport.actionTL = (int) 0 (0x00000000)
  268 (4 bytes): ActionOnTransitionToJavaSupport.actionTL = (int) 0 (0x00000000)
  272 (4 bytes): ImplicitExceptions.implicitExceptionsAreFatal = (int) 0 (0x00000000)
  276 (4 bytes): StackOverflowCheckImpl.yellowZoneStateTL = (int) 2130640638 (0x7efefefe)
  280 (4 bytes): StatusSupport.safepointBehaviorTL = (int) 1 (0x00000001)
  284 (4 bytes): ThreadingSupportImpl.currentPauseDepth = (int) 0 (0x00000000)

No VMOperation in progress

The 15 most recent VM operation status changes (oldest first):

The 20 most recent RuntimeCodeInfo operations (oldest first):

RuntimeCodeInfoMemory contains 0 methods:

Recent deoptimization events (oldest first):

Counters:

Java frame anchors for the failing thread 0x000000000b3cec00:
  Anchor 0x00007fff735ac480 LastJavaSP 0x00007fff735ac470 LastJavaIP 0x00000000008cd5be

Stacktrace for the failing thread 0x000000000b3cec00:
  SP 0x00007fff735ac2c0 IP 0x00007f6eca830ec5  IP is not within Java code. Trying frame anchor of last Java frame instead.
  SP 0x00007fff735ac470 IP 0x00000000008cd5be  [image code] com.oracle.svm.core.posix.headers.Pwd.getpwuid(Pwd.java)
  SP 0x00007fff735ac470 IP 0x00000000008cd5be  [image code] com.oracle.svm.core.posix.PosixSystemPropertiesSupport.userHomeValue(PosixSystemPropertiesSupport.java:52)
  SP 0x00007fff735ac4b0 IP 0x00000000008b6896  [image code] com.oracle.svm.core.jdk.SystemPropertiesSupport.userHome(SystemPropertiesSupport.java:239)
  SP 0x00007fff735ac4b0 IP 0x00000000008b6896  [image code] com.oracle.svm.core.jdk.SystemPropertiesSupport$$Lambda$c08be315aa20ccffc6d99c8ceeebd4e4a45b68c0.get(Unknown Source)
  SP 0x00007fff735ac4d0 IP 0x00000000008b6fb1  [image code] com.oracle.svm.core.jdk.SystemPropertiesSupport.initializeLazyValue(SystemPropertiesSupport.java:217)
  SP 0x00007fff735ac510 IP 0x00000000008b6e63  [image code] com.oracle.svm.core.jdk.SystemPropertiesSupport.getProperty(SystemPropertiesSupport.java:170)
  SP 0x00007fff735ac530 IP 0x000000000273b8d4  [image code] java.lang.System.getProperty(System.java:303)
  SP 0x00007fff735ac550 IP 0x000000000265f512  [image code] dev.pp.basics.utilities.os.OSDirectories.<clinit>(OSDirectories.java:11)
  SP 0x00007fff735ac580 IP 0x00000000007ea20b  [image code] com.oracle.svm.core.classinitialization.ClassInitializationInfo.invokeClassInitializer(ClassInitializationInfo.java:361)
  SP 0x00007fff735ac590 IP 0x00000000007e8a09  [image code] com.oracle.svm.core.classinitialization.ClassInitializationInfo.initialize(ClassInitializationInfo.java:277)
  SP 0x00007fff735aca90 IP 0x000000000265a7ce  [image code] dev.pp.basics.utilities.directory.DirectoryConfig.userDirectoryForApplication(DirectoryConfig.java:71)
  SP 0x00007fff735acae0 IP 0x0000000002659234  [image code] dev.pp.basics.utilities.directory.DirectoryConfig.userConfigDirectoryForApplication(DirectoryConfig.java:58)
  SP 0x00007fff735acb10 IP 0x000000000262eab0  [image code] dev.pmlc.ext.PMLCResources.<clinit>(PMLCResources.java:18)
  SP 0x00007fff735acb40 IP 0x00000000007ea20b  [image code] com.oracle.svm.core.classinitialization.ClassInitializationInfo.invokeClassInitializer(ClassInitializationInfo.java:361)
  SP 0x00007fff735acb50 IP 0x00000000007e8a09  [image code] com.oracle.svm.core.classinitialization.ClassInitializationInfo.initialize(ClassInitializationInfo.java:277)
  SP 0x00007fff735ad050 IP 0x00000000025e39b3  [image code] dev.pmlc.commands.Start.init(Start.java:31)
  SP 0x00007fff735ad070 IP 0x00000000025e39f8  [image code] dev.pmlc.commands.Start.main(Start.java:14)
  SP 0x00007fff735ad090 IP 0x00000000007d66a3  [image code] com.oracle.svm.core.JavaMainWrapper.runCore0(JavaMainWrapper.java:166)
  SP 0x00007fff735ad0b0 IP 0x00000000007d6445  [image code] com.oracle.svm.core.JavaMainWrapper.runCore(JavaMainWrapper.java:130)
  SP 0x00007fff735ad0b0 IP 0x00000000007d6445  [image code] com.oracle.svm.core.JavaMainWrapper.run(JavaMainWrapper.java:214)
  SP 0x00007fff735ad0e0 IP 0x000000000082738b  [image code] com.oracle.svm.core.code.IsolateEnterStub.JavaMainWrapper_run_5087f5482cc9a6abc971913ece43acb471d2631b(IsolateEnterStub.java:0)

VM mutexes:
  mutex "mainVMOperationControlWorkQueue" is unlocked.
  mutex "referencePendingList" is unlocked.
  mutex "thread" is unlocked.

AOT compiled code is mapped at 0x0000000000403000 - 0x0000000003ae7bbf

Heap settings and statistics:
  Supports isolates: true
  Heap base: 0x00007f6ecb500000
  Object reference size: 8
  Aligned chunk size: 1048576
  Incremental collections: 0
  Complete collections: 0

Native image heap boundaries:
  ReadOnly Primitives: 0x00007f6ecb601028 - 0x00007f6eccda6770
  ReadOnly References: 0x00007f6eccda6770 - 0x00007f6ecd8b49d0
  ReadOnly Relocatables: 0x00007f6ecd8b5000 - 0x00007f6ecdc96400
  Writable Primitives: 0x00007f6ecdc97000 - 0x00007f6ecddb5c38
  Writable References: 0x00007f6ecddb5c38 - 0x00007f6ecebe52c0
  Writable Huge: 0x00007f6ecec00030 - 0x00007f6ececde7c8
  ReadOnly Huge: 0x00007f6ececdf030 - 0x00007f6ed110ca80

Heap:
  Young generation:
    Eden:
      edenSpace:
        aligned: 0/0 unaligned: 0/0
    Survivors:
      Survivor-1 From:
        aligned: 0/0 unaligned: 0/0
      Survivor-1 To:
        aligned: 0/0 unaligned: 0/0
      Survivor-2 From:
        aligned: 0/0 unaligned: 0/0
      Survivor-2 To:
        aligned: 0/0 unaligned: 0/0
      Survivor-3 From:
        aligned: 0/0 unaligned: 0/0
      Survivor-3 To:
        aligned: 0/0 unaligned: 0/0
      Survivor-4 From:
        aligned: 0/0 unaligned: 0/0
      Survivor-4 To:
        aligned: 0/0 unaligned: 0/0
      Survivor-5 From:
        aligned: 0/0 unaligned: 0/0
      Survivor-5 To:
        aligned: 0/0 unaligned: 0/0
      Survivor-6 From:
        aligned: 0/0 unaligned: 0/0
      Survivor-6 To:
        aligned: 0/0 unaligned: 0/0
      Survivor-7 From:
        aligned: 0/0 unaligned: 0/0
      Survivor-7 To:
        aligned: 0/0 unaligned: 0/0
      Survivor-8 From:
        aligned: 0/0 unaligned: 0/0
      Survivor-8 To:
        aligned: 0/0 unaligned: 0/0
      Survivor-9 From:
        aligned: 0/0 unaligned: 0/0
      Survivor-9 To:
        aligned: 0/0 unaligned: 0/0
      Survivor-10 From:
        aligned: 0/0 unaligned: 0/0
      Survivor-10 To:
        aligned: 0/0 unaligned: 0/0
      Survivor-11 From:
        aligned: 0/0 unaligned: 0/0
      Survivor-11 To:
        aligned: 0/0 unaligned: 0/0
      Survivor-12 From:
        aligned: 0/0 unaligned: 0/0
      Survivor-12 To:
        aligned: 0/0 unaligned: 0/0
      Survivor-13 From:
        aligned: 0/0 unaligned: 0/0
      Survivor-13 To:
        aligned: 0/0 unaligned: 0/0
      Survivor-14 From:
        aligned: 0/0 unaligned: 0/0
      Survivor-14 To:
        aligned: 0/0 unaligned: 0/0
      Survivor-15 From:
        aligned: 0/0 unaligned: 0/0
      Survivor-15 To:
        aligned: 0/0 unaligned: 0/0
  Old generation:
    oldFromSpace:
      aligned: 0/0 unaligned: 0/0
    oldToSpace:
      aligned: 0/0 unaligned: 0/0

  Unused:
    aligned: 0/0

Segfault detected, aborting process. Use runtime option -R:-InstallSegfaultHandler if you don't want to use SubstrateSegfaultHandler.

Broken Tables in PML 2.3.0

Something is not right with Tables' headers in PML 2.3.0.

While HTML headers generated via [table_data are as expected, the HTML generated via normal [table nodes are not: header cells in the former are correctly assigned the pml-table-header-cell class, whereas in the latter they are assigned the pml-table-body-cell class, which makes the header cells look like normal cells.

You can see this even in the documentation examples, where you'll notice that the ordinary Table headers are not styles in bold.

Delimited Text Syntax and Unbalanced Delimiters

@pml-lang, PML 4.0.0 now adopts the Delimited Text Syntax for raw-text blocks as the proper way to format raw-blocks (see also tajmone/Sublime-PML#40).
I've noticed that the PDML documentation mentions:

The closing delimiter line must contain at least as many delimiter characters as the opening delimiter line.

And I've tested it and discovered that in fact the closing delimiter can be longer than the opening delimiter, e.g.

[code
===============
print("Hello");
===================
]

I find this choice rather problematic and unconventional.

Usually markup syntaxes require that both delimiters are balanced (i.e. same characters and length), the reason being that it prevents issues in cases where the raw-text contains delimiters.

E.g. a PML listing block like this one requires that all delimiters in the raw-text are shorter than the enclosing block delimiters:

[code
    ====================
    [code
        ===============
        print("Hello");
        ===================
    ]
    ====================
]

Of course, the situation is manageable (one just needs to ensure that the outer delimiters are longer than any inner delimiters, or use different characters: " or ~), but I don't understand the benefits of supporting delimiters with unbalanced lengths.

Strictly balanced delimiters reduce the chances of clashes between the block delimiters and any raw-text contents that might cause a false positive match for the closing delimiter — especially when including long external listings via insert_code directives.

Furthermore, as far as I can tell it's impossible to correctly implement support for different-length delimiters in most syntax packages for PML because they rely on RegEx backreferences ($1 or \1) to match the same delimiter again — one could achieve this only by ignoring trailing characters, but the correct approach here would be to match the whole line, starting from the line-start anchor ^ up to the end-of-line $:

^(?=( |\t)*["=~]{3,})

Ultimately, it seems to me that supporting unbalanced delimiters has little or no benefits, but is a potential source of problems for both end users and syntax maintainers.

Any specific reason why you decided to allow closing delimiters to be longer than the opening delimiter?

Windows: Installing PML via a Package Manager

It would really great if Windows users could install the PML converter app via the Chocolatey package manager, which greatly simplifies updates since it can fully automate the process, from un-installing previous versions, to dealing with dependencies, the registry, etc.

Thanks to the official Chocolatey GUI app, it's even easier to install and update packages, without having to use the command line.

Chocolatey packages are usually hosted on GitHub, and being just PowerShell scripts its common practice to integrate these packages to their original project via automation tools that can update the PS scripts whenever a new version is released — it boils down to recreating the PS scripts with updated version info, links, etc., and then updating the package info on Chocolatey's website.

In my experience, Chocolatey packages are only worth using if they're created by the official maintainers of a project (third party packages often end up going stale when users loose interest in the app/package), especially because of the auto-generated updates offering a strong guarantee that each new product release will be followed immediately by its Choco package being updated.

Creating the initial package might require some reading, because there are tons of settings on Chocolatey, and different ways to handle silent installations, default settings, etc.

https://docs.chocolatey.org/en-us/create/

I've noticed that PML installation currently requires restarting Windows for the process to complete. This might be a problem with Chololatey, and I'm not sure if it can handle (or allows) this, because end users must be able to auto-update multiple packages at once.

I'm not well versed in PowerShell (and it's many incarnations), so I might not of great help here, but I'm willing to dig through the Chocolatey and PowerShell docs it this might help. IMO, it shouldn't be too hard to create a Choco package, but i might require some local testing before publishing, especially for the part concerning auto-updating the Choco files from the PML repository (via some CI service like Travis CI, Circle CI, or GitHub Actions) whenever a new tagged release is published.

But I believe that being able to offer a PML Chocolatey package would be a great incentive for end users, and it would ensure that they'll always have an up to date PML converter without having to go through the manual process.

Equal sign in query string needs escaping

Hi Christian(@pml-lang),

I have found that a [link tag does not resolve correctly if a query string exists in the URL. I need to escape the = sign for the link to appear correctly in the HTML output. Here is a working example:

link-tag-with-query-string

The query string ?ref= will not work if entered "as-is". A broken URL up to the question mark appears in the output. I'm guessing that why the = needs escaping, is because the [link tag is expecting the next parameter and is not checking that it is preceded by the text attribute.

This is not a high priority issue since I have found a workaround.

Kind Regards,
Liam

Remove "date_time_created" from JSON

In the generated pml_tags.json, please remove the "date_time_created" entry because its time-stamp value make the generated JSON file non-portable — i.e. in repositories which use automated scripts to generate the pml_tags.json file, each time the JSON file is rebuilt it shows up in Git as changed, which can potentially block any toolchain Git operations that require a clean status.

Unless there are good reasons to preserve the time-stamp, it would be better to drop it (the PML version should suffice, for the same tags info should be generated for a same PML release, regardless of the timestamp of PMLC execution).

It would be far more useful to replace "date_time_created" with a "release_date" entry specifying when the current PML version was released (it would complement the "pml_version" entry).

JavaScript Date function fails in user-defined node

The following user-defined node

[node
    [name timestamp]
    [writer
        [script
            """
            context.write(new Date())
            """
        ]
    ]
]

yields the following error in PML 2.2.0 2021-12-14.

Running PMLC on the file "myfolder/Main.pml" ...
Error      The following error occurred when a script was executed for node 'timestamp':                              
           java.lang.ExceptionInInitializerError                                                                       
Error id   SCRIPTING_ERROR                                                                                             
-----------------------------------------------------------------------------------------------------------------------

THE FOLLOWING APPLICATION ERROR OCCURRED (2022-02-01T09:41:45.650332221):
Java throwable: org.graalvm.polyglot.PolyglotException: java.lang.ExceptionInInitializerError
See file 'myfolder/errors.log' for more information.

errors.log

Whitespace not collapsed when line break precedes node end

In version 1.5.0 some inline nodes don't collapse the end whitespace when written like this:

Here is a sentence (and "here is a quote"[sup
    [xref node_id="my_footnote_28" text="28"]
]), and here is the rest of the sentence.

resulting in an extra space before the end of the node:

... is a quote&quot;<sup class="pml-superscript"><a href="#my_footnote_28" class="pml-xref">28</a> </sup>), and here ...

Image source is relative to target directory, not source directory

The image tag help says this about its source attribute:

Description    : The relative file path to the image file. The path is relative to the target HTML file.
Examples       : source = images/ball.png

I get that source translates directly to href in the generated HTML anchor. However, I see a few problems here:

  1. User expectation. Since PML is a compiled language, a user who means his PML file /workspace/doc.pml to include an internal image /workspace/images/ball.png would naturally expect the source attribute to be relative to the source folder containing the PML file (or, less ideally, to the working directory where the converter is run), but certainly not to the target directory.
  2. Portability. With the path being relative to the target directory instead of the source directory, the PML code now has to be made aware of the location of the target directory, which otherwise should be defined only in the converter arguments, thereby making the PML code non-portable: The PML code effectively has to either know where the HTML file will be generated (e.g. source = "../../../workspace/images/ball.jpg") or else rely on hard-coded absolute paths (source = "/workspace/images/ball.jpg"), neither of which is practical when the developer decides to deploy his HTML to a server or move it to another machine.
  3. Completeness. With the converter expecting the image to already exist in the target directory, the image is effectively omitted from the build. This means that the image tag represents not an image but only an image reference, meaning any internal images must be deployed to the target outside the PML conversion process.

I propose it would be more helpful, in the case of internal images, for said images to be bundled by the converter into the output directory, along with the HTML file and CSS. Then the source attribute would be relative to the source directory instead of the target directory, a state that is much more in line with a common user's expectation of the proper usage of an image tag in a compiled language. The same rationale extends to the video and audio tags as well.

Of course, this solution concerns only the case of internal images, not the case of external image references. Supporting both cases would perhaps necessitate a new attribute.

Add Pre-Processing Option to PMLC

Please add a preprocessor option to pmlc so that it's possible to create a standalone source document from a project that uses [insert and [insert_code directives and multiple files.

Possibly, there should also be a way to control whether [const parameters should be expanded and replaced or whether they should be preserved in the pre-processed document generated via this option.

This option would come handy in various context, from someone wanting to release a document which is generated as part of a more complex toolchain, to the PML projects themselves, which could generate standalone sample docs and documentation files (for inclusion in releases, projects, etc.) without having to give up the power of [insert and [insert_code directives in their maintenance.

See also Ascidoctor's coalescer script (soon to become an official extension).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.