diff --git a/internal/api/entry.go b/internal/api/entry.go
index 6a299a01e58..d2f9c7426df 100644
--- a/internal/api/entry.go
+++ b/internal/api/entry.go
@@ -335,7 +335,13 @@ func (h *handler) fetchContent(w http.ResponseWriter, r *http.Request) {
return
}
- json.OK(w, r, map[string]string{"content": entry.Content})
+ if request.QueryBoolParam(r, "save", false) {
+ if err := h.store.UpdateEntryTitleAndContent(entry); err != nil {
+ json.ServerError(w, r, err)
+ }
+ }
+
+ json.OK(w, r, map[string]string{"content": entry.Content, "web_content": entry.WebContent})
}
func (h *handler) flushHistory(w http.ResponseWriter, r *http.Request) {
diff --git a/internal/database/migrations.go b/internal/database/migrations.go
index d40e5d2f813..b8ae43a8b12 100644
--- a/internal/database/migrations.go
+++ b/internal/database/migrations.go
@@ -882,4 +882,11 @@ var migrations = []func(tx *sql.Tx) error{
_, err = tx.Exec(sql)
return err
},
+ func(tx *sql.Tx) (err error) {
+ sql := `
+ ALTER TABLE entries ADD COLUMN web_content text default '';
+ `
+ _, err = tx.Exec(sql)
+ return err
+ },
}
diff --git a/internal/locale/translations/de_DE.json b/internal/locale/translations/de_DE.json
index cc60035a0eb..e49d7506a47 100644
--- a/internal/locale/translations/de_DE.json
+++ b/internal/locale/translations/de_DE.json
@@ -72,6 +72,8 @@
"entry.save.title": "Diesen Artikel speichern",
"entry.save.completed": "Erledigt!",
"entry.save.toast.completed": "Artikel gespeichert",
+ "entry.scraper.label.rss": "RSS-Inhalte anzeigen",
+ "entry.scraper.title.rss": "RSS-Inhalte abrufen",
"entry.scraper.label": "Herunterladen",
"entry.scraper.title": "Inhalt herunterladen",
"entry.scraper.completed": "Erledigt!",
diff --git a/internal/locale/translations/el_EL.json b/internal/locale/translations/el_EL.json
index 822821633db..5ff20e22667 100644
--- a/internal/locale/translations/el_EL.json
+++ b/internal/locale/translations/el_EL.json
@@ -72,6 +72,8 @@
"entry.save.title": "Αποθηκεύστε αυτό το άρθρο",
"entry.save.completed": "Έγινε!",
"entry.save.toast.completed": "Το άρθρο αποθηκεύτηκε",
+ "entry.scraper.label.rss": "Εμφάνιση περιεχομένου RSS",
+ "entry.scraper.title.rss": "Λήψη περιεχομένου RSS",
"entry.scraper.label": "Λήψη",
"entry.scraper.title": "Λήψη αρχικού περιεχομένου",
"entry.scraper.completed": "Έγινε!",
diff --git a/internal/locale/translations/en_US.json b/internal/locale/translations/en_US.json
index 97e58fe5a2b..b463d43388b 100644
--- a/internal/locale/translations/en_US.json
+++ b/internal/locale/translations/en_US.json
@@ -72,6 +72,8 @@
"entry.save.title": "Save this entry",
"entry.save.completed": "Done!",
"entry.save.toast.completed": "Entry saved",
+ "entry.scraper.label.rss": "Show RSS Content",
+ "entry.scraper.title.rss": "Fetch RSS content",
"entry.scraper.label": "Download",
"entry.scraper.title": "Fetch original content",
"entry.scraper.completed": "Done!",
diff --git a/internal/locale/translations/es_ES.json b/internal/locale/translations/es_ES.json
index 914d8994220..6e6c003d112 100644
--- a/internal/locale/translations/es_ES.json
+++ b/internal/locale/translations/es_ES.json
@@ -72,6 +72,8 @@
"entry.save.title": "Guardar este artículo",
"entry.save.completed": "¡Hecho!",
"entry.save.toast.completed": "Artículos guardados",
+ "entry.scraper.label.rss": "Mostrar contenido RSS",
+ "entry.scraper.title.rss": "Obtener contenido RSS",
"entry.scraper.label": "Descargar",
"entry.scraper.title": "Obtener contenido original",
"entry.scraper.completed": "¡Hecho!",
diff --git a/internal/locale/translations/fi_FI.json b/internal/locale/translations/fi_FI.json
index 41bd2e50d04..95337d8e674 100644
--- a/internal/locale/translations/fi_FI.json
+++ b/internal/locale/translations/fi_FI.json
@@ -72,6 +72,8 @@
"entry.save.title": "Tallenna tämä artikkeli",
"entry.save.completed": "Valmis!",
"entry.save.toast.completed": "Artikkeli tallennettu",
+ "entry.scraper.label.rss": "Näytä RSS-sisältö",
+ "entry.scraper.title.rss": "Hae RSS-sisältöä",
"entry.scraper.label": "Lataa",
"entry.scraper.title": "Nouda alkuperäinen sisältö",
"entry.scraper.completed": "Valmis!",
diff --git a/internal/locale/translations/fr_FR.json b/internal/locale/translations/fr_FR.json
index d616eb3eb3a..a8d7ceccda2 100644
--- a/internal/locale/translations/fr_FR.json
+++ b/internal/locale/translations/fr_FR.json
@@ -72,6 +72,8 @@
"entry.save.title": "Sauvegarder cet article",
"entry.save.completed": "Terminé !",
"entry.save.toast.completed": "Article sauvegardé",
+ "entry.scraper.label.rss": "Afficher le contenu RSS",
+ "entry.scraper.title.rss": "Obtenir le contenu RSS",
"entry.scraper.label": "Télécharger",
"entry.scraper.title": "Récupérer le contenu original",
"entry.scraper.completed": "Terminé !",
diff --git a/internal/locale/translations/hi_IN.json b/internal/locale/translations/hi_IN.json
index 199c66af1a6..de076e1c0ab 100644
--- a/internal/locale/translations/hi_IN.json
+++ b/internal/locale/translations/hi_IN.json
@@ -72,6 +72,8 @@
"entry.save.title": "एस लेख को सहेजे",
"entry.save.completed": "कार्य समाप्त हुआ!",
"entry.save.toast.completed": "लेख को सहेज लिया",
+ "entry.scraper.label.rss": "RSS सामग्री दिखाएँ",
+ "entry.scraper.title.rss": "RSS सामग्री प्राप्त करें",
"entry.scraper.label": "डाउनलोड",
"entry.scraper.title": "मूल विषयवस्तु लाए",
"entry.scraper.completed": "कार्य समाप्त हुआ!",
diff --git a/internal/locale/translations/id_ID.json b/internal/locale/translations/id_ID.json
index ee06ac61f34..b7cb54b31f1 100644
--- a/internal/locale/translations/id_ID.json
+++ b/internal/locale/translations/id_ID.json
@@ -72,6 +72,8 @@
"entry.save.title": "Simpan artikel ini",
"entry.save.completed": "Selesai!",
"entry.save.toast.completed": "Artikel tersimpan",
+ "entry.scraper.label.rss": "Tampilkan Konten RSS",
+ "entry.scraper.title.rss": "Dapatkan Konten RSS",
"entry.scraper.label": "Unduh",
"entry.scraper.title": "Ambil konten asli",
"entry.scraper.completed": "Selesai!",
diff --git a/internal/locale/translations/it_IT.json b/internal/locale/translations/it_IT.json
index 6e808a02053..4f0eee49b3c 100644
--- a/internal/locale/translations/it_IT.json
+++ b/internal/locale/translations/it_IT.json
@@ -72,6 +72,8 @@
"entry.save.title": "Salva questo articolo",
"entry.save.completed": "Fatto!",
"entry.save.toast.completed": "Articolo salvato",
+ "entry.scraper.label.rss": "Mostra contenuto RSS",
+ "entry.scraper.title.rss": "Ottieni contenuto RSS",
"entry.scraper.label": "Scarica",
"entry.scraper.title": "Scarica il contenuto integrale",
"entry.scraper.completed": "Fatto!",
diff --git a/internal/locale/translations/ja_JP.json b/internal/locale/translations/ja_JP.json
index 8c767b55162..bd6697101bf 100644
--- a/internal/locale/translations/ja_JP.json
+++ b/internal/locale/translations/ja_JP.json
@@ -72,6 +72,8 @@
"entry.save.title": "この記事を保存",
"entry.save.completed": "完了!",
"entry.save.toast.completed": "記事は保存されました",
+ "entry.scraper.label.rss": "RSS コンテンツを表示",
+ "entry.scraper.title.rss": "RSS コンテンツを取得",
"entry.scraper.label": "ダウンロード",
"entry.scraper.title": "オリジナルの内容を取得",
"entry.scraper.completed": "完了!",
diff --git a/internal/locale/translations/nl_NL.json b/internal/locale/translations/nl_NL.json
index d47510e9518..3a1e5fd61f2 100644
--- a/internal/locale/translations/nl_NL.json
+++ b/internal/locale/translations/nl_NL.json
@@ -72,6 +72,8 @@
"entry.save.title": "Artikel opslaan",
"entry.save.completed": "Done!",
"entry.save.toast.completed": "Artikel opgeslagen",
+ "entry.scraper.label.rss": "Toon RSS-content",
+ "entry.scraper.title.rss": "Haal RSS-content op",
"entry.scraper.label": "Downloaden",
"entry.scraper.title": "Fetch original content",
"entry.scraper.completed": "Klaar!",
diff --git a/internal/locale/translations/pl_PL.json b/internal/locale/translations/pl_PL.json
index 32f3e4f8ceb..de9c267b2fe 100644
--- a/internal/locale/translations/pl_PL.json
+++ b/internal/locale/translations/pl_PL.json
@@ -72,6 +72,8 @@
"entry.save.title": "Zapisz ten artykuł",
"entry.save.completed": "Gotowe!",
"entry.save.toast.completed": "Artykuł zapisany",
+ "entry.scraper.label.rss": "Pokaż treść RSS",
+ "entry.scraper.title.rss": "Pobierz treść RSS",
"entry.scraper.label": "Ściągnij",
"entry.scraper.title": "Pobierz oryginalną treść",
"entry.scraper.completed": "Gotowe!",
diff --git a/internal/locale/translations/pt_BR.json b/internal/locale/translations/pt_BR.json
index 56861a3a080..5c213d21146 100644
--- a/internal/locale/translations/pt_BR.json
+++ b/internal/locale/translations/pt_BR.json
@@ -72,6 +72,8 @@
"entry.save.title": "Salvar esse item",
"entry.save.completed": "Feito!",
"entry.save.toast.completed": "Item guardado",
+ "entry.scraper.label.rss": "Mostrar conteúdo RSS",
+ "entry.scraper.title.rss": "Obter conteúdo RSS",
"entry.scraper.label": "Baixar",
"entry.scraper.title": "Obter conteúdo completo",
"entry.scraper.completed": "Feito!",
diff --git a/internal/locale/translations/ru_RU.json b/internal/locale/translations/ru_RU.json
index 69c139f0183..a0d51f7a83a 100644
--- a/internal/locale/translations/ru_RU.json
+++ b/internal/locale/translations/ru_RU.json
@@ -72,6 +72,8 @@
"entry.save.title": "Сохранить эту статью",
"entry.save.completed": "Готово!",
"entry.save.toast.completed": "Статья сохранена",
+ "entry.scraper.label.rss": "Показать содержимое RSS",
+ "entry.scraper.title.rss": "Получить содержимое RSS",
"entry.scraper.label": "Скачать",
"entry.scraper.title": "Извлечь оригинальное содержимое",
"entry.scraper.completed": "Готово!",
diff --git a/internal/locale/translations/tr_TR.json b/internal/locale/translations/tr_TR.json
index 85238400541..502ecc6c292 100644
--- a/internal/locale/translations/tr_TR.json
+++ b/internal/locale/translations/tr_TR.json
@@ -72,6 +72,8 @@
"entry.save.title": "Bu makaleyi kaydet",
"entry.save.completed": "Bitti!",
"entry.save.toast.completed": "Makale kaydedildi",
+ "entry.scraper.label.rss": "RSS İçeriğini Göster",
+ "entry.scraper.title.rss": "RSS İçeriğini Al",
"entry.scraper.label": "İndir",
"entry.scraper.title": "Orijinal içeriği çek",
"entry.scraper.completed": "Bitti!",
diff --git a/internal/locale/translations/uk_UA.json b/internal/locale/translations/uk_UA.json
index eeb305d73b4..8de17076867 100644
--- a/internal/locale/translations/uk_UA.json
+++ b/internal/locale/translations/uk_UA.json
@@ -69,7 +69,9 @@
"entry.state.saving": "Зберігаю...",
"entry.state.loading": "Завантаження...",
"entry.save.label": "Зберегти",
+ "entry.scraper.label.rss": "Показати вміст RSS",
"entry.save.title": "Зберегти цю статтю",
+ "entry.scraper.title.rss": "Отримати вміст RSS",
"entry.save.completed": "Готово!",
"entry.save.toast.completed": "Стаття збережена",
"entry.scraper.label": "Завантажити",
diff --git a/internal/locale/translations/zh_CN.json b/internal/locale/translations/zh_CN.json
index dc1079c420f..ea356a9c958 100644
--- a/internal/locale/translations/zh_CN.json
+++ b/internal/locale/translations/zh_CN.json
@@ -72,6 +72,8 @@
"entry.save.title": "保存这篇文章",
"entry.save.completed": "完成",
"entry.save.toast.completed": "已保存文章",
+ "entry.scraper.label.rss": "显示 RSS 内容",
+ "entry.scraper.title.rss": "获取 RSS 内容",
"entry.scraper.label": "抓取全文",
"entry.scraper.title": "抓取全文内容",
"entry.scraper.completed": "抓取完成",
diff --git a/internal/locale/translations/zh_TW.json b/internal/locale/translations/zh_TW.json
index 4b4316f3b0e..92f840936e6 100644
--- a/internal/locale/translations/zh_TW.json
+++ b/internal/locale/translations/zh_TW.json
@@ -72,6 +72,8 @@
"entry.save.title": "儲存這篇文章",
"entry.save.completed": "完成",
"entry.save.toast.completed": "已儲存文章",
+ "entry.scraper.label.rss": "顯示 RSS 內容",
+ "entry.scraper.title.rss": "獲取 RSS 內容",
"entry.scraper.label": "下載原文",
"entry.scraper.title": "下載原文內容",
"entry.scraper.completed": "下載完成",
diff --git a/internal/model/entry.go b/internal/model/entry.go
index 7631119ab6b..93de92a49bd 100644
--- a/internal/model/entry.go
+++ b/internal/model/entry.go
@@ -30,6 +30,7 @@ type Entry struct {
CreatedAt time.Time `json:"created_at"`
ChangedAt time.Time `json:"changed_at"`
Content string `json:"content"`
+ WebContent string `json:"web_content,omitempty"`
Author string `json:"author"`
ShareCode string `json:"share_code"`
Starred bool `json:"starred"`
diff --git a/internal/reader/processor/processor.go b/internal/reader/processor/processor.go
index 913ae0b3bfc..0bb20527b1e 100644
--- a/internal/reader/processor/processor.go
+++ b/internal/reader/processor/processor.go
@@ -98,14 +98,14 @@ func ProcessFeedEntries(store *storage.Storage, feed *model.Feed, user *model.Us
)
} else if content != "" {
// We replace the entry content only if the scraper doesn't return any error.
- entry.Content = content
+ entry.WebContent = content
}
}
rewrite.Rewriter(websiteURL, entry, feed.RewriteRules)
// The sanitizer should always run at the end of the process to make sure unsafe HTML is filtered.
- entry.Content = sanitizer.Sanitize(websiteURL, entry.Content)
+ entry.WebContent = sanitizer.Sanitize(websiteURL, entry.Content)
updateEntryReadingTime(store, feed, entry, entryIsNew, user)
filteredEntries = append(filteredEntries, entry)
@@ -209,14 +209,14 @@ func ProcessEntryWebPage(feed *model.Feed, entry *model.Entry, user *model.User)
}
if content != "" {
- entry.Content = content
+ entry.WebContent = content
if user.ShowReadingTime {
- entry.ReadingTime = readingtime.EstimateReadingTime(entry.Content, user.DefaultReadingSpeed, user.CJKReadingSpeed)
+ entry.ReadingTime = readingtime.EstimateReadingTime(entry.WebContent, user.DefaultReadingSpeed, user.CJKReadingSpeed)
}
}
rewrite.Rewriter(websiteURL, entry, entry.Feed.RewriteRules)
- entry.Content = sanitizer.Sanitize(websiteURL, entry.Content)
+ entry.WebContent = sanitizer.Sanitize(websiteURL, entry.WebContent)
return nil
}
diff --git a/internal/reader/rewrite/rewriter.go b/internal/reader/rewrite/rewriter.go
index b577f687517..37d9243787c 100644
--- a/internal/reader/rewrite/rewriter.go
+++ b/internal/reader/rewrite/rewriter.go
@@ -24,35 +24,35 @@ type rule struct {
func (rule rule) applyRule(entryURL string, entry *model.Entry) {
switch rule.name {
case "add_image_title":
- entry.Content = addImageTitle(entryURL, entry.Content)
+ entry.WebContent = addImageTitle(entryURL, entry.WebContent)
case "add_mailto_subject":
- entry.Content = addMailtoSubject(entryURL, entry.Content)
+ entry.WebContent = addMailtoSubject(entryURL, entry.WebContent)
case "add_dynamic_image":
- entry.Content = addDynamicImage(entryURL, entry.Content)
+ entry.WebContent = addDynamicImage(entryURL, entry.WebContent)
case "add_dynamic_iframe":
- entry.Content = addDynamicIframe(entryURL, entry.Content)
+ entry.WebContent = addDynamicIframe(entryURL, entry.WebContent)
case "add_youtube_video":
- entry.Content = addYoutubeVideo(entryURL, entry.Content)
+ entry.WebContent = addYoutubeVideo(entryURL, entry.WebContent)
case "add_invidious_video":
- entry.Content = addInvidiousVideo(entryURL, entry.Content)
+ entry.WebContent = addInvidiousVideo(entryURL, entry.WebContent)
case "add_youtube_video_using_invidious_player":
- entry.Content = addYoutubeVideoUsingInvidiousPlayer(entryURL, entry.Content)
+ entry.WebContent = addYoutubeVideoUsingInvidiousPlayer(entryURL, entry.WebContent)
case "add_youtube_video_from_id":
- entry.Content = addYoutubeVideoFromId(entry.Content)
+ entry.WebContent = addYoutubeVideoFromId(entry.WebContent)
case "add_pdf_download_link":
- entry.Content = addPDFLink(entryURL, entry.Content)
+ entry.WebContent = addPDFLink(entryURL, entry.WebContent)
case "nl2br":
- entry.Content = strings.ReplaceAll(entry.Content, "\n", "
")
+ entry.WebContent = strings.ReplaceAll(entry.WebContent, "\n", "
")
case "convert_text_link", "convert_text_links":
- entry.Content = replaceTextLinks(entry.Content)
+ entry.WebContent = replaceTextLinks(entry.WebContent)
case "fix_medium_images":
- entry.Content = fixMediumImages(entryURL, entry.Content)
+ entry.WebContent = fixMediumImages(entryURL, entry.WebContent)
case "use_noscript_figure_images":
- entry.Content = useNoScriptImages(entryURL, entry.Content)
+ entry.WebContent = useNoScriptImages(entryURL, entry.WebContent)
case "replace":
// Format: replace("search-term"|"replace-term")
if len(rule.args) >= 2 {
- entry.Content = replaceCustom(entry.Content, rule.args[0], rule.args[1])
+ entry.WebContent = replaceCustom(entry.WebContent, rule.args[0], rule.args[1])
} else {
slog.Warn("Cannot find search and replace terms for replace rule",
slog.Any("rule", rule),
@@ -72,7 +72,7 @@ func (rule rule) applyRule(entryURL string, entry *model.Entry) {
case "remove":
// Format: remove("#selector > .element, .another")
if len(rule.args) >= 1 {
- entry.Content = removeCustom(entry.Content, rule.args[0])
+ entry.WebContent = removeCustom(entry.WebContent, rule.args[0])
} else {
slog.Warn("Cannot find selector for remove rule",
slog.Any("rule", rule),
@@ -80,21 +80,21 @@ func (rule rule) applyRule(entryURL string, entry *model.Entry) {
)
}
case "add_castopod_episode":
- entry.Content = addCastopodEpisode(entryURL, entry.Content)
+ entry.WebContent = addCastopodEpisode(entryURL, entry.WebContent)
case "base64_decode":
selector := "body"
if len(rule.args) >= 1 {
selector = rule.args[0]
}
- entry.Content = applyFuncOnTextContent(entry.Content, selector, decodeBase64Content)
+ entry.WebContent = applyFuncOnTextContent(entry.WebContent, selector, decodeBase64Content)
case "add_hn_links_using_hack":
- entry.Content = addHackerNewsLinksUsing(entry.Content, "hack")
+ entry.WebContent = addHackerNewsLinksUsing(entry.WebContent, "hack")
case "add_hn_links_using_opener":
- entry.Content = addHackerNewsLinksUsing(entry.Content, "opener")
+ entry.WebContent = addHackerNewsLinksUsing(entry.WebContent, "opener")
case "parse_markdown":
- entry.Content = parseMarkdown(entry.Content)
+ entry.WebContent = parseMarkdown(entry.WebContent)
case "remove_tables":
- entry.Content = removeTables(entry.Content)
+ entry.WebContent = removeTables(entry.WebContent)
case "remove_clickbait":
entry.Title = cases.Title(language.English).String(strings.ToLower(entry.Title))
}
diff --git a/internal/reader/rewrite/rewriter_test.go b/internal/reader/rewrite/rewriter_test.go
index fa2b765bd2e..2dcceb6b46a 100644
--- a/internal/reader/rewrite/rewriter_test.go
+++ b/internal/reader/rewrite/rewriter_test.go
@@ -50,12 +50,12 @@ func TestReplaceTextLinks(t *testing.T) {
func TestRewriteWithNoMatchingRule(t *testing.T) {
controlEntry := &model.Entry{
- Title: `A title`,
- Content: `Some text.`,
+ Title: `A title`,
+ WebContent: `Some text.`,
}
testEntry := &model.Entry{
- Title: `A title`,
- Content: `Some text.`,
+ Title: `A title`,
+ WebContent: `Some text.`,
}
Rewriter("https://example.org/article", testEntry, ``)
@@ -68,12 +68,12 @@ func TestRewriteWithYoutubeLink(t *testing.T) {
config.Opts = config.NewOptions()
controlEntry := &model.Entry{
- Title: `A title`,
- Content: `
Video Description`,
+ Title: `A title`,
+ WebContent: `
Video Description`,
}
testEntry := &model.Entry{
- Title: `A title`,
- Content: `Video Description`,
+ Title: `A title`,
+ WebContent: `Video Description`,
}
Rewriter("https://www.youtube.com/watch?v=1234", testEntry, ``)
@@ -95,12 +95,12 @@ func TestRewriteWithYoutubeLinkAndCustomEmbedURL(t *testing.T) {
}
controlEntry := &model.Entry{
- Title: `A title`,
- Content: `
Video Description`,
+ Title: `A title`,
+ WebContent: `
Video Description`,
}
testEntry := &model.Entry{
- Title: `A title`,
- Content: `Video Description`,
+ Title: `A title`,
+ WebContent: `Video Description`,
}
Rewriter("https://www.youtube.com/watch?v=1234", testEntry, ``)
@@ -111,12 +111,12 @@ func TestRewriteWithYoutubeLinkAndCustomEmbedURL(t *testing.T) {
func TestRewriteWithInexistingCustomRule(t *testing.T) {
controlEntry := &model.Entry{
- Title: `A title`,
- Content: `Video Description`,
+ Title: `A title`,
+ WebContent: `Video Description`,
}
testEntry := &model.Entry{
- Title: `A title`,
- Content: `Video Description`,
+ Title: `A title`,
+ WebContent: `Video Description`,
}
Rewriter("https://www.youtube.com/watch?v=1234", testEntry, `some rule`)
@@ -127,12 +127,12 @@ func TestRewriteWithInexistingCustomRule(t *testing.T) {
func TestRewriteWithXkcdLink(t *testing.T) {
controlEntry := &model.Entry{
- Title: `A title`,
- Content: ``,
+ Title: `A title`,
+ WebContent: ``,
}
testEntry := &model.Entry{
- Title: `A title`,
- Content: ``,
+ Title: `A title`,
+ WebContent: ``,
}
Rewriter("https://xkcd.com/1912/", testEntry, ``)
@@ -143,12 +143,12 @@ func TestRewriteWithXkcdLink(t *testing.T) {
func TestRewriteWithXkcdLinkHtmlInjection(t *testing.T) {
controlEntry := &model.Entry{
- Title: `A title`,
- Content: ``,
+ Title: `A title`,
+ WebContent: ``,
}
testEntry := &model.Entry{
- Title: `A title`,
- Content: ``,
+ Title: `A title`,
+ WebContent: ``,
}
Rewriter("https://xkcd.com/1912/", testEntry, ``)
@@ -159,12 +159,12 @@ func TestRewriteWithXkcdLinkHtmlInjection(t *testing.T) {
func TestRewriteWithXkcdLinkAndImageNoTitle(t *testing.T) {
controlEntry := &model.Entry{
- Title: `A title`,
- Content: ``,
+ Title: `A title`,
+ WebContent: ``,
}
testEntry := &model.Entry{
- Title: `A title`,
- Content: ``,
+ Title: `A title`,
+ WebContent: ``,
}
Rewriter("https://xkcd.com/1912/", testEntry, ``)
@@ -175,12 +175,12 @@ func TestRewriteWithXkcdLinkAndImageNoTitle(t *testing.T) {
func TestRewriteWithXkcdLinkAndNoImage(t *testing.T) {
controlEntry := &model.Entry{
- Title: `A title`,
- Content: `test`,
+ Title: `A title`,
+ WebContent: `test`,
}
testEntry := &model.Entry{
- Title: `A title`,
- Content: `test`,
+ Title: `A title`,
+ WebContent: `test`,
}
Rewriter("https://xkcd.com/1912/", testEntry, ``)
@@ -191,12 +191,12 @@ func TestRewriteWithXkcdLinkAndNoImage(t *testing.T) {
func TestRewriteWithXkcdAndNoImage(t *testing.T) {
controlEntry := &model.Entry{
- Title: `A title`,
- Content: `test`,
+ Title: `A title`,
+ WebContent: `test`,
}
testEntry := &model.Entry{
- Title: `A title`,
- Content: `test`,
+ Title: `A title`,
+ WebContent: `test`,
}
Rewriter("https://xkcd.com/1912/", testEntry, ``)
@@ -207,12 +207,12 @@ func TestRewriteWithXkcdAndNoImage(t *testing.T) {
func TestRewriteMailtoLink(t *testing.T) {
controlEntry := &model.Entry{
- Title: `A title`,
- Content: `contact [blah blah]`,
+ Title: `A title`,
+ WebContent: `contact [blah blah]`,
}
testEntry := &model.Entry{
- Title: `A title`,
- Content: `contact`,
+ Title: `A title`,
+ WebContent: `contact`,
}
Rewriter("https://www.qwantz.com/", testEntry, ``)
@@ -223,12 +223,12 @@ func TestRewriteMailtoLink(t *testing.T) {
func TestRewriteWithPDFLink(t *testing.T) {
controlEntry := &model.Entry{
- Title: `A title`,
- Content: `PDF
test`,
+ Title: `A title`,
+ WebContent: `PDF
test`,
}
testEntry := &model.Entry{
- Title: `A title`,
- Content: `test`,
+ Title: `A title`,
+ WebContent: `test`,
}
Rewriter("https://example.org/document.pdf", testEntry, ``)
@@ -239,12 +239,12 @@ func TestRewriteWithPDFLink(t *testing.T) {
func TestRewriteWithNoLazyImage(t *testing.T) {
controlEntry := &model.Entry{
- Title: `A title`,
- Content: ``,
+ Title: `A title`,
+ WebContent: ``,
}
testEntry := &model.Entry{
- Title: `A title`,
- Content: ``,
+ Title: `A title`,
+ WebContent: ``,
}
Rewriter("https://example.org/article", testEntry, "add_dynamic_image")
@@ -255,12 +255,12 @@ func TestRewriteWithNoLazyImage(t *testing.T) {
func TestRewriteWithLazyImage(t *testing.T) {
controlEntry := &model.Entry{
- Title: `A title`,
- Content: ``,
+ Title: `A title`,
+ WebContent: ``,
}
testEntry := &model.Entry{
- Title: `A title`,
- Content: ``,
+ Title: `A title`,
+ WebContent: ``,
}
Rewriter("https://example.org/article", testEntry, "add_dynamic_image")
@@ -271,12 +271,12 @@ func TestRewriteWithLazyImage(t *testing.T) {
func TestRewriteWithLazyDivImage(t *testing.T) {
controlEntry := &model.Entry{
- Title: `A title`,
- Content: ``,
+ Title: `A title`,
+ WebContent: ``,
}
testEntry := &model.Entry{
- Title: `A title`,
- Content: `
Test
Hello World!
Test
`, + Title: `A title`, + WebContent: `Test
Hello World!
Test
`, } testEntry := &model.Entry{ - Title: `A title`, - Content: `Test
|
Test
|
Article URL: https://example.org/article
+ WebContent: `Article URL: https://example.org/article
Comments URL: https://news.ycombinator.com/item?id=37620043
Points: 23
# Comments: 38
`, @@ -637,7 +637,7 @@ func TestAddHackerNewsLinksUsingHack(t *testing.T) { controlEntry := &model.Entry{ Title: `A title`, - Content: `Article URL: https://example.org/article
+ WebContent: `Article URL: https://example.org/article
Comments URL: https://news.ycombinator.com/item?id=37620043 Open with HACK
Points: 23
# Comments: 38
`, @@ -652,7 +652,7 @@ func TestAddHackerNewsLinksUsingHack(t *testing.T) { func TestAddHackerNewsLinksUsingOpener(t *testing.T) { testEntry := &model.Entry{ Title: `A title`, - Content: `Article URL: https://example.org/article
+ WebContent: `Article URL: https://example.org/article
Comments URL: https://news.ycombinator.com/item?id=37620043
Points: 23
# Comments: 38
`, @@ -660,7 +660,7 @@ func TestAddHackerNewsLinksUsingOpener(t *testing.T) { controlEntry := &model.Entry{ Title: `A title`, - Content: `Article URL: https://example.org/article
+ WebContent: `Article URL: https://example.org/article
Comments URL: https://news.ycombinator.com/item?id=37620043 Open with Opener
Points: 23
# Comments: 38
`, @@ -675,7 +675,7 @@ func TestAddHackerNewsLinksUsingOpener(t *testing.T) { func TestAddImageTitle(t *testing.T) { testEntry := &model.Entry{ Title: `A title`, - Content: ` + WebContent: ` @@ -688,7 +688,7 @@ func TestAddImageTitle(t *testing.T) { controlEntry := &model.Entry{ Title: `A title`, - Content: ` + WebContent: ` diff --git a/internal/storage/entry.go b/internal/storage/entry.go index 1a7cc6d73dc..bd4e342eee7 100644 --- a/internal/storage/entry.go +++ b/internal/storage/entry.go @@ -77,13 +77,14 @@ func (s *Storage) UpdateEntryTitleAndContent(entry *model.Entry) error { SET title=$1, content=$2, - reading_time=$3, - document_vectors = setweight(to_tsvector(left(coalesce($1, ''), 500000)), 'A') || setweight(to_tsvector(left(coalesce($2, ''), 500000)), 'B') + web_content=$3, + reading_time=$4, + document_vectors = setweight(to_tsvector(left(coalesce($1, ''), 500000)), 'A') || setweight(to_tsvector(left(coalesce($2, ''), 500000)), 'B') || setweight(to_tsvector(left(coalesce($3, ''), 500000)), 'C') WHERE - id=$4 AND user_id=$5 + id=$5 AND user_id=$6 ` - if _, err := s.db.Exec(query, entry.Title, entry.Content, entry.ReadingTime, entry.ID, entry.UserID); err != nil { + if _, err := s.db.Exec(query, entry.Title, entry.Content, entry.WebContent, entry.ReadingTime, entry.ID, entry.UserID); err != nil { return fmt.Errorf(`store: unable to update entry #%d: %v`, entry.ID, err) } @@ -101,6 +102,7 @@ func (s *Storage) createEntry(tx *sql.Tx, entry *model.Entry) error { comments_url, published_at, content, + web_content, author, user_id, feed_id, @@ -121,9 +123,10 @@ func (s *Storage) createEntry(tx *sql.Tx, entry *model.Entry) error { $8, $9, $10, + $11, now(), - setweight(to_tsvector(left(coalesce($1, ''), 500000)), 'A') || setweight(to_tsvector(left(coalesce($6, ''), 500000)), 'B'), - $11 + setweight(to_tsvector(left(coalesce($1, ''), 500000)), 'A') || setweight(to_tsvector(left(coalesce($6, ''), 500000)), 'B') || setweight(to_tsvector(left(coalesce($7, ''), 500000)), 'C'), + $12 ) RETURNING id, status, created_at, changed_at @@ -136,6 +139,7 @@ func (s *Storage) createEntry(tx *sql.Tx, entry *model.Entry) error { entry.CommentsURL, entry.Date, entry.Content, + entry.WebContent, entry.Author, entry.UserID, entry.FeedID, @@ -176,12 +180,13 @@ func (s *Storage) updateEntry(tx *sql.Tx, entry *model.Entry) error { url=$2, comments_url=$3, content=$4, - author=$5, - reading_time=$6, - document_vectors = setweight(to_tsvector(left(coalesce($1, ''), 500000)), 'A') || setweight(to_tsvector(left(coalesce($4, ''), 500000)), 'B'), - tags=$10 + web_content=$5, + author=$6, + reading_time=$7, + document_vectors = setweight(to_tsvector(left(coalesce($1, ''), 500000)), 'A') || setweight(to_tsvector(left(coalesce($4, ''), 500000)), 'B') || setweight(to_tsvector(left(coalesce($5, ''), 500000)), 'C'), + tags=$11 WHERE - user_id=$7 AND feed_id=$8 AND hash=$9 + user_id=$8 AND feed_id=$9 AND hash=$10 RETURNING id ` @@ -191,6 +196,7 @@ func (s *Storage) updateEntry(tx *sql.Tx, entry *model.Entry) error { entry.URL, entry.CommentsURL, entry.Content, + entry.WebContent, entry.Author, entry.ReadingTime, entry.UserID, diff --git a/internal/storage/entry_query_builder.go b/internal/storage/entry_query_builder.go index 680fbedb25e..c70500c5a46 100644 --- a/internal/storage/entry_query_builder.go +++ b/internal/storage/entry_query_builder.go @@ -271,6 +271,7 @@ func (e *EntryQueryBuilder) GetEntries() (model.Entries, error) { e.author, e.share_code, e.content, + e.web_content, e.status, e.starred, e.reading_time, @@ -337,6 +338,7 @@ func (e *EntryQueryBuilder) GetEntries() (model.Entries, error) { &entry.Author, &entry.ShareCode, &entry.Content, + &entry.WebContent, &entry.Status, &entry.Starred, &entry.ReadingTime, @@ -361,7 +363,6 @@ func (e *EntryQueryBuilder) GetEntries() (model.Entries, error) { &iconID, &tz, ) - if err != nil { return nil, fmt.Errorf("store: unable to fetch entry row: %v", err) } diff --git a/internal/template/templates/views/entry.html b/internal/template/templates/views/entry.html index 4284f097013..a6ec78e1b9f 100644 --- a/internal/template/templates/views/entry.html +++ b/internal/template/templates/views/entry.html @@ -85,11 +85,17 @@