aswinkumar863 / smarty-vscode-support

Smarty template support extension for Visual Studio Code
https://marketplace.visualstudio.com/items?itemName=aswinkumar863.smarty-template-support
MIT License
110 stars 11 forks source link

Navigation breaks with multiple ".tpl"s #479

Open nurullahakin opened 4 weeks ago

nurullahakin commented 4 weeks ago

If I use multiple .tpl in the include syntax, the created link to the included file isn't correct.

I suspect the extracted path from the syntax uses a greedy pattern matching, that is, it's looking for the last occurrence of the .tpl. However, this is wrong. Examine the following case:

{include file="dashboard.tpl" icon="svg/products.tpl"}

1

2

One should be able to pass a template path as a variable/value. However, this conflicts with the current behavior.

It'd be nice if it could just ignore other .tpls. It'd be great if it could create multiple "follow" links in one include syntax.


I'm not familiar with developing VSCode extensions, however, I don't want to wait till this gets solved/implemented. If there's a quick way for me to do some modification in the extension files and get it working, that would be great.

nurullahakin commented 4 weeks ago

I took a quick look around, and found the file client/src/language/documentLink.ts. I suspect it handles the document links in the file. I'll tinker when I have the time.

nurullahakin commented 4 weeks ago

Did some tinkering with the regex pattern, and it seems the problem lies there. It is greedy.

Using [^\s'"] instead of . solves the problem. Also + instead of *, because ".tpl" isn't a valid link.

const linkPattern = /(?<=['"]).*\.tpl(?=['"])/g;       // original
const linkPattern = /(?<=['"])[^\s'"]+\.tpl(?=['"])/g; // new
const linkPattern = /(?<=['"])   .   *\.tpl(?=['"])/g; // original
const linkPattern = /(?<=['"])[^\s'"]+\.tpl(?=['"])/g; // new

Some tests:

const linkPattern = /(?<=['"])[^\s'"]+\.tpl(?=['"])/g;

const testCases = [
    {
        input: `{include file="dashboard.tpl"}`,
        expected: ["dashboard.tpl"]
    },
    {
        input: `{include file='dashboard.tpl'}`,
        expected: ["dashboard.tpl"]
    },
    {
        input: `{include file="dashboard.tpl" icon="svg/products.tpl"}`,
        expected: ["dashboard.tpl", "svg/products.tpl"]
    },
    {
        input: `{include file="main.tpl" icon='icons/menu.tpl' footer="footer.tpl"}`,
        expected: ["main.tpl", "icons/menu.tpl", "footer.tpl"]
    },
    {
        input: `{include file="partials/header.tpl"}`,
        expected: ["partials/header.tpl"]
    },
    {
        input: `{include file="not_a_template.txt"}`,
        expected: null
    }
];

console.clear();
testCases.forEach(({input, expected}, index) => {
    const matches = input.match(linkPattern);
    const isCorrect = JSON.stringify(matches) === JSON.stringify(expected);
    if (isCorrect) {
        console.log(`Test ${index + 1} passed`);
    } else {
        console.error(`Test ${index + 1} failed`);
    }
    if (!isCorrect) {
        console.warn(`Input: ${input}`);
        console.warn(`Expected: ${expected}, but got: ${matches}`);
    }
});

Also did some tests directly on the extension files, and this seems to work. The paths are correct, and both are clickable.

Screenshot 2024-11-07 103820

Modified the regex patterns in the following files: