vscode-antlr4 icon indicating copy to clipboard operation
vscode-antlr4 copied to clipboard

Cannot save railroad diagrams

Open startibartfast opened this issue 2 years ago • 4 comments

When I click the 'Save to PNG' button, for single rule, or 'Save to HTML' button for all rules diagram, nothing happens.

startibartfast avatar Jun 22 '22 07:06 startibartfast

Experiencing the self-same issue. Want to use this feature to document system, but cannot. Would appreciate any workaround if possible.

bertrandm avatar Jul 24 '22 19:07 bertrandm

The same problem here, any advice? I also want to document grammar for our project.

classicwuhao avatar Sep 03 '22 14:09 classicwuhao

@classicwuhao I found an alternative for creating railroad diagrams, downside is that you have to make them by hand, depending upon complexity of your grammar this may or may not work for you. After a while I got good at it, and I was able to cut and paste the SVG into my documents, and it works wonderfully, also could style it with css. Railroad Diagram Generator

Orgl9l avatar Sep 03 '22 17:09 Orgl9l

@Orgl9l Thanks, I will try, I have 500+ lines of grammar... GG.

classicwuhao avatar Sep 03 '22 17:09 classicwuhao

Here is a work around (probably not the best one, but it does the job):

First locate where the VSCode extension is installed, typically under something like ${USER_HOME}/.vscode/extensions/mike-lischke.vscode-antlr4-2.3.0. Let the value of ${ROOT} be this directory.

The files you want to change are under the directory ${ROOT}/out/src/frontend/webviews/. To get the railroad diagram for a single rule, you can change the file ${ROOT}/out/src/frontend/webviews/RailroadDiagramProvider.js as follows:

Also look for the style of the SVG file, which you would find under ${ROOT}/misc/light.css or ${ROOT}/misc/dark.css

Change

        diagram += `
            <div class="header">
                <span class="rrd-color">
                    <span class="graph-initial">Ⓡ</span>ule&nbsp;&nbsp;
                </span>
                    &nbsp;&nbsp;${this.currentRule} <span class="rule-index">(rule index: ${this.currentRuleIndex})
                </span>
                <span class="action-box">
                    Save to SVG
                    <a onClick="exportToSVG('rrd', '${this.currentRule}');">
                        <span class="rrd-save-image" />
                    </a>
                </span>
            </div>
            <div id="container">
                <script>${this.backend.getRRDScript(fileName, this.currentRule)}</script>
            </div>
        `;

to

        //this is the style for the light theme,
        //modify or copy the values of the dark theme if you want this to be different
        const style = `
<style>
svg.railroad-diagram path {
    /* The connection lines. */
    stroke-width: 2;
    stroke: darkgray;
    fill: rgba(0, 0, 0, 0);
}

svg.railroad-diagram text {
    /* All text except comments. */
    font: bold 12px Hack, "Source Code Pro", monospace;
    text-anchor: middle;
    fill: #404040;
    /* Use fill instead of color for svg text. */
}

svg.railroad-diagram text.comment {
    /* Comment text */
    font: italic 10px Hack, "Source Code Pro", monospace;
    fill: #404040;
}

svg.railroad-diagram g.non-terminal rect {
    /* The non-terminal boxes. */
    stroke-width: 2;
    stroke: #404040;
    fill: rgba(255, 255, 255, 1);
}

svg.railroad-diagram g.terminal rect {
    /* The terminal boxes. */
    stroke-width: 2;
    stroke: #404040;
    fill: rgba(0, 0, 0, 0.1);
}

svg.railroad-diagram text.diagram-text {
    /* Multiple choice text, not working atm. */
    font-size: 12px Hack, "Source Code Pro", monospace;
    fill: red;
}

svg.railroad-diagram path.diagram-text {
    /* Multiple choice text, not working atm. */
    stroke-width: 1;
    stroke: red;
    fill: red;
    cursor: help;
}

svg.railroad-diagram g.diagram-text:hover path.diagram-text {
    /* Multiple choice text, not working atm. */
    fill: #f00;
}
</style>
`.replaceAll('\n', '')
 .replaceAll('&', '&amp;')
 .replaceAll('<', '&lt;')
 .replaceAll('>', '&gt;')
 .replaceAll('"', '&quot;')
 .replaceAll("'", '&#039;');
        diagram += `
            <div class="header">
                <span class="rrd-color">
                    <span class="graph-initial">Ⓡ</span>ule&nbsp;&nbsp;
                </span>
                    &nbsp;&nbsp;${this.currentRule} <span class="rule-index">(rule index: ${this.currentRuleIndex})
                </span>
                <span class="action-box">
                    Save to SVG
                    <a onClick="exportToSVG('rrd', '${this.currentRule}');">
                        <span class="rrd-save-image" />
                    </a>
                </span>
            </div>
            <div>
              <button onclick="readSVG()">show SVG</button>
            </div>
            <div>
              <pre id="content">
              </pre>
            </div>
            <script>
              function readSVG() {
                const source = document.getElementById('container').getElementsByTagName('svg')[0];
                const destination = document.getElementById('content');
                const unstyled = source.outerHTML
                                       .replaceAll('&', '&amp;')
                                       .replaceAll('<', '&lt;')
                                       .replaceAll('>', '&gt;')
                                       .replaceAll('"', '&quot;')
                                       .replaceAll("'", '&#039;');
                const styleIndex = unstyled.indexOf('&gt;') + '&gt;'.length;
                const styled = unstyled.slice(0, styleIndex) + '${style}' + unstyled.slice(styleIndex);
                destination.innerHTML = styled;
              }
            </script>
            <div id="container">
                <script>${this.backend.getRRDScript(fileName, this.currentRule)}</script>
            </div>
        `;

You will now have a button in the user interface that you can click to print the SVG as text in the window. You can copy this text to a new SVG file.

This SVG file will look like the railroad diagram shown in VSCode if shown in a browser. However the SVG file will not be correctly displayed in all applications (e.g. Inkscape or LibreOffice), because these applications are not processing the CSS styles as intended. In my case I ended up opening the SVG files in an application that renders them as intended, then exporting these SVG files to the PNG format and then using the PNG files in LibreOffice.

toongeorges avatar Oct 17 '22 20:10 toongeorges

A new release (2.4.0) was just published, with a much improved RRD handling.

mike-lischke avatar Oct 01 '23 17:10 mike-lischke