Open KosRud opened 1 month ago
Brainstorming format for markdown file:
<leaflet-marker markerId="1569753">
population: 420
[details](/some/file.md)
# Districts
## Port
...
## Market
...
## Slums
...
</leaflet-marker>
<leaflet-marker markerId="1578552">
![image](/images/forest.png)
[details](/some/folder/welwood.md)
</leaflet-marker>
Markdown supports using HTML tags. All built-in HTML elements use one word definition, so name leaflet-marker
should be safe and future-proof. If the element leaflet-marker
is not defined, the preview will just ignore it. But it can still be parsed easily with regex.
Attribute name is markerId
to avoid clashing with id
attribute in HTML.
To keep everything in one file, JSON map definition can be stored inside frontmatter at the beginning of markdown file. VSCode seems to include frontmatter plugin by default:
In the preview I've confirmed that frontmatter is not displayed.
As a backup plan if frontmatter is not viable for some reason, one could put JSON inside a code block at the very beginning of the markdown file.
I'll look into how to implement these suggestions. The parsing shouldn't be too difficult, I had been working on unreleased integration with Dendron that can be adapted for that. Regarding Part 2: Thank you for the information, that is very useful for future consideration. It's something I wanted to implement, just didn't get around to yet. I think, I'll prefer having descriptions as separate files and use either links or ids to reference them.
Separate files was my first thought, but I see one potential problem with it: polluting the file picker (Ctrl + P
) and slowdown from things like updating links that have to go through all files in the workspace. To what extent it actually is a problem (if at all), I don't know.
I've stumbled upon a problem when trying to capture MarkdownIt instance by masquerading as a markdown extension: the initialization of markdown extensions happens when you first open a markdown file, not when the extension is activated.
As a workaround, I made the extension check if MarkdownIt instance is already captured. If it is not, produce an error with a button that forces MarkdownIt instance capture:
if (md == null) {
const option = await vscode.window.showErrorMessage(
`Error: MarkdownIt instance was not captured`,
'Force capture'
);
switch (option) {
case 'Force capture':
const mdCapturePromise = new Promise<void>((resolve) => {
mdCaptureCallback = resolve;
setTimeout(resolve, 3000);
});
await vscode.workspace
.openTextDocument({
content: `This is a dummy markdown document opened to force MardownIt initialization. This allows ${extensionNamePretty} to capture the MarkdownIt instance.`,
language: 'markdown',
})
.then(async (doc) => {
await vscode.window.showTextDocument(doc, {
preview: false,
viewColumn: vscode.ViewColumn.One,
});
await vscode.commands.executeCommand(
'workbench.action.revertAndCloseActiveEditor'
);
});
await mdCapturePromise;
if (md == null) {
await vscode.window.showErrorMessage(
'MarkdownIt instance capture failed'
);
return;
}
await vscode.window.showInformationMessage(
'MarkdownIt instance captured'
);
return;
default:
return;
}
}
export function activate(context: vscode.ExtensionContext) {
// init commands...
return {
extendMarkdownIt(markdownIt: any) {
md = markdownIt;
if (mdCaptureCallback) {
mdCaptureCallback();
}
return markdownIt;
},
};
}
However, a better solution might be to use command markdown.api.render
like mentioned here:
I'll look into it after the next update for marker icons is out, probably within the next two weeks.
Tried the command, this seems to work just fine:
const result = await vscode.commands.executeCommand<string>(
'markdown.api.render',
'# Test render'
);
Note: if tokens are needed (md.parse
instead of md.render
), command will not help.
Firstly, thanks for this awesome extension.
I have the following suggestion:
Part 1
Marker description can render markdown parsed by built-in markdown-it instance from vscode. To capture the built-in parser instance, your extension can masquerade as markdown extension, but instead of injecting a plugin it just saves the provided parser instance to a variable for later use.
Part 2
The second part might be a bit controversial and "ugly" from architectural standpoint, but it provides a great benefit (IMHO) which would be (comparably) difficult to achieve otherwise.
Instead of storing descriptions inside json file, they are stored externally as
.md
files. For example: each marker has a unique id, and an.md
file with the name matching its id will contain corresponding description.Why? Because vscode has a built-in setting for updating links in
.md
files when target file is moved or renamed:markdown.updateLinksOnFileMove.enabled
. If you don't feel like re-implementing it, existing code can be leveraged by putting descriptions into.md
files so vscode will take care of it.This is how VSCode finds links in markdown files: link.
Single markdown file
Alternatively, all descriptions can be stored within a single markdown file:
In these examples
1569753
and1578552
are marker ids (followed by names). Note that I usedh1
headings to define anchors: this is not ideal (such text could be contained within marker description as valid markdown) but from the top of my head I don't see a good solution that is guaranteed to never clash with valid markdown.