mike-lischke / vscode-antlr4

ANTLR4 language support for Visual Studio Code
http://www.soft-gems.net
MIT License
429 stars 60 forks source link

Cannot save railroad diagrams #179

Closed startibartfast closed 1 year ago

startibartfast commented 2 years ago

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

bertrandm commented 2 years ago

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

classicwuhao commented 2 years ago

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

Orgl9l commented 2 years ago

@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%0A)

classicwuhao commented 2 years ago

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

toongeorges commented 2 years ago

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.

mike-lischke commented 1 year ago

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