From a0a25d64f1e63a896564c1f615383b43714de76b Mon Sep 17 00:00:00 2001
From: Harvey Tindall
Date: Fri, 26 Mar 2021 23:13:19 +0000
Subject: [PATCH] rewrite stripmd, fix some typos
doesn't work any better, but more efficient and doesn't require
eyebleach after viewing.
---
README.md | 4 +--
stripmd.go | 69 ++++++++++++++++++-----------------------
ts/modules/stripmd.ts | 71 +++++++++++++++++++------------------------
3 files changed, 63 insertions(+), 81 deletions(-)
diff --git a/README.md b/README.md
index 0900fed..fd2c53e 100644
--- a/README.md
+++ b/README.md
@@ -16,12 +16,12 @@ I chose to rewrite the python [jellyfin-accounts](https://github.com/hrfee/jelly
* Granular control over invites: Validity period as well as number of uses can be specified.
* Account profiles: Assign settings profiles to invites so new users have your predefined permissions, homescreen layout, etc. applied to their account on creation.
* Password validation: Ensure users choose a strong password.
-* ⌛ User expiry: Specify a validity period, and new user's accounts will be disabled/deleted after it. The period can be manually extended too.
+* ⌛ User expiry: Specify a validity period, and new users accounts will be disabled/deleted after it. The period can be manually extended too.
* 🔗 Ombi Integration: Automatically creates Ombi accounts for new users using their email address and login details, and your own defined set of permissions.
* Account management: Apply settings to your users individually or en masse, and delete users, optionally sending them an email notification with a reason.
* 📨 Email storage: Add your existing users email addresses through the UI, and jfa-go will ask new users for them on account creation.
* Email addresses can optionally be used instead of usernames
-* 🔑 Password resets: When user's forget their passwords and request a change in Jellyfin, jfa-go reads the PIN from the created file and sends it straight to the user via email.
+* 🔑 Password resets: When users forget their passwords and request a change in Jellyfin, jfa-go reads the PIN from the created file and sends it straight to the user via email.
* Notifications: Get notified when someone creates an account, or an invite expires.
* 📣 Announcements: Bulk email your users with announcements about your server.
* Authentication via Jellyfin: Instead of using separate credentials for jfa-go and Jellyfin, jfa-go can use it as the authentication provider.
diff --git a/stripmd.go b/stripmd.go
index 7ea2266..0568067 100644
--- a/stripmd.go
+++ b/stripmd.go
@@ -6,50 +6,41 @@ import (
stripmd "github.com/writeas/go-strip-markdown"
)
-func stripMarkdown(md string) string {
- // Search for markdown-formatted urls, and replace them with just the url, then use a library to strip any traces of markdown. You'll need some eyebleach after this.
- foundOpenSquare := false
- openSquare := -1
- openBracket := -1
- closeBracket := -1
- openSquares := []int{}
- closeBrackets := []int{}
- links := []string{}
- foundOpen := false
- for i, c := range md {
- if !foundOpenSquare && !foundOpen && c != '[' && c != ']' {
+// StripAltText removes Markdown alt text from links and images and replaces them with just the URL.
+// Currently uses the deepest alt text when links/images are nested.
+func StripAltText(md string) string {
+ altTextStart := -1 // Start of alt text (between '[' & ']')
+ URLStart := -1 // Start of url (between '(' & ')')
+ URLEnd := -1
+ previousURLEnd := -2
+ out := ""
+ for i := range md {
+ if altTextStart != -1 && URLStart != -1 && md[i] == ')' {
+ URLEnd = i - 1
+ out += md[previousURLEnd+2:altTextStart-1] + md[URLStart:URLEnd+1]
+ previousURLEnd = URLEnd
+ altTextStart, URLStart, URLEnd = -1, -1, -1
continue
}
- if c == '[' && md[i-1] != '!' {
- foundOpenSquare = true
- openSquare = i
- } else if c == ']' {
- if md[i+1] == '(' {
- foundOpenSquare = false
- foundOpen = true
- openBracket = i + 1
- continue
+ if md[i] == '[' && altTextStart == -1 {
+ altTextStart = i + 1
+ if i > 0 && md[i-1] == '!' {
+ altTextStart--
}
- } else if c == ')' {
- closeBracket = i
- openSquares = append(openSquares, openSquare)
- closeBrackets = append(closeBrackets, closeBracket)
- links = append(links, md[openBracket+1:closeBracket])
- openBracket = -1
- closeBracket = -1
- openSquare = -1
- foundOpenSquare = false
- foundOpen = false
+ }
+ if i > 0 && md[i-1] == ']' && md[i] == '(' && URLStart == -1 {
+ URLStart = i + 1
}
}
- fullLinks := make([]string, len(openSquares))
- for i := range openSquares {
- if openSquares[i] != -1 && closeBrackets[i] != -1 {
- fullLinks[i] = md[openSquares[i] : closeBrackets[i]+1]
- }
+ if previousURLEnd+1 != len(md)-1 {
+ out += md[previousURLEnd+2:]
}
- for i, _ := range openSquares {
- md = strings.Replace(md, fullLinks[i], links[i], 1)
+ if out == "" {
+ return md
}
- return strings.TrimPrefix(strings.TrimSuffix(stripmd.Strip(md), "
"), "")
+ return out
+}
+
+func stripMarkdown(md string) string {
+ return strings.TrimPrefix(strings.TrimSuffix(stripmd.Strip(StripAltText(md)), "
"), "")
}
diff --git a/ts/modules/stripmd.ts b/ts/modules/stripmd.ts
index cc184cf..39381ab 100644
--- a/ts/modules/stripmd.ts
+++ b/ts/modules/stripmd.ts
@@ -1,49 +1,40 @@
const removeMd = require("remove-markdown");
-export function stripMarkdown(md: string): string {
- let foundOpenSquare = false;
- let openSquare = -1;
- let openBracket = -1;
- let closeBracket = -1;
- let openSquares: number[] = [];
- let closeBrackets: number[] = [];
- let links: string[] = [];
- let foundOpen = false;
+function stripAltText(md: string): string {
+ let altStart = -1; // Start of alt text (between '[' & ']')
+ let urlStart = -1; // Start of url (between '(' & ')')
+ let urlEnd = -1;
+ let prevURLEnd = -2;
+ let out = "";
for (let i = 0; i < md.length; i++) {
- const c = md.charAt(i);
- if (!foundOpenSquare && !foundOpen && c != '[' && c != ']') {
+ if (altStart != -1 && urlStart != -1 && md.charAt(i) == ')') {
+ urlEnd = i - 1;
+ out += md.substring(prevURLEnd+2, altStart-1) + md.substring(urlStart, urlEnd+1);
+ prevURLEnd = urlEnd;
+ altStart = -1;
+ urlStart = -1;
+ urlEnd = -1;
continue;
}
- if (c == '[' && md.charAt(i-1) != '!') {
- foundOpenSquare = true;
- openSquare = i;
- } else if (c == ']') {
- if (md.charAt(i+1) == '(') {
- foundOpenSquare = false;
- foundOpen = true;
- openBracket = i + 1;
- continue;
+ if (md.charAt(i) == '[' && altStart == -1) {
+ altStart = i + 1
+ if (i > 0 && md.charAt(i-1) == '!') {
+ altStart--
}
- } else if (c == ')') {
- closeBracket = i;
- openSquares.push(openSquare);
- closeBrackets.push(closeBracket);
- links.push(md.slice(openBracket+1, closeBracket))
- openBracket = -1;
- closeBracket = -1;
- openSquare = -1;
- foundOpenSquare = false;
- foundOpen = false;
+ }
+ if (i > 0 && md.charAt(i-1) == ']' && md.charAt(i) == '(' && urlStart == -1) {
+ urlStart = i + 1
}
}
- let fullLinks: string[] = new Array(openSquares.length);
- for (let i = 0; i < openSquares.length; i++) {
- if (openSquares[i] != -1 && closeBrackets[i] != -1) {
- fullLinks[i] = md.slice(openSquares[i], closeBrackets[i]+1)
- }
- }
- for (let i = 0; i < openSquares.length; i++) {
- md = md.replace(fullLinks[i], links[i]);
- }
- return removeMd(md);
+ if (prevURLEnd + 1 != md.length - 1) {
+ out += md.substring(prevURLEnd+2)
+ }
+ if (out == "") {
+ return md
+ }
+ return out
+}
+
+export function stripMarkdown(md: string): string {
+ return removeMd(stripAltText(md));
}