diff --git a/assets/javascripts/discourse/initializers/url-to-article.js b/assets/javascripts/discourse/initializers/url-to-article.js
index 649e840..1cc9db5 100644
--- a/assets/javascripts/discourse/initializers/url-to-article.js
+++ b/assets/javascripts/discourse/initializers/url-to-article.js
@@ -1,9 +1,21 @@
import { apiInitializer } from "discourse/lib/api";
import { ajax } from "discourse/lib/ajax";
-import { i18n } from "discourse-i18n";
const URL_REGEX = /^(https?:\/\/[^\s/$.?#][^\s]*)$/i;
+const STRINGS = {
+ bar_label: "URL detected β import as article?",
+ fetch_button: "Import Article",
+ onebox_button: "Use Onebox",
+ dismiss: "Dismiss",
+ fetching: "Fetchingβ¦",
+ success: "Article imported!",
+ error_generic: "Unknown error",
+ error_prefix: "Error:",
+ source_label: "Source",
+ retry_button: "Retry",
+};
+
export default apiInitializer("1.8.0", (api) => {
if (!api.container.lookup("site-settings:main").url_to_article_enabled) {
return;
@@ -29,9 +41,9 @@ export default apiInitializer("1.8.0", (api) => {
},
// ---- Title paste interception -------------------------------------
- // We use capture:true so our handler runs before Discourse's, then
+ // capture:true so our handler runs before Discourse's, then
// preventDefault + stopImmediatePropagation so Discourse never sees
- // the paste event at all β no title lookup, no onebox race.
+ // the paste event β no title lookup, no onebox race.
_attachTitlePasteListener(attempts = 0) {
const input = document.querySelector("#reply-title");
@@ -66,22 +78,21 @@ export default apiInitializer("1.8.0", (api) => {
bar.className = "url-to-article-bar";
bar.innerHTML = `
π
- ${i18n("url_to_article.bar_label")}
+ ${STRINGS.bar_label}
+ aria-label="${STRINGS.dismiss}">β
`;
bar.querySelector(".url-to-article-btn").addEventListener("click", () => {
this._fetchAndPopulate(url);
});
- // "Use Onebox" β commit URL into Ember model normally so Discourse takes over
bar.querySelector(".url-to-article-onebox-btn").addEventListener("click", () => {
this._hideArticleBar();
this._commitUrlToModel();
@@ -135,9 +146,9 @@ export default apiInitializer("1.8.0", (api) => {
if (btn) {
btn.disabled = true;
- btn.textContent = i18n("url_to_article.fetching");
+ btn.textContent = STRINGS.fetching;
}
- this._setStatus(i18n("url_to_article.fetching"), "info");
+ this._setStatus(STRINGS.fetching, "info");
try {
const data = await ajax("/url-to-article/extract", {
@@ -148,20 +159,17 @@ export default apiInitializer("1.8.0", (api) => {
if (data.error) throw new Error(data.error);
this._populateComposer(data);
- this._setStatus(i18n("url_to_article.success"), "success");
+ this._setStatus(STRINGS.success, "success");
setTimeout(() => this._hideArticleBar(), 3000);
} catch (err) {
const msg =
err.jqXHR?.responseJSON?.error ||
err.message ||
- i18n("url_to_article.error_generic");
- this._setStatus(
- `${i18n("url_to_article.error_prefix")} ${msg}`,
- "error"
- );
+ STRINGS.error_generic;
+ this._setStatus(`${STRINGS.error_prefix} ${msg}`, "error");
if (btn) {
btn.disabled = false;
- btn.textContent = i18n("url_to_article.retry_button");
+ btn.textContent = STRINGS.retry_button;
}
}
},
@@ -175,10 +183,10 @@ export default apiInitializer("1.8.0", (api) => {
const byline = data.byline ? ` β *${data.byline}*` : "";
if (siteName || byline) {
lines.push(`> ${siteName}${byline}`);
- lines.push(`> ${i18n("url_to_article.source_label")}: <${data.url}>`);
+ lines.push(`> ${STRINGS.source_label}: <${data.url}>`);
lines.push("");
} else {
- lines.push(`> ${i18n("url_to_article.source_label")}: <${data.url}>`);
+ lines.push(`> ${STRINGS.source_label}: <${data.url}>`);
lines.push("");
}
@@ -191,12 +199,10 @@ export default apiInitializer("1.8.0", (api) => {
lines.push(data.markdown || "");
- // Set title directly on the model (bypasses the title-lookup trigger)
composerModel.set("title", data.title || this._pendingUrl || "");
composerModel.set("reply", lines.join("\n"));
this._pendingUrl = null;
- // Sync the title input visually
if (this._titleInputEl) {
this._titleInputEl.value = composerModel.get("title");
}