···172172 return resolvedFacets;
173173}
174174175175+export function getLinkUrlsFromText(text) {
176176+ if (!text) {
177177+ return [];
178178+ }
179179+ return getLinkFacetsFromText(text).map((facet) => facet.features[0].uri);
180180+}
181181+182182+// Removes the link matching `url` from the text when it sits at the very
183183+// start or end of the message (ignoring surrounding whitespace). Matching is
184184+// facet-based because a typed link without a scheme (e.g. "bsky.app/...")
185185+// produces a normalized facet uri that doesn't appear verbatim in the text.
186186+export function stripLeadingOrTrailingLink(text, url) {
187187+ const linkFacets = getLinkFacetsFromText(text).filter(
188188+ (facet) => facet.features[0].uri === url,
189189+ );
190190+ const totalBytes = getByteLength(text);
191191+ for (const facet of linkFacets) {
192192+ const before = sliceByByte(text, 0, facet.index.byteStart);
193193+ const after = sliceByByte(text, facet.index.byteEnd, totalBytes);
194194+ if (before.trim() === "") {
195195+ return after.trimStart();
196196+ }
197197+ if (after.trim() === "") {
198198+ return before.trimEnd();
199199+ }
200200+ }
201201+ return text;
202202+}
203203+175204export function getTagsFromFacets(facets) {
176205 return facets.filter(
177206 (facet) => facet.features[0].$type === "app.bsky.richtext.facet#tag",