kemayo / obsidian-smart-links

MIT License
26 stars 4 forks source link

Does not recognize # #2

Closed czhad closed 1 year ago

czhad commented 1 year ago

Hi,

I tried the following setting:

look for: (TTS|[Tt]icket|#) {0,1}(\d+)
replace with: https://our.tts.com/tts/Ticket/Display.html?id=$2

It works as intended for TTS12345 or ticket 12345, but it fails for #12345. I suppose it somehow conflicts with Obsidian tags?

Thanks for looking into it.

berot3 commented 1 year ago

same for me. It does not create a link when # is used.

test1 works:

test2 fails:

kemayo commented 1 year ago

Amusingly, the specific issue here isn't anything to do with Obsidian's tags, because those don't trigger on a pure hash-followed-by-numbers string. Rather, this is because I build a pattern from your input and prepend \b to it so it only runs after a word-break (because otherwise patterns like t \d+ would trigger on things like "culvert 12"). Unfortunately, immediately preceding a hash isn't a word-break because a hash isn't in \w. You'll note that if you write a pattern like T#\d+ it'll work.

I think the right solution here is probably for me to abandon \b and construct a horrific abomination of a regex that uses lookbehinds to expand what I'm considering as valid to run after.

(That said, it'll still easily get mixed up if you wrote a pattern that did expect to run on a hash followed by anything but numbers. The way I have this set up is to use registerMarkdownPostProcessor and then check for direct text-node children of any p or li tags in the read-view markup. I'm not actually sure if Obsidian's own markdown transform runs as a postprocessor or is a more fundamental action, but either way it happens before my check does.)

czhad commented 1 year ago

Hi, thanks for the explanation. I wonder if an easier (and perhaps more reliable) solution to this would be to define your own \b substitution that actually only checks for white space or line beginning before the user-defined search pattern. Something like ( |\t|^) instead of \b.

czhad commented 1 year ago

Or rather ( |\t|\b|^)

kemayo commented 1 year ago

The main reason to go with a more complex lookback approach than that is avoiding needing to substitute the initial character as part of my replacement -- which would complicate letting people specify their own replacement patterns (since I'd be silently using $1). I could do it in a two-step manner, I guess -- match with that sort of group, then do the replacement as a second pass. It feels more prone to fragility, though.

kemayo commented 1 year ago

Okay, I've released version 1.0.1 which contains my fix for this.

czhad commented 1 year ago

It works perfectly on my desktop now, thank you. It doesn't seem to work at all on mobile (iOS), though.

kemayo commented 1 year ago

Interesting. It worked before I made that change, so I'm speculating that there's some difference in either the generated markup on iOS or the details of the regular expression engine. I'll need to go see what the tools are for debugging something like this in Obsidian on iOS -- I'll try to get back and fix it tomorrow.

kemayo commented 1 year ago

Okay! Turns out that WebKit doesn't (quite yet) support lookbehind in regular expressions. I've adjusted this to include a manual lookbehind step, which make it all work on iOS again.

kemayo commented 1 year ago

1.0.2 is released containing this fix.

czhad commented 1 year ago

Perfect. Works like a charm on both my Mac and iOS. Thanks a lot.