-
Notifications
You must be signed in to change notification settings - Fork 2.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add "Mermaid Fixer" plugin #2061
Conversation
buttonIconEl.innerHTML = BUTTON_ICON; Can you explain more as to how your plugin fixes these issues? |
“You should use the
|
The requested changes have been done. There is no more (And I updated the |
@joethei Remember that setIcon is also just an innerHTML. @Bunker-D I am looking at your CSS styles and seeing if there's any of them we can integrate. I couldn't find some of them (or at least, where the go) in testing. I wrote some comments between the lines: /* This seems to fix a #fff? If that's the case I can fix easily */
.mermaid [aria-roledescription="sequence"] .sequenceNumber {
fill:var(--background-primary)!important;
}
/* This was set to background-modifier-border before, right? If that's the case I can fix easily */
.mermaid [aria-roledescription="classDiagram"] .relation {
stroke:var(--text-normal)!important;
}
/* Couldn't find this rule anywhere */
.mermaid [aria-roledescription="er"] path.er {
stroke:var(--text-muted)!important;
}
/* Why is this #000 */
.mermaid [aria-roledescription="journey"] .label {
color:#000!important;
}
/* Couldn't find this rule anywhere */
.mermaid [aria-roledescription="requirement"] path.er{
stroke:var(--text-normal)!important;
}
/* I can fix both here */
.mermaid [aria-roledescription="requirement"] .reqBox{
fill:var(--background-primary-alt)!important;
stroke:var(--text-muted)!important
}
/* I can fix the color here, but what is the stroke for? */
.mermaid [aria-roledescription="requirement"] .reqLabelBox{
fill:var(--background-secondary)!important;
stroke:none!important
}
/* I can fix */
.mermaid [aria-roledescription="requirement"] .req-title-line{
stroke:var(--text-muted)!important
}
/* I can fix */
.mermaid [aria-roledescription="requirement"] .relationshipLabel{
fill:var(--text-normal)!important
} |
Just to add, for the arrow thing, @Bunker-D you should send a patch to mermaid upstream. |
/* This seems to fix a #fff? If that's the case I can fix easily */
.mermaid [aria-roledescription="sequence"] .sequenceNumber {
fill:var(--background-primary)!important;
} → Yes. It gives the text color for the sequence numbers in sequence diagrams. It avoids having white on almost-white. (You can see the effect the Readme.) Note that the /* This was set to background-modifier-border before, right? If that's the case I can fix easily */
.mermaid [aria-roledescription="classDiagram"] .relation {
stroke:var(--text-normal)!important;
} → The SVG Note that in the case of my plugin, the markers' style is fixed in the markers I insert (with the /* Couldn't find this rule anywhere */
.mermaid [aria-roledescription="er"] path.er {
stroke:var(--text-muted)!important;
} → It fixes the color of the links between boxes. It is affected by /* Why is this #000 */
.mermaid [aria-roledescription="journey"] .label {
color:#000!important;
} → User journeys uses big yellowish boxes and smileys. One possibility is to either keep that and fix a fitting text color, the other is to set theme-dependent backgrounds and text colors. I chose the former. (And I typically do the latter with requirement diagrams.) /* I can fix the color here, but what is the stroke for? */
.mermaid [aria-roledescription="requirement"] .reqLabelBox{
fill:var(--background-secondary)!important;
stroke:none!important
} → The boxes ( (On the contrary, there's the same issue with the main boxes. But in this case, I feel like the border are quite more important for the diagram legibility.) |
Do you happen to have example mermaid diagrams I can test with for each of the cases? |
@joethei What I am proposing here cannot be included into Mermaid:
I might propose some solution to solve the issue on Mermaid side, but it would be a totally different solution (to ensure unique ID), and I would have to dig into their code to not forget anything. My issue is that it could break something for other users: changing the ID (to ensure unique IDs) might affect some styling. It could be implemented as something optional, but then it would affect most current uses of Mermaid. So yes, updating Mermaid. But I can't right now and it might not be so easy. |
@lishid You can use the notes in the For each note, going Edit view → Read view as the effect of triggering the arrow-disappearing bug. (I explain why in the dev readme.) |
@lishid If you can and want to modify Obsidian's code, maybe you could just add some code so that every time Mermaid is called to create an SVG, you make the IDs inside unique. (Although I would understand if you prefer to wait to have this done on Mermaid's side.) This would work: function makeMarkerIdsUnique( svg: Element ): void {
( new MermaidCleaner( svg ) ).makeAllMarkerIdsUnique();
}
class MermaidCleaner {
private element: Element;
private id: string;
private style: Element;
constructor( svg: Element ) {
this.element = svg;
this.id = svg.id;
this.style = svg.getElementsByTagName( 'style' )[ 0 ];
}
makeAllMarkerIdsUnique() {
for ( const marker of this.element.getElementsByTagName( 'marker' ) ) {
this.makeMarkerIdUnique( marker );
}
}
makeMarkerIdUnique( markerEl: Element ) {
const oldMarkerId = markerEl.id;
if ( !oldMarkerId ) return;
const newMarkerId = this.makeNewId( oldMarkerId );
markerEl.id = newMarkerId;
this.updateMarkerCalls( oldMarkerId, newMarkerId );
this.updateMarkerStyle( oldMarkerId, newMarkerId );
}
makeNewId( oldId: string ): string {
// We use the diagram id — if any — as a suffix
if ( this.id ) {
return `${ oldId }-${ this.id }`;
}
// Else we use a random string at least 3 characters long
// (Using a random suffix in any case minimises the risk of conflicts with other unprocessed id of any origin.)
let id = oldId + '-';
let length = 3;
while ( length-- || document.getElementById( id ) ) {
id += String.fromCharCode( 97 + Math.floor( 26 * Math.random() ) );
}
return id;
}
updateMarkerCalls( oldMarkerId: string, newMarkerId: string ): void {
for ( const attribute of [ 'marker-start', 'marker-end' ] ) {
for ( const el of [ ...this.element.querySelectorAll( `[${ attribute }="url(#${ oldMarkerId })"]` ) ] ) {
el.setAttr( attribute, `url(#${ newMarkerId })` );
}
}
}
updateMarkerStyle( oldMarkerId: string, newMarkerId: string ): void {
if ( !this.style ) return;
const re = new RegExp( `#${ oldMarkerId }(?!\\w|-)`, 'g' );
this.style.innerHTML = this.style.innerHTML.replace( re, '#' + newMarkerId );
}
} With that, you just have to use (I tested it works with a draft plugin applying the function to every element of Note that obviously it just takes care of the ID issue, not the styling issues. |
By the way, just ask if you want help so that all styling issues are covered through CSS, including those solved by the way I defined my markers. Typically, my plugin doesn't have to fix |
I am aware of the missing IDs for the markers; I've just been waiting for someone to submit a patch upstream to fix it properly 🤣 |
Yeah. But Mermaid's code being as it is, I'm not sure I can code and commit a fix that wouldn't break anything in a timely manner. Plus, as it would change the ID, it could break somebody's use of Mermaid. So it might been argued that it would have to be a major release (while it fixes an issue visible only with some applications). That's why I'm proposing a solution to fix Mermaid's result. |
Ok I have implemented all of the style fixes, as well as a refactored version of your marker fix. Will credit you in the next release notes for the help with these! |
I am submitting a new Community Plugin
Repo URL
Link to my plugin: https://github.com/Bunker-D/obsidian-mermaid-fixer
Release Checklist
main.js
manifest.json
styles.css
(optional)v
)id
in mymanifest.json
matches theid
in thecommunity-plugins.json
file.I have given proper attribution to these other projects in my
README.md
.💡 The plugin does use
innerHTML
, but only with literal strings (defined by the plugin itself), thereby avoiding security issues. This choice is justified by the fact that it significantly facilitate the plugin maintenance, while modifications to Mermaid might require to update the plugin to mirror said modifications.