Regex lookbehind na Safari

0

Mam sobie taki edytorek, do którego dodałem linkowanie. Potem przerabiam go na web component, który pod spodem jest komponentem Vue.

Muszę z linka wydobyć atrybuty, żeby przekazać do komponentu, więc zrobiłem to regexem:

const href = link.match(/(?<=href=").+?(?=")/g)
const title = link.match(/(?<=title=").+?(?=")/g)
const content = link.match(/(?<=>).+?(?=<\/a>)/g)
const webComponent = `<web-component-base-link to="${href}" title="${title}">${content}</web-component-base-link>`

Wszystko spoko, ale oczywiście okazało się, że na IE naszych czasów tj. Srafari lookbehind nie jest wspierany https://caniuse.com/js-regexp-lookbehind

Czy da się jakoś inaczej regexem wyciągnąć te atrybuty?
Proszę o pomoc i serdecznie dziękuję.

1

Ja zawsze stosuję /href="([^"]+)"/

1

A do zawartości:
<a[^>]*>([^<]+)<\/a>

Tak szczerze to sprawdza mi się do tej pory w 100% przypadków. Gdyby się nie sprawdziło gdzieś to albo pisałbym hacki pod tę jedną stronę, na której się nie sprawdza, albo po prostu użyłbym parsera, a nie regexpa, bo chyba wiesz, że regexp nie powinien być wykorzystywany do HTMLa? ;)

0

@dzek69: Spoko, tylko tutaj łapie to co chcę jako grupę:

screenshot-20221121103351.png

Przy lookbehind matchuje mi tylko wartość atrybutu i różnica jest bardzo niewielka albo nawet żadna, ale właśnie mi chodzi o to, czy są jakieś inne patenty, żeby np. wyciąć kilka znaków początkowych lub końcowych z tego, co regex dopasował. Tak teoretycznie, bo się słabo znam.

Co do drugiej odpowiedzi, to ostatnio przysiadłem nad regexami i ćwiczyłem, żeby poogarniać zasadę działania. Czyli powinienem np. użyć DOMParsera, potem wyciągnąć z DOM ten element i wziąć atrybuty? To z regexami gdzieś na blogu jakimś znalazłem i na SO takie rozwiązania też proponowali w podobnych przypadkach. Dlaczego nie powinien być wykorzystywany do HTMLa?

Teraz sprawdziłem i pewnie dlatego zrobiłem to regexem, bo ja to potrzebuję po stronie SSR, a DOMParser is not defined. Są biblioteki do tego, ale staram się dbać o małego bundla.

1

Zawsze można pokombinować inaczej, zrobić "postprocessing" danych z regexpów, aniżeli rozbudowywać te magiczne regexpowe znaczki do zrobienia czegoś, do czego nie bardzo są przystosowane.
Jeżeli używasz flagi g (pominąłem to wcześniej), to pomocne będzie matchAll - Safari o dziwo to wspiera 🎉:

Array.from(`<a href="hello">bla bla</a><div>jakiś content<a href="world">ble ble</a></div>`.matchAll(/href="([^"]+)"/g)).map(x => x[1])
(2) ['hello', 'world']

Dlaczego regexpy nie do HTML: https://stackoverflow.com/questions/6751105/why-its-not-possible-to-use-regex-to-parse-html-xml-a-formal-explanation-in-la

A do parsowania po stronie serwera masz cheerio :) choć nie zdziwiłbym się, gdyby ktoś zrobił polyfilla (być może jako wrapper do cheerio) do DOMParser (z tego ostatniego nigdy nie korzystałem tak szczerze)

0

@dzek69: Dzięki. Ogólnie też dodam, że ja tym regexem sprawdzałem tylko stringi z pojedynczym tagiem a np. <a href="/produkty/termostaty" title="Termostaty" class="link link-web-component no-underline">nim sterować</a>, więc mimo wszystko chyba można by regexem to wyciągać? Wiadomo, że jakbym cały dokument sprawdzał, to mogłyby pojawić się problemy, ale no faktycznie nie napisałem o tym w pierwszym poście.

1

Regexp będzie lżejszy i szybszy, po prostu nie zawsze skuteczny. Jeżeli powyższe rozwiązanie Ci działa to jak najbardziej śmiało używaj :)

A jeżeli masz pojedynczy tag w testowanym stringu to nie potrzebujesz matchAll ani flagi g:

const href = link.match(/href="([^"]+)"/)[1];

Powyższe co prawda wysypie się, gdy match zwróci null, więc albo link.match(/href="([^"]+)"/)?.[1] jeżeli Twoje środowisko to wspiera, albo jakiś if albo try/catch - co ci tam pasuje, myślę, że już ogarniesz.

1 użytkowników online, w tym zalogowanych: 0, gości: 1