diff --git a/app/assets/javascripts/admin/components/resumable-upload.js b/app/assets/javascripts/admin/components/resumable-upload.js index ed95ea68be4..97b6f19875a 100644 --- a/app/assets/javascripts/admin/components/resumable-upload.js +++ b/app/assets/javascripts/admin/components/resumable-upload.js @@ -1,3 +1,4 @@ +import getURL from "discourse-common/lib/get-url"; import I18n from "I18n"; import { later, schedule } from "@ember/runloop"; import Component from "@ember/component"; @@ -31,7 +32,7 @@ export default Component.extend({ @on("init") _initialize() { this.resumable = new Resumable({ - target: Discourse.getURL(this.target), + target: getURL(this.target), maxFiles: 1, // only 1 file at a time headers: { "X-CSRF-Token": document.querySelector("meta[name='csrf-token']") diff --git a/app/assets/javascripts/admin/controllers/admin-dashboard-general.js b/app/assets/javascripts/admin/controllers/admin-dashboard-general.js index 07a195b5663..2030c1e613a 100644 --- a/app/assets/javascripts/admin/controllers/admin-dashboard-general.js +++ b/app/assets/javascripts/admin/controllers/admin-dashboard-general.js @@ -8,6 +8,7 @@ import AdminDashboard from "admin/models/admin-dashboard"; import Report from "admin/models/report"; import PeriodComputationMixin from "admin/mixins/period-computation"; import { computed } from "@ember/object"; +import getURL from "discourse-common/lib/get-url"; function staticReport(reportType) { return computed("reports.[]", function() { @@ -20,7 +21,6 @@ export default Controller.extend(PeriodComputationMixin, { dashboardFetchedAt: null, exceptionController: inject("exception"), logSearchQueriesEnabled: setting("log_search_queries"), - basePath: Discourse.BaseUri, @discourseComputed("siteSettings.dashboard_general_tab_activity_metrics") activityMetrics(metrics) { @@ -107,7 +107,7 @@ export default Controller.extend(PeriodComputationMixin, { @discourseComputed trendingSearchDisabledLabel() { return I18n.t("admin.dashboard.reports.trending_search.disabled", { - basePath: Discourse.BaseUri + basePath: getURL("/") }); }, @@ -150,6 +150,6 @@ export default Controller.extend(PeriodComputationMixin, { }, _reportsForPeriodURL(period) { - return Discourse.getURL(`/admin?period=${period}`); + return getURL(`/admin?period=${period}`); } }); diff --git a/app/assets/javascripts/admin/controllers/admin-dashboard-moderation.js b/app/assets/javascripts/admin/controllers/admin-dashboard-moderation.js index 95f820b598f..f37d8606afe 100644 --- a/app/assets/javascripts/admin/controllers/admin-dashboard-moderation.js +++ b/app/assets/javascripts/admin/controllers/admin-dashboard-moderation.js @@ -1,3 +1,4 @@ +import getURL from "discourse-common/lib/get-url"; import discourseComputed from "discourse-common/utils/decorators"; import Controller from "@ember/controller"; import PeriodComputationMixin from "admin/mixins/period-computation"; @@ -45,6 +46,6 @@ export default Controller.extend(PeriodComputationMixin, { }, _reportsForPeriodURL(period) { - return Discourse.getURL(`/admin/dashboard/moderation?period=${period}`); + return getURL(`/admin/dashboard/moderation?period=${period}`); } }); diff --git a/app/assets/javascripts/admin/controllers/admin-web-hooks-show.js b/app/assets/javascripts/admin/controllers/admin-web-hooks-show.js index 031ad8ee8b4..e6f20ee2f52 100644 --- a/app/assets/javascripts/admin/controllers/admin-web-hooks-show.js +++ b/app/assets/javascripts/admin/controllers/admin-web-hooks-show.js @@ -6,6 +6,7 @@ import Controller, { inject as controller } from "@ember/controller"; import { popupAjaxError } from "discourse/lib/ajax-error"; import { extractDomainFromUrl } from "discourse/lib/utilities"; import EmberObject from "@ember/object"; +import { isAbsoluteURL } from "discourse-common/lib/get-url"; export default Controller.extend({ adminWebHooks: controller(), @@ -109,7 +110,7 @@ export default Controller.extend({ domain === "localhost" || domain.match(/192\.168\.\d+\.\d+/) || domain.match(/127\.\d+\.\d+\.\d+/) || - url.startsWith(Discourse.BaseUrl) + isAbsoluteURL(url) ) { return bootbox.confirm( I18n.t("admin.web_hooks.warn_local_payload_url"), diff --git a/app/assets/javascripts/admin/models/admin-user.js b/app/assets/javascripts/admin/models/admin-user.js index 9977fa8dd46..8dc7685cc10 100644 --- a/app/assets/javascripts/admin/models/admin-user.js +++ b/app/assets/javascripts/admin/models/admin-user.js @@ -1,3 +1,4 @@ +import getURL from "discourse-common/lib/get-url"; import I18n from "I18n"; import discourseComputed from "discourse-common/utils/decorators"; import { filter, or, gt, lt, not } from "@ember/object/computed"; @@ -43,7 +44,7 @@ const AdminUser = User.extend({ @discourseComputed bounceLink() { - return Discourse.getURL("/admin/email/bounced"); + return getURL("/admin/email/bounced"); }, canResetBounceScore: gt("bounce_score", 0), @@ -306,7 +307,7 @@ const AdminUser = User.extend({ type: "POST", data: { username_or_email: this.username } }) - .then(() => (document.location = Discourse.getURL("/"))) + .then(() => (document.location = getURL("/"))) .catch(e => { if (e.status === 404) { bootbox.alert(I18n.t("admin.impersonate.not_found")); @@ -395,11 +396,11 @@ const AdminUser = User.extend({ .then(function(data) { if (data.success) { if (data.username) { - document.location = Discourse.getURL( + document.location = getURL( `/admin/users/${user.get("id")}/${data.username}` ); } else { - document.location = Discourse.getURL("/admin/users/list/active"); + document.location = getURL("/admin/users/list/active"); } } else { bootbox.alert(I18n.t("admin.user.anonymize_failed")); @@ -456,7 +457,7 @@ const AdminUser = User.extend({ if (/^\/admin\/users\/list\//.test(location)) { document.location = location; } else { - document.location = Discourse.getURL("/admin/users/list/active"); + document.location = getURL("/admin/users/list/active"); } } else { bootbox.alert(I18n.t("admin.user.delete_failed")); diff --git a/app/assets/javascripts/admin/models/backup.js b/app/assets/javascripts/admin/models/backup.js index 45727a28b23..0b6f7122a4d 100644 --- a/app/assets/javascripts/admin/models/backup.js +++ b/app/assets/javascripts/admin/models/backup.js @@ -1,3 +1,4 @@ +import getURL from "discourse-common/lib/get-url"; import I18n from "I18n"; import { ajax } from "discourse/lib/ajax"; import { extractError } from "discourse/lib/ajax-error"; @@ -66,7 +67,7 @@ Backup.reopenClass({ bootbox.alert(result.message); } else { // redirect to homepage (session might be lost) - window.location = Discourse.getURL("/"); + window.location = getURL("/"); } }); } diff --git a/app/assets/javascripts/admin/models/email-log.js b/app/assets/javascripts/admin/models/email-log.js index c2eaaa26e6d..1317df29436 100644 --- a/app/assets/javascripts/admin/models/email-log.js +++ b/app/assets/javascripts/admin/models/email-log.js @@ -1,3 +1,4 @@ +import getURL from "discourse-common/lib/get-url"; import { ajax } from "discourse/lib/ajax"; import AdminUser from "admin/models/admin-user"; import EmberObject from "@ember/object"; @@ -13,7 +14,7 @@ EmailLog.reopenClass({ } if (attrs.post_url) { - attrs.post_url = Discourse.getURL(attrs.post_url); + attrs.post_url = getURL(attrs.post_url); } return this._super(attrs); diff --git a/app/assets/javascripts/admin/models/report.js b/app/assets/javascripts/admin/models/report.js index 2e0b4488875..9d2f25f9a1d 100644 --- a/app/assets/javascripts/admin/models/report.js +++ b/app/assets/javascripts/admin/models/report.js @@ -1,3 +1,4 @@ +import getURL from "discourse-common/lib/get-url"; import I18n from "I18n"; import discourseComputed from "discourse-common/utils/decorators"; import { makeArray } from "discourse-common/lib/helpers"; @@ -37,7 +38,7 @@ const Report = EmberObject.extend({ .locale("en") .format("YYYY-MM-DD"); - return Discourse.getURL( + return getURL( `/admin/reports/${type}?start_date=${start_date}&end_date=${end_date}` ); }, @@ -335,7 +336,7 @@ const Report = EmberObject.extend({ avatar_template: row[properties.avatar] }); - const href = Discourse.getURL(`/admin/users/${userId}/${username}`); + const href = getURL(`/admin/users/${userId}/${username}`); const avatarImg = renderAvatar(user, { imageSize: "tiny", @@ -356,7 +357,7 @@ const Report = EmberObject.extend({ const formatedValue = () => { const topicId = row[properties.id]; - const href = Discourse.getURL(`/t/-/${topicId}`); + const href = getURL(`/t/-/${topicId}`); return `${escapeExpression(topicTitle)}`; }; @@ -370,7 +371,7 @@ const Report = EmberObject.extend({ const postTitle = row[properties.truncated_raw]; const postNumber = row[properties.number]; const topicId = row[properties.topic_id]; - const href = Discourse.getURL(`/t/-/${topicId}/${postNumber}`); + const href = getURL(`/t/-/${topicId}/${postNumber}`); return { property: properties.title, @@ -434,7 +435,7 @@ const Report = EmberObject.extend({ _linkLabel(properties, row) { const property = properties[0]; - const value = Discourse.getURL(row[property]); + const value = getURL(row[property]); const formatedValue = (href, anchor) => { return `${escapeExpression( anchor diff --git a/app/assets/javascripts/admin/routes/admin-backups.js b/app/assets/javascripts/admin/routes/admin-backups.js index 3d517acbf12..aa7c88aba98 100644 --- a/app/assets/javascripts/admin/routes/admin-backups.js +++ b/app/assets/javascripts/admin/routes/admin-backups.js @@ -1,3 +1,4 @@ +import getURL from "discourse-common/lib/get-url"; import I18n from "I18n"; import EmberObject from "@ember/object"; import DiscourseRoute from "discourse/routes/discourse"; @@ -40,7 +41,7 @@ export default DiscourseRoute.extend({ ); if (log.operation === "restore") { // redirect to homepage when the restore is done (session might be lost) - window.location = Discourse.getURL("/"); + window.location = getURL("/"); } } else { this.controllerFor("adminBackupsLogs") diff --git a/app/assets/javascripts/admin/templates/dashboard_general.hbs b/app/assets/javascripts/admin/templates/dashboard_general.hbs index 5566271a20d..8c90890c55e 100644 --- a/app/assets/javascripts/admin/templates/dashboard_general.hbs +++ b/app/assets/javascripts/admin/templates/dashboard_general.hbs @@ -147,7 +147,7 @@ filters=trendingSearchFilters isEnabled=logSearchQueriesEnabled disabledLabel=trendingSearchDisabledLabel}} - {{html-safe (i18n "admin.dashboard.reports.trending_search.more" basePath=basePath)}} + {{html-safe (i18n "admin.dashboard.reports.trending_search.more" basePath=(get-url "/"))}} {{/if}} diff --git a/app/assets/javascripts/discourse-common/addon/lib/get-url.js b/app/assets/javascripts/discourse-common/addon/lib/get-url.js index 4a3a20d0d80..eb36586e8d5 100644 --- a/app/assets/javascripts/discourse-common/addon/lib/get-url.js +++ b/app/assets/javascripts/discourse-common/addon/lib/get-url.js @@ -1,4 +1,5 @@ -let baseUri; +let cdn, baseUrl, baseUri; +let S3BaseUrl, S3CDN; export default function getURL(url) { if (!url) return url; @@ -17,3 +18,42 @@ export default function getURL(url) { return baseUri + url; } + +export function getURLWithCDN(url) { + url = getURL(url); + // only relative urls + if (cdn && /^\/[^\/]/.test(url)) { + url = cdn + url; + } else if (S3CDN) { + url = url.replace(S3BaseUrl, S3CDN); + } + return url; +} + +export function getAbsoluteURL(path) { + return baseUrl + path; +} + +export function isAbsoluteURL(url) { + return url.startsWith(baseUrl); +} + +export function withoutPrefix(path) { + const rootURL = (!baseUri ? "/" : baseUri).replace(/\/$/, ""); + return path.replace(rootURL, ""); +} + +export function setPrefix(configBaseUri) { + baseUri = configBaseUri; +} + +export function setupURL(configCdn, configBaseUrl, configBaseUri) { + cdn = configCdn; + baseUrl = configBaseUrl; + baseUri = configBaseUri; +} + +export function setupS3CDN(configS3BaseUrl, configS3CDN) { + S3BaseUrl = configS3BaseUrl; + S3CDN = configS3CDN; +} diff --git a/app/assets/javascripts/discourse/app/adapters/topic-list.js b/app/assets/javascripts/discourse/app/adapters/topic-list.js index bd45b85e094..359d7ee05ae 100644 --- a/app/assets/javascripts/discourse/app/adapters/topic-list.js +++ b/app/assets/javascripts/discourse/app/adapters/topic-list.js @@ -1,10 +1,11 @@ +import getURL from "discourse-common/lib/get-url"; import { ajax } from "discourse/lib/ajax"; import RestAdapter from "discourse/adapters/rest"; import PreloadStore from "discourse/lib/preload-store"; export function finderFor(filter, params) { return function() { - let url = Discourse.getURL("/") + filter + ".json"; + let url = getURL("/") + filter + ".json"; if (params) { const keys = Object.keys(params), diff --git a/app/assets/javascripts/discourse/app/app.js b/app/assets/javascripts/discourse/app/app.js index b484afcf522..06e5064e3e2 100644 --- a/app/assets/javascripts/discourse/app/app.js +++ b/app/assets/javascripts/discourse/app/app.js @@ -4,6 +4,8 @@ import { computed } from "@ember/object"; import { buildResolver } from "discourse-common/resolver"; import { bind } from "@ember/runloop"; import discourseComputed, { observes } from "discourse-common/utils/decorators"; +import { default as getURL, getURLWithCDN } from "discourse-common/lib/get-url"; +import deprecated from "discourse-common/lib/deprecated"; const _pluginCallbacks = []; @@ -42,26 +44,19 @@ const Discourse = Application.extend({ }, getURL(url) { - if (!url) return url; - - // if it's a non relative URL, return it. - if (url !== "/" && !/^\/[^\/]/.test(url)) return url; - - if (url[0] !== "/") url = "/" + url; - if (url.startsWith(this.BaseUri)) return url; - - return this.BaseUri + url; + deprecated( + "Import `getURL` from `discourse-common/lib/get-url` instead of `Discourse.getURL`", + { since: "2.5", dropFrom: "2.6" } + ); + return getURL(url); }, getURLWithCDN(url) { - url = this.getURL(url); - // only relative urls - if (this.CDN && /^\/[^\/]/.test(url)) { - url = this.CDN + url; - } else if (this.S3CDN) { - url = url.replace(this.S3BaseUrl, this.S3CDN); - } - return url; + deprecated( + "Import `getURLWithCDN` from `discourse-common/lib/get-url` instead of `Discourse.getURLWithCDN`", + { since: "2.5", dropFrom: "2.6" } + ); + return getURLWithCDN(url); }, Resolver: buildResolver("discourse"), diff --git a/app/assets/javascripts/discourse/app/components/cdn-img.js b/app/assets/javascripts/discourse/app/components/cdn-img.js index a5c7a2642a0..e343eaea1f2 100644 --- a/app/assets/javascripts/discourse/app/components/cdn-img.js +++ b/app/assets/javascripts/discourse/app/components/cdn-img.js @@ -1,3 +1,4 @@ +import { getURLWithCDN } from "discourse-common/lib/get-url"; import discourseComputed from "discourse-common/utils/decorators"; import Component from "@ember/component"; import { htmlSafe } from "@ember/template"; @@ -7,7 +8,7 @@ export default Component.extend({ @discourseComputed("src") cdnSrc(src) { - return Discourse.getURLWithCDN(src); + return getURLWithCDN(src); }, @discourseComputed("width", "height") diff --git a/app/assets/javascripts/discourse/app/components/composer-editor.js b/app/assets/javascripts/discourse/app/components/composer-editor.js index 2eb99f44c5b..74443c88ec4 100644 --- a/app/assets/javascripts/discourse/app/components/composer-editor.js +++ b/app/assets/javascripts/discourse/app/components/composer-editor.js @@ -1,3 +1,4 @@ +import getURL from "discourse-common/lib/get-url"; import I18n from "I18n"; import { debounce, later, next, schedule, throttle } from "@ember/runloop"; import Component from "@ember/component"; @@ -650,9 +651,7 @@ export default Component.extend({ const $element = $(this.element); $element.fileupload({ - url: Discourse.getURL( - `/uploads.json?client_id=${this.messageBus.clientId}` - ), + url: getURL(`/uploads.json?client_id=${this.messageBus.clientId}`), dataType: "json", pasteZone: $element }); diff --git a/app/assets/javascripts/discourse/app/components/discourse-tag-bound.js b/app/assets/javascripts/discourse/app/components/discourse-tag-bound.js index 13c87986311..becd4a1fa62 100644 --- a/app/assets/javascripts/discourse/app/components/discourse-tag-bound.js +++ b/app/assets/javascripts/discourse/app/components/discourse-tag-bound.js @@ -1,3 +1,4 @@ +import getURL from "discourse-common/lib/get-url"; import discourseComputed from "discourse-common/utils/decorators"; import Component from "@ember/component"; @@ -13,6 +14,6 @@ export default Component.extend({ @discourseComputed("tagRecord.id") href(tagRecordId) { - return Discourse.getURL("/tag/" + tagRecordId); + return getURL("/tag/" + tagRecordId); } }); diff --git a/app/assets/javascripts/discourse/app/components/edit-category-general.js b/app/assets/javascripts/discourse/app/components/edit-category-general.js index a2a477f6a1e..931e8923fb6 100644 --- a/app/assets/javascripts/discourse/app/components/edit-category-general.js +++ b/app/assets/javascripts/discourse/app/components/edit-category-general.js @@ -1,3 +1,4 @@ +import getURL from "discourse-common/lib/get-url"; import discourseComputed from "discourse-common/utils/decorators"; import { isEmpty } from "@ember/utils"; import { not } from "@ember/object/computed"; @@ -27,10 +28,10 @@ export default buildCategoryPanel("general", { }, canSelectParentCategory: not("category.isUncategorizedCategory"), - uncategorizedSiteSettingLink: Discourse.getURL( + uncategorizedSiteSettingLink: getURL( "/admin/site_settings/category/all_results?filter=allow_uncategorized_topics" ), - customizeTextContentLink: Discourse.getURL( + customizeTextContentLink: getURL( "/admin/customize/site_texts?q=uncategorized" ), diff --git a/app/assets/javascripts/discourse/app/components/global-notice.js b/app/assets/javascripts/discourse/app/components/global-notice.js index 15eb1bf3768..ced8c86bb25 100644 --- a/app/assets/javascripts/discourse/app/components/global-notice.js +++ b/app/assets/javascripts/discourse/app/components/global-notice.js @@ -1,3 +1,4 @@ +import getURL from "discourse-common/lib/get-url"; import I18n from "I18n"; import { bind, cancel } from "@ember/runloop"; import Component from "@ember/component"; @@ -105,7 +106,7 @@ export default Component.extend({ if (this.site.wizard_required) { const requiredText = I18n.t("wizard_required", { - url: Discourse.getURL("/wizard") + url: getURL("/wizard") }); notices.push(Notice.create({ text: requiredText, id: "alert-wizard" })); } diff --git a/app/assets/javascripts/discourse/app/components/google-search.js b/app/assets/javascripts/discourse/app/components/google-search.js index 43db648e81b..0054f2898b7 100644 --- a/app/assets/javascripts/discourse/app/components/google-search.js +++ b/app/assets/javascripts/discourse/app/components/google-search.js @@ -1,3 +1,4 @@ +import getURL from "discourse-common/lib/get-url"; import discourseComputed from "discourse-common/utils/decorators"; import { alias } from "@ember/object/computed"; import Component from "@ember/component"; @@ -10,6 +11,6 @@ export default Component.extend({ @discourseComputed siteUrl() { - return `${location.protocol}//${location.host}${Discourse.getURL("/")}`; + return `${location.protocol}//${location.host}${getURL("/")}`; } }); diff --git a/app/assets/javascripts/discourse/app/components/group-flair-inputs.js b/app/assets/javascripts/discourse/app/components/group-flair-inputs.js index b5ecb07bfc1..0e264cdad36 100644 --- a/app/assets/javascripts/discourse/app/components/group-flair-inputs.js +++ b/app/assets/javascripts/discourse/app/components/group-flair-inputs.js @@ -1,3 +1,4 @@ +import getURL from "discourse-common/lib/get-url"; import I18n from "I18n"; import discourseComputed from "discourse-common/utils/decorators"; import { debounce } from "@ember/runloop"; @@ -14,7 +15,7 @@ export default Component.extend({ @discourseComputed demoAvatarUrl() { - return Discourse.getURL("/images/avatar.png"); + return getURL("/images/avatar.png"); }, @discourseComputed("model.flair_type") @@ -105,7 +106,7 @@ export default Component.extend({ @action setFlairImage(upload) { this.model.setProperties({ - flair_url: Discourse.getURL(upload.url), + flair_url: getURL(upload.url), flair_upload_id: upload.id }); }, diff --git a/app/assets/javascripts/discourse/app/components/group-post.js b/app/assets/javascripts/discourse/app/components/group-post.js index 51bb53f0ead..cdbd44ba38e 100644 --- a/app/assets/javascripts/discourse/app/components/group-post.js +++ b/app/assets/javascripts/discourse/app/components/group-post.js @@ -1,9 +1,10 @@ +import getURL from "discourse-common/lib/get-url"; import discourseComputed from "discourse-common/utils/decorators"; import Component from "@ember/component"; export default Component.extend({ @discourseComputed("post.url") postUrl(url) { - return Discourse.getURL(url); + return getURL(url); } }); diff --git a/app/assets/javascripts/discourse/app/components/image-uploader.js b/app/assets/javascripts/discourse/app/components/image-uploader.js index 6db47602adc..48a8855889a 100644 --- a/app/assets/javascripts/discourse/app/components/image-uploader.js +++ b/app/assets/javascripts/discourse/app/components/image-uploader.js @@ -1,3 +1,4 @@ +import { getURLWithCDN } from "discourse-common/lib/get-url"; import discourseComputed from "discourse-common/utils/decorators"; import { isEmpty } from "@ember/utils"; import { next } from "@ember/runloop"; @@ -43,7 +44,7 @@ export default Component.extend(UploadMixin, { return "".htmlSafe(); } - return Discourse.getURLWithCDN(url); + return getURLWithCDN(url); }, @discourseComputed("imageCDNURL") diff --git a/app/assets/javascripts/discourse/app/components/related-messages.js b/app/assets/javascripts/discourse/app/components/related-messages.js index 1e1457db7d8..6381b3f9b85 100644 --- a/app/assets/javascripts/discourse/app/components/related-messages.js +++ b/app/assets/javascripts/discourse/app/components/related-messages.js @@ -1,3 +1,4 @@ +import getURL from "discourse-common/lib/get-url"; import discourseComputed from "discourse-common/utils/decorators"; import Component from "@ember/component"; @@ -23,7 +24,7 @@ export default Component.extend({ @discourseComputed searchLink() { - return Discourse.getURL( + return getURL( `/search?expanded=true&q=%40${this.targetUser.username}%20in%3Apersonal-direct` ); }, diff --git a/app/assets/javascripts/discourse/app/components/suggested-topics.js b/app/assets/javascripts/discourse/app/components/suggested-topics.js index e5c5a40f154..38ebaa1a5a8 100644 --- a/app/assets/javascripts/discourse/app/components/suggested-topics.js +++ b/app/assets/javascripts/discourse/app/components/suggested-topics.js @@ -1,3 +1,4 @@ +import getURL from "discourse-common/lib/get-url"; import I18n from "I18n"; import discourseComputed from "discourse-common/utils/decorators"; import { computed, get } from "@ember/object"; @@ -25,7 +26,7 @@ export default Component.extend({ } const opts = { - latestLink: `${I18n.t( + latestLink: `${I18n.t( "topic.view_latest_topics" )}` }; @@ -43,7 +44,7 @@ export default Component.extend({ } else { opts.catLink = '' + I18n.t("topic.browse_all_categories") + ""; diff --git a/app/assets/javascripts/discourse/app/components/user-card-contents.js b/app/assets/javascripts/discourse/app/components/user-card-contents.js index ee19f26d820..220cadc923d 100644 --- a/app/assets/javascripts/discourse/app/components/user-card-contents.js +++ b/app/assets/javascripts/discourse/app/components/user-card-contents.js @@ -1,3 +1,4 @@ +import { getURLWithCDN } from "discourse-common/lib/get-url"; import I18n from "I18n"; import { isEmpty } from "@ember/utils"; import { alias, gte, and, gt, not, or } from "@ember/object/computed"; @@ -153,7 +154,7 @@ export default Component.extend(CardContentsBase, CanCheckEmails, CleansUp, { } const url = this.get("user.card_background_upload_url"); - const bg = isEmpty(url) ? "" : `url(${Discourse.getURLWithCDN(url)})`; + const bg = isEmpty(url) ? "" : `url(${getURLWithCDN(url)})`; thisElem.style.backgroundImage = bg; }, diff --git a/app/assets/javascripts/discourse/app/controllers/bookmark.js b/app/assets/javascripts/discourse/app/controllers/bookmark.js index aa731cb62dc..05a4c26b530 100644 --- a/app/assets/javascripts/discourse/app/controllers/bookmark.js +++ b/app/assets/javascripts/discourse/app/controllers/bookmark.js @@ -270,11 +270,6 @@ export default Controller.extend(ModalFunctionality, { return this.nextMonth().format(I18n.t("dates.long_no_year")); }, - @discourseComputed() - basePath() { - return Discourse.BaseUri; - }, - @discourseComputed("userTimezone") userHasTimezoneSet(userTimezone) { return !_.isEmpty(userTimezone); diff --git a/app/assets/javascripts/discourse/app/controllers/composer.js b/app/assets/javascripts/discourse/app/controllers/composer.js index d4a5466da3e..3ca2b70f36d 100644 --- a/app/assets/javascripts/discourse/app/controllers/composer.js +++ b/app/assets/javascripts/discourse/app/controllers/composer.js @@ -1,3 +1,4 @@ +import getURL from "discourse-common/lib/get-url"; import I18n from "I18n"; import { isEmpty } from "@ember/utils"; import { and, or, alias, reads } from "@ember/object/computed"; @@ -561,7 +562,7 @@ export default Controller.extend({ ) { groups.forEach(group => { let body; - const groupLink = Discourse.getURL(`/g/${group.name}/members`); + const groupLink = getURL(`/g/${group.name}/members`); if (group.max_mentions < group.user_count) { body = I18n.t("composer.group_mentioned_limit", { diff --git a/app/assets/javascripts/discourse/app/controllers/create-account.js b/app/assets/javascripts/discourse/app/controllers/create-account.js index 75ec7b2a66f..dc8ee4dbcfe 100644 --- a/app/assets/javascripts/discourse/app/controllers/create-account.js +++ b/app/assets/javascripts/discourse/app/controllers/create-account.js @@ -1,3 +1,4 @@ +import getURL from "discourse-common/lib/get-url"; import I18n from "I18n"; import { A } from "@ember/array"; import { isEmpty } from "@ember/utils"; @@ -86,10 +87,9 @@ export default Controller.extend( @discourseComputed disclaimerHtml() { return I18n.t("create_account.disclaimer", { - tos_link: this.get("siteSettings.tos_url") || Discourse.getURL("/tos"), + tos_link: this.get("siteSettings.tos_url") || getURL("/tos"), privacy_link: - this.get("siteSettings.privacy_policy_url") || - Discourse.getURL("/privacy") + this.get("siteSettings.privacy_policy_url") || getURL("/privacy") }); }, diff --git a/app/assets/javascripts/discourse/app/controllers/email-login.js b/app/assets/javascripts/discourse/app/controllers/email-login.js index 40006185877..6802271fd93 100644 --- a/app/assets/javascripts/discourse/app/controllers/email-login.js +++ b/app/assets/javascripts/discourse/app/controllers/email-login.js @@ -1,3 +1,4 @@ +import getURL from "discourse-common/lib/get-url"; import discourseComputed from "discourse-common/utils/decorators"; import Controller from "@ember/controller"; import { SECOND_FACTOR_METHODS } from "discourse/models/user"; @@ -7,7 +8,7 @@ import { popupAjaxError } from "discourse/lib/ajax-error"; import { getWebauthnCredential } from "discourse/lib/webauthn"; export default Controller.extend({ - lockImageUrl: Discourse.getURL("/images/lock.svg"), + lockImageUrl: getURL("/images/lock.svg"), @discourseComputed("model") secondFactorRequired(model) { diff --git a/app/assets/javascripts/discourse/app/controllers/forgot-password.js b/app/assets/javascripts/discourse/app/controllers/forgot-password.js index 9821947e3b2..334367a370a 100644 --- a/app/assets/javascripts/discourse/app/controllers/forgot-password.js +++ b/app/assets/javascripts/discourse/app/controllers/forgot-password.js @@ -6,6 +6,7 @@ import { ajax } from "discourse/lib/ajax"; import ModalFunctionality from "discourse/mixins/modal-functionality"; import { escapeExpression } from "discourse/lib/utilities"; import { extractError } from "discourse/lib/ajax-error"; +import getURL from "discourse-common/lib/get-url"; export default Controller.extend(ModalFunctionality, { offerHelp: null, @@ -30,7 +31,7 @@ export default Controller.extend(ModalFunctionality, { help() { this.setProperties({ offerHelp: I18n.t("forgot_password.help", { - basePath: Discourse.BaseUri + basePath: getURL("/") }), helpSeen: true }); diff --git a/app/assets/javascripts/discourse/app/controllers/login.js b/app/assets/javascripts/discourse/app/controllers/login.js index 4bc124b0608..9edefd68ec1 100644 --- a/app/assets/javascripts/discourse/app/controllers/login.js +++ b/app/assets/javascripts/discourse/app/controllers/login.js @@ -1,3 +1,4 @@ +import getURL from "discourse-common/lib/get-url"; import I18n from "I18n"; import discourseComputed from "discourse-common/utils/decorators"; import { isEmpty } from "@ember/utils"; @@ -372,8 +373,8 @@ export default Controller.extend(ModalFunctionality, { // redirect client to the original URL $.removeCookie("destination_url"); window.location.href = destinationUrl; - } else if (window.location.pathname === Discourse.getURL("/login")) { - window.location = Discourse.getURL("/"); + } else if (window.location.pathname === getURL("/login")) { + window.location = getURL("/"); } else { window.location.reload(); } diff --git a/app/assets/javascripts/discourse/app/controllers/password-reset.js b/app/assets/javascripts/discourse/app/controllers/password-reset.js index 764396c21e9..e14de1c1bd9 100644 --- a/app/assets/javascripts/discourse/app/controllers/password-reset.js +++ b/app/assets/javascripts/discourse/app/controllers/password-reset.js @@ -1,3 +1,4 @@ +import getURL from "discourse-common/lib/get-url"; import I18n from "I18n"; import { alias, or, readOnly } from "@ember/object/computed"; import Controller from "@ember/controller"; @@ -41,10 +42,10 @@ export default Controller.extend(PasswordValidation, { @discourseComputed("redirectTo") redirectHref(redirectTo) { - return Discourse.getURL(redirectTo || "/"); + return getURL(redirectTo || "/"); }, - lockImageUrl: Discourse.getURL("/images/lock.svg"), + lockImageUrl: getURL("/images/lock.svg"), actions: { submit() { diff --git a/app/assets/javascripts/discourse/app/controllers/preferences/account.js b/app/assets/javascripts/discourse/app/controllers/preferences/account.js index 584440ed0c1..0a6f54c2800 100644 --- a/app/assets/javascripts/discourse/app/controllers/preferences/account.js +++ b/app/assets/javascripts/discourse/app/controllers/preferences/account.js @@ -1,3 +1,4 @@ +import getURL from "discourse-common/lib/get-url"; import I18n from "I18n"; import { not, or, gt } from "@ember/object/computed"; import Controller from "@ember/controller"; @@ -195,7 +196,7 @@ export default Controller.extend(CanCheckEmails, { () => { bootbox.alert( I18n.t("user.deleted_yourself"), - () => (window.location = Discourse.getURL("/")) + () => (window.location = getURL("/")) ); }, () => { diff --git a/app/assets/javascripts/discourse/app/helpers/category-link.js b/app/assets/javascripts/discourse/app/helpers/category-link.js index 9530c269825..ff63695293e 100644 --- a/app/assets/javascripts/discourse/app/helpers/category-link.js +++ b/app/assets/javascripts/discourse/app/helpers/category-link.js @@ -1,3 +1,4 @@ +import getURL from "discourse-common/lib/get-url"; import I18n from "I18n"; import { get } from "@ember/object"; import { registerUnbound } from "discourse-common/lib/helpers"; @@ -104,9 +105,7 @@ function defaultCategoryLinkRenderer(category, opts) { let restricted = get(category, "read_restricted"); let url = opts.url ? opts.url - : Discourse.getURL( - `/c/${Category.slugFor(category)}/${get(category, "id")}` - ); + : getURL(`/c/${Category.slugFor(category)}/${get(category, "id")}`); let href = opts.link === false ? "" : url; let tagName = opts.link === false || opts.link === "false" ? "span" : "a"; let extraClasses = opts.extraClasses ? " " + opts.extraClasses : ""; diff --git a/app/assets/javascripts/discourse/app/initializers/message-bus.js b/app/assets/javascripts/discourse/app/initializers/message-bus.js index 6825cd90fa2..3422b6c4059 100644 --- a/app/assets/javascripts/discourse/app/initializers/message-bus.js +++ b/app/assets/javascripts/discourse/app/initializers/message-bus.js @@ -1,3 +1,4 @@ +import getURL from "discourse-common/lib/get-url"; // Initialize the message bus to receive messages. import userPresent from "discourse/lib/user-presence"; import { handleLogoff } from "discourse/lib/ajax"; @@ -84,7 +85,7 @@ export default { return ajax(opts); }; - messageBus.baseUrl = Discourse.getURL("/"); + messageBus.baseUrl = getURL("/"); } if (user) { diff --git a/app/assets/javascripts/discourse/app/initializers/register-service-worker.js b/app/assets/javascripts/discourse/app/initializers/register-service-worker.js index fbfc4484deb..c22b7e98fff 100644 --- a/app/assets/javascripts/discourse/app/initializers/register-service-worker.js +++ b/app/assets/javascripts/discourse/app/initializers/register-service-worker.js @@ -1,3 +1,6 @@ +import { isAbsoluteURL } from "discourse-common/lib/get-url"; +import getURL from "discourse-common/lib/get-url"; + export default { name: "register-service-worker", @@ -30,7 +33,7 @@ export default { }); navigator.serviceWorker - .register(`${Discourse.BaseUri}/${Discourse.ServiceWorkerURL}`) + .register(`${getURL(Discourse.ServiceWorkerURL)}`) .catch(error => { // eslint-disable-next-line no-console console.info(`Failed to register Service Worker: ${error}`); @@ -46,7 +49,7 @@ export default { }, unregister(registration) { - if (registration.scope.startsWith(Discourse.BaseUrl)) { + if (isAbsoluteURL(registration.scope)) { registration.unregister(); } } diff --git a/app/assets/javascripts/discourse/app/lib/ajax.js b/app/assets/javascripts/discourse/app/lib/ajax.js index 1eadcda6260..da1af132067 100644 --- a/app/assets/javascripts/discourse/app/lib/ajax.js +++ b/app/assets/javascripts/discourse/app/lib/ajax.js @@ -1,3 +1,4 @@ +import getURL from "discourse-common/lib/get-url"; import I18n from "I18n"; import { run } from "@ember/runloop"; import userPresent from "discourse/lib/user-presence"; @@ -159,7 +160,7 @@ export function ajax() { args.cache = true; // Disable JQuery cache busting param, which was created to deal with IE8 } - ajaxObj = $.ajax(Discourse.getURL(url), args); + ajaxObj = $.ajax(getURL(url), args); } let promise; @@ -169,7 +170,7 @@ export function ajax() { if ( args.type && args.type.toUpperCase() !== "GET" && - url !== Discourse.getURL("/clicks/track") && + url !== getURL("/clicks/track") && !Session.currentProp("csrfToken") ) { promise = new Promise((resolve, reject) => { diff --git a/app/assets/javascripts/discourse/app/lib/category-tag-search.js b/app/assets/javascripts/discourse/app/lib/category-tag-search.js index 9a370f0e21e..83ad3e96ab4 100644 --- a/app/assets/javascripts/discourse/app/lib/category-tag-search.js +++ b/app/assets/javascripts/discourse/app/lib/category-tag-search.js @@ -1,3 +1,4 @@ +import getURL from "discourse-common/lib/get-url"; import discourseDebounce from "discourse/lib/debounce"; import { CANCELLED_STATUS } from "discourse/lib/autocomplete"; import Category from "discourse/models/category"; @@ -27,7 +28,7 @@ function searchTags(term, categories, limit) { ); const debouncedSearch = discourseDebounce((q, cats, resultFunc) => { - oldSearch = $.ajax(Discourse.getURL("/tags/filter/search"), { + oldSearch = $.ajax(getURL("/tags/filter/search"), { type: "GET", cache: true, data: { limit: limit, q } diff --git a/app/assets/javascripts/discourse/app/lib/click-track.js b/app/assets/javascripts/discourse/app/lib/click-track.js index d34e33363a6..d3a37441f77 100644 --- a/app/assets/javascripts/discourse/app/lib/click-track.js +++ b/app/assets/javascripts/discourse/app/lib/click-track.js @@ -1,3 +1,4 @@ +import getURL from "discourse-common/lib/get-url"; import I18n from "I18n"; import { later } from "@ember/runloop"; import { ajax } from "discourse/lib/ajax"; @@ -106,9 +107,9 @@ export default { data.append("url", href); data.append("post_id", postId); data.append("topic_id", topicId); - navigator.sendBeacon(Discourse.getURL("/clicks/track"), data); + navigator.sendBeacon(getURL("/clicks/track"), data); } else { - trackPromise = ajax(Discourse.getURL("/clicks/track"), { + trackPromise = ajax(getURL("/clicks/track"), { type: "POST", data: { url: href, diff --git a/app/assets/javascripts/discourse/app/lib/computed.js b/app/assets/javascripts/discourse/app/lib/computed.js index 68eefd11da4..b3a4eb2e2a1 100644 --- a/app/assets/javascripts/discourse/app/lib/computed.js +++ b/app/assets/javascripts/discourse/app/lib/computed.js @@ -1,3 +1,4 @@ +import getURL from "discourse-common/lib/get-url"; import I18n from "I18n"; import { computed } from "@ember/object"; import { htmlSafe as htmlSafeTemplateHelper } from "@ember/template"; @@ -126,7 +127,7 @@ export function fmt(...args) { export function url(...args) { const format = args.pop(); return computed(...args, function() { - return Discourse.getURL(addonFmt(format, ...args.map(a => this.get(a)))); + return getURL(addonFmt(format, ...args.map(a => this.get(a)))); }); } diff --git a/app/assets/javascripts/discourse/app/lib/discourse-location.js b/app/assets/javascripts/discourse/app/lib/discourse-location.js index 20e8ad8c5d0..2c0466c7390 100644 --- a/app/assets/javascripts/discourse/app/lib/discourse-location.js +++ b/app/assets/javascripts/discourse/app/lib/discourse-location.js @@ -1,6 +1,7 @@ import EmberObject from "@ember/object"; import { defaultHomepage } from "discourse/lib/utilities"; import { guidFor } from "@ember/object/internals"; +import { withoutPrefix } from "discourse-common/lib/get-url"; let popstateFired = false; const supportsHistoryState = window.history && "state" in window.history; const popstateCallbacks = []; @@ -62,10 +63,7 @@ const DiscourseLocation = EmberObject.extend({ @method getURL */ getURL() { - let url = this.location.pathname; - - url = url.replace(new RegExp(`^${Discourse.BaseUri}`), ""); - + let url = withoutPrefix(this.location.pathname); const search = this.location.search || ""; url += search; return url; diff --git a/app/assets/javascripts/discourse/app/lib/keyboard-shortcuts.js b/app/assets/javascripts/discourse/app/lib/keyboard-shortcuts.js index 985d9fc1af7..29cfaaf9d23 100644 --- a/app/assets/javascripts/discourse/app/lib/keyboard-shortcuts.js +++ b/app/assets/javascripts/discourse/app/lib/keyboard-shortcuts.js @@ -471,9 +471,7 @@ export default { }, _bindToPath(path, key) { - this.keyTrapper.bind(key, () => - DiscourseURL.routeTo(Discourse.BaseUri + path) - ); + this.keyTrapper.bind(key, () => DiscourseURL.routeTo(path)); }, _bindToClick(selector, binding) { diff --git a/app/assets/javascripts/discourse/app/lib/link-mentions.js b/app/assets/javascripts/discourse/app/lib/link-mentions.js index 02872edaecf..700412a2239 100644 --- a/app/assets/javascripts/discourse/app/lib/link-mentions.js +++ b/app/assets/javascripts/discourse/app/lib/link-mentions.js @@ -1,3 +1,4 @@ +import getURL from "discourse-common/lib/get-url"; import { schedule } from "@ember/runloop"; import { ajax } from "discourse/lib/ajax"; import { userPath } from "discourse/lib/url"; @@ -15,7 +16,7 @@ function replaceSpan($e, username, opts) { extraClass = "notify"; } $e.replaceWith( - `@${username}` ); } else { diff --git a/app/assets/javascripts/discourse/app/lib/load-script.js b/app/assets/javascripts/discourse/app/lib/load-script.js index 7c8dfd851f3..52babb1952f 100644 --- a/app/assets/javascripts/discourse/app/lib/load-script.js +++ b/app/assets/javascripts/discourse/app/lib/load-script.js @@ -1,3 +1,4 @@ +import { default as getURL, getURLWithCDN } from "discourse-common/lib/get-url"; import { run } from "@ember/runloop"; import { ajax } from "discourse/lib/ajax"; import { Promise } from "rsvp"; @@ -51,9 +52,7 @@ export default function loadScript(url, opts) { // Scripts should always load from CDN // CSS is type text, to accept it from a CDN we would need to handle CORS - const fullUrl = opts.css - ? Discourse.getURL(url) - : Discourse.getURLWithCDN(url); + const fullUrl = opts.css ? getURL(url) : getURLWithCDN(url); $("script").each((i, tag) => { const src = tag.getAttribute("src"); diff --git a/app/assets/javascripts/discourse/app/lib/logout.js b/app/assets/javascripts/discourse/app/lib/logout.js index 23160f8e449..2d5bf9966b1 100644 --- a/app/assets/javascripts/discourse/app/lib/logout.js +++ b/app/assets/javascripts/discourse/app/lib/logout.js @@ -1,3 +1,4 @@ +import getURL from "discourse-common/lib/get-url"; import { isEmpty } from "@ember/utils"; import { findAll } from "discourse/models/login-method"; @@ -23,9 +24,9 @@ export default function logout(siteSettings, keyValueStore) { if (siteSettings.login_required && (sso || oneAuthenticator)) { // In this situation visiting most URLs will start the auth process again // Go to the `/login` page to avoid an immediate redirect - window.location.href = Discourse.getURL("/login"); + window.location.href = getURL("/login"); return; } - window.location.href = Discourse.getURL("/"); + window.location.href = getURL("/"); } diff --git a/app/assets/javascripts/discourse/app/lib/page-tracker.js b/app/assets/javascripts/discourse/app/lib/page-tracker.js index 4acbdc4ea36..3246f14ee81 100644 --- a/app/assets/javascripts/discourse/app/lib/page-tracker.js +++ b/app/assets/javascripts/discourse/app/lib/page-tracker.js @@ -1,3 +1,4 @@ +import getURL from "discourse-common/lib/get-url"; import { next } from "@ember/runloop"; let _started = false; let cache = {}; @@ -28,7 +29,7 @@ export function startPageTracking(router, appEvents) { transition.urlMethod === "replace" && transition.queryParamsOnly; router.send("refreshTitle"); - const url = Discourse.getURL(router.get("url")); + const url = getURL(router.get("url")); // Refreshing the title is debounced, so we need to trigger this in the // next runloop to have the correct title. diff --git a/app/assets/javascripts/discourse/app/lib/render-tag.js b/app/assets/javascripts/discourse/app/lib/render-tag.js index f1882a386eb..da11af4669c 100644 --- a/app/assets/javascripts/discourse/app/lib/render-tag.js +++ b/app/assets/javascripts/discourse/app/lib/render-tag.js @@ -1,3 +1,4 @@ +import getURL from "discourse-common/lib/get-url"; import User from "discourse/models/user"; import { escapeExpression } from "discourse/lib/utilities"; @@ -24,7 +25,7 @@ export function defaultRenderTag(tag, params) { path = `/tag/${tag}`; } } - const href = path ? ` href='${Discourse.getURL(path)}' ` : ""; + const href = path ? ` href='${getURL(path)}' ` : ""; if (Discourse.SiteSettings.tag_style || params.style) { classes.push(params.style || Discourse.SiteSettings.tag_style); diff --git a/app/assets/javascripts/discourse/app/lib/search.js b/app/assets/javascripts/discourse/app/lib/search.js index 07eb6ad7bf2..d0974eba057 100644 --- a/app/assets/javascripts/discourse/app/lib/search.js +++ b/app/assets/javascripts/discourse/app/lib/search.js @@ -1,3 +1,4 @@ +import getURL from "discourse-common/lib/get-url"; import I18n from "I18n"; import { isEmpty } from "@ember/utils"; import EmberObject from "@ember/object"; @@ -67,7 +68,7 @@ export function translateResults(results, opts) { flairBgColor, fullName, name, - url: Discourse.getURL(`/g/${name}`) + url: getURL(`/g/${name}`) }; }) .compact(); @@ -77,7 +78,7 @@ export function translateResults(results, opts) { const tagName = escapeExpression(tag.name); return EmberObject.create({ id: tagName, - url: Discourse.getURL("/tag/" + tagName) + url: getURL("/tag/" + tagName) }); }) .compact(); diff --git a/app/assets/javascripts/discourse/app/lib/text.js b/app/assets/javascripts/discourse/app/lib/text.js index 94d33b18d57..afca9415f71 100644 --- a/app/assets/javascripts/discourse/app/lib/text.js +++ b/app/assets/javascripts/discourse/app/lib/text.js @@ -1,3 +1,4 @@ +import { getURLWithCDN } from "discourse-common/lib/get-url"; import PrettyText, { buildOptions } from "pretty-text/pretty-text"; import { performEmojiUnescape, buildEmojiUrl } from "pretty-text/emoji"; import WhiteLister from "pretty-text/white-lister"; @@ -7,8 +8,6 @@ import { formatUsername } from "discourse/lib/utilities"; import { Promise } from "rsvp"; import { htmlSafe } from "@ember/template"; -const getURLWithCDN = url => Discourse.getURLWithCDN(url); - function getOpts(opts) { const siteSettings = Discourse.__container__.lookup("site-settings:main"), site = Discourse.__container__.lookup("site:main"); diff --git a/app/assets/javascripts/discourse/app/lib/url.js b/app/assets/javascripts/discourse/app/lib/url.js index 4086ca7b623..f357e4978ae 100644 --- a/app/assets/javascripts/discourse/app/lib/url.js +++ b/app/assets/javascripts/discourse/app/lib/url.js @@ -5,6 +5,7 @@ import offsetCalculator from "discourse/lib/offset-calculator"; import LockOn from "discourse/lib/lock-on"; import { defaultHomepage } from "discourse/lib/utilities"; import User from "discourse/models/user"; +import { default as getURL, withoutPrefix } from "discourse-common/lib/get-url"; const rewrites = []; const TOPIC_REGEXP = /\/t\/([^\/]+)\/(\d+)\/?(\d+)?/; @@ -55,11 +56,11 @@ export function clearRewrites() { } export function userPath(subPath) { - return Discourse.getURL(subPath ? `/u/${subPath}` : "/u"); + return getURL(subPath ? `/u/${subPath}` : "/u"); } export function groupPath(subPath) { - return Discourse.getURL(subPath ? `/g/${subPath}` : "/g"); + return getURL(subPath ? `/g/${subPath}` : "/g"); } let _jumpScheduled = false; @@ -210,11 +211,10 @@ const DiscourseURL = EmberObject.extend({ } if (Discourse.get("requiresRefresh")) { - return redirectTo(Discourse.getURL(path)); + return redirectTo(getURL(path)); } const pathname = path.replace(/(https?\:)?\/\/[^\/]+/, ""); - const baseUri = Discourse.BaseUri; if (!DiscourseURL.isInternal(path)) { return redirectTo(path); @@ -241,7 +241,7 @@ const DiscourseURL = EmberObject.extend({ path = path.replace(/(https?\:)?\/\/[^\/]+/, ""); // Rewrite /my/* urls - let myPath = `${baseUri}/my/`; + let myPath = getURL("/my"); if (path.indexOf(myPath) === 0) { const currentUser = User.current(); if (currentUser) { @@ -256,11 +256,7 @@ const DiscourseURL = EmberObject.extend({ // handle prefixes if (path.indexOf("/") === 0) { - const rootURL = (baseUri === undefined ? "/" : baseUri).replace( - /\/$/, - "" - ); - path = path.replace(rootURL, ""); + path = withoutPrefix(path); } path = rewritePath(path); @@ -293,7 +289,7 @@ const DiscourseURL = EmberObject.extend({ }, routeToUrl(url, opts = {}) { - this.routeTo(Discourse.getURL(url), opts); + this.routeTo(getURL(url), opts); }, rewrite(regexp, replacement, opts) { @@ -301,7 +297,7 @@ const DiscourseURL = EmberObject.extend({ }, redirectTo(url) { - window.location = Discourse.getURL(url); + window.location = getURL(url); }, /** @@ -420,10 +416,8 @@ const DiscourseURL = EmberObject.extend({ // This has been extracted so it can be tested. origin() { - return ( - window.location.origin + - (Discourse.BaseUri === "/" ? "" : Discourse.BaseUri) - ); + let prefix = getURL("/"); + return window.location.origin + (prefix === "/" ? "" : prefix); }, // TODO: These container calls can be replaced eventually if we migrate this to a service diff --git a/app/assets/javascripts/discourse/app/lib/utilities.js b/app/assets/javascripts/discourse/app/lib/utilities.js index 688aa53929c..92fa3441344 100644 --- a/app/assets/javascripts/discourse/app/lib/utilities.js +++ b/app/assets/javascripts/discourse/app/lib/utilities.js @@ -2,6 +2,7 @@ import I18n from "I18n"; import { escape } from "pretty-text/sanitizer"; import toMarkdown from "discourse/lib/to-markdown"; import Handlebars from "handlebars"; +import { default as getURL, getURLWithCDN } from "discourse-common/lib/get-url"; const homepageSelector = "meta[name=discourse_current_homepage]"; @@ -55,18 +56,15 @@ export function getRawSize(size) { return size * Math.min(3, Math.max(1, Math.round(pixelRatio))); } -const getURLWithCDN = url => Discourse.getURLWithCDN(url); - -export function avatarImg(options, getURL) { - getURL = getURL || getURLWithCDN; - +export function avatarImg(options, customGetURL) { const size = translateSize(options.size); - const url = avatarUrl(options.avatarTemplate, size); + let path = avatarUrl(options.avatarTemplate, size); // We won't render an invalid url - if (!url || url.length === 0) { + if (!path || path.length === 0) { return ""; } + path = (customGetURL || getURLWithCDN)(path); const classes = "avatar" + (options.extraClasses ? " " + options.extraClasses : ""); @@ -77,19 +75,7 @@ export function avatarImg(options, getURL) { title = ` title='${escaped}' aria-label='${escaped}'`; } - return ( - "" - ); + return ``; } export function tinyAvatar(avatarTemplate, options) { @@ -99,7 +85,7 @@ export function tinyAvatar(avatarTemplate, options) { } export function postUrl(slug, topicId, postNumber) { - var url = Discourse.getURL("/t/"); + var url = getURL("/t/"); if (slug) { url += slug + "/"; } else { @@ -430,7 +416,7 @@ function reportToLogster(name, error) { stacktrace: error.stack }; - Ember.$.ajax(`${Discourse.BaseUri}/logs/report_js_error`, { + Ember.$.ajax(getURL("/logs/report_js_error"), { data, type: "POST", cache: false @@ -447,7 +433,7 @@ export function rescueThemeError(name, error, api) { return; } - const path = `${Discourse.BaseUri}/admin/customize/themes`; + const path = getURL(`/admin/customize/themes`); const message = I18n.t("themes.broken_theme_alert", { theme: name, path: `${path}` diff --git a/app/assets/javascripts/discourse/app/mapping-router.js b/app/assets/javascripts/discourse/app/mapping-router.js index 99935ddc32e..ca6728a1fbf 100644 --- a/app/assets/javascripts/discourse/app/mapping-router.js +++ b/app/assets/javascripts/discourse/app/mapping-router.js @@ -3,11 +3,9 @@ import { defaultHomepage } from "discourse/lib/utilities"; import { rewritePath } from "discourse/lib/url"; import Site from "discourse/models/site"; import { isTesting } from "discourse-common/config/environment"; - -const rootURL = Discourse.BaseUri; +import getURL from "discourse-common/lib/get-url"; const BareRouter = EmberRouter.extend({ - rootURL, location: isTesting() ? "none" : "discourse-location", handleURL(url) { @@ -136,10 +134,10 @@ export function mapRoutes() { } }); - return BareRouter.extend().map(function() { + return BareRouter.extend({ + rootURL: getURL("/") + }).map(function() { tree.mapRoutes(this); this.route("unknown", { path: "*path" }); }); } - -export default BareRouter; diff --git a/app/assets/javascripts/discourse/app/models/badge.js b/app/assets/javascripts/discourse/app/models/badge.js index 5b9e46cef9c..3ea5131ae1c 100644 --- a/app/assets/javascripts/discourse/app/models/badge.js +++ b/app/assets/javascripts/discourse/app/models/badge.js @@ -1,3 +1,4 @@ +import getURL from "discourse-common/lib/get-url"; import discourseComputed from "discourse-common/utils/decorators"; import { none } from "@ember/object/computed"; import EmberObject from "@ember/object"; @@ -11,7 +12,7 @@ const Badge = RestModel.extend({ @discourseComputed url() { - return Discourse.getURL(`/badges/${this.id}/${this.slug}`); + return getURL(`/badges/${this.id}/${this.slug}`); }, updateFromJson(json) { diff --git a/app/assets/javascripts/discourse/app/models/bookmark.js b/app/assets/javascripts/discourse/app/models/bookmark.js index a55fb80acec..c7a3249144f 100644 --- a/app/assets/javascripts/discourse/app/models/bookmark.js +++ b/app/assets/javascripts/discourse/app/models/bookmark.js @@ -1,3 +1,4 @@ +import getURL from "discourse-common/lib/get-url"; import I18n from "I18n"; import Category from "discourse/models/category"; import User from "discourse/models/user"; @@ -19,7 +20,7 @@ const Bookmark = RestModel.extend({ @computed get url() { - return Discourse.getURL(`/bookmarks/${this.id}`); + return getURL(`/bookmarks/${this.id}`); }, destroy() { @@ -37,7 +38,7 @@ const Bookmark = RestModel.extend({ // Helper to build a Url with a post number urlForPostNumber(postNumber) { - let url = Discourse.getURL(`/t/${this.topic_id}`); + let url = getURL(`/t/${this.topic_id}`); if (postNumber > 0) { url += `/${postNumber}`; } diff --git a/app/assets/javascripts/discourse/app/models/category.js b/app/assets/javascripts/discourse/app/models/category.js index 78802cba87d..2c0442a4703 100644 --- a/app/assets/javascripts/discourse/app/models/category.js +++ b/app/assets/javascripts/discourse/app/models/category.js @@ -1,3 +1,4 @@ +import getURL from "discourse-common/lib/get-url"; import discourseComputed from "discourse-common/utils/decorators"; import { get } from "@ember/object"; import { ajax } from "discourse/lib/ajax"; @@ -96,7 +97,7 @@ const Category = RestModel.extend({ @discourseComputed("name") url() { - return Discourse.getURL(`/c/${Category.slugFor(this)}/${this.id}`); + return getURL(`/c/${Category.slugFor(this)}/${this.id}`); }, @discourseComputed diff --git a/app/assets/javascripts/discourse/app/models/login-method.js b/app/assets/javascripts/discourse/app/models/login-method.js index 0f2f1a46c03..0ef480e5ab0 100644 --- a/app/assets/javascripts/discourse/app/models/login-method.js +++ b/app/assets/javascripts/discourse/app/models/login-method.js @@ -1,3 +1,4 @@ +import getURL from "discourse-common/lib/get-url"; import I18n from "I18n"; import discourseComputed from "discourse-common/utils/decorators"; import EmberObject from "@ember/object"; @@ -33,7 +34,7 @@ const LoginMethod = EmberObject.extend({ return Promise.resolve(); } - let authUrl = Discourse.getURL(`/auth/${this.name}`); + let authUrl = getURL(`/auth/${this.name}`); if (reconnect) { params["reconnect"] = true; diff --git a/app/assets/javascripts/discourse/app/models/nav-item.js b/app/assets/javascripts/discourse/app/models/nav-item.js index 955e536e1eb..bf41bdde661 100644 --- a/app/assets/javascripts/discourse/app/models/nav-item.js +++ b/app/assets/javascripts/discourse/app/models/nav-item.js @@ -1,3 +1,4 @@ +import getURL from "discourse-common/lib/get-url"; import I18n from "I18n"; import discourseComputed from "discourse-common/utils/decorators"; import { emojiUnescape } from "discourse/lib/text"; @@ -105,7 +106,7 @@ NavItem.reopenClass({ extraNavItemDescriptors: [], pathFor(filterType, context) { - let path = Discourse.getURL(""); + let path = getURL(""); let includesCategoryContext = false; let includesTagContext = false; diff --git a/app/assets/javascripts/discourse/app/models/published-page.js b/app/assets/javascripts/discourse/app/models/published-page.js index 7f0c12ddf56..91152fa04cb 100644 --- a/app/assets/javascripts/discourse/app/models/published-page.js +++ b/app/assets/javascripts/discourse/app/models/published-page.js @@ -1,8 +1,9 @@ import RestModel from "discourse/models/rest"; import { computed } from "@ember/object"; +import { getAbsoluteURL } from "discourse-common/lib/get-url"; export default RestModel.extend({ url: computed("slug", function() { - return `${Discourse.BaseUrl}/pub/${this.slug}`; + return getAbsoluteURL(`/pub/${this.slug}`); }) }); diff --git a/app/assets/javascripts/discourse/app/models/topic-details.js b/app/assets/javascripts/discourse/app/models/topic-details.js index d8d5ea0036f..514db4d9f4d 100644 --- a/app/assets/javascripts/discourse/app/models/topic-details.js +++ b/app/assets/javascripts/discourse/app/models/topic-details.js @@ -3,6 +3,8 @@ import discourseComputed from "discourse-common/utils/decorators"; import EmberObject from "@ember/object"; import { ajax } from "discourse/lib/ajax"; import User from "discourse/models/user"; +import getURL from "discourse-common/lib/get-url"; + /** A model representing a Topic's details that aren't always present, such as a list of participants. When showing topics in lists and such this information should not be required. @@ -56,7 +58,7 @@ const TopicDetails = RestModel.extend({ } else { return I18n.t(localeString, { username: User.currentProp("username_lower"), - basePath: Discourse.BaseUri + basePath: getURL("/") }); } }, diff --git a/app/assets/javascripts/discourse/app/models/topic-list.js b/app/assets/javascripts/discourse/app/models/topic-list.js index 489c926de30..16b2b67c6b1 100644 --- a/app/assets/javascripts/discourse/app/models/topic-list.js +++ b/app/assets/javascripts/discourse/app/models/topic-list.js @@ -1,3 +1,4 @@ +import getURL from "discourse-common/lib/get-url"; import { notEmpty } from "@ember/object/computed"; import EmberObject from "@ember/object"; import { ajax } from "discourse/lib/ajax"; @@ -124,9 +125,9 @@ const TopicList = RestModel.extend({ this.topics.filter(topic => topic_ids.indexOf(topic.id) >= 0) ); - const url = `${Discourse.getURL("/")}${ - this.filter - }.json?topic_ids=${topic_ids.join(",")}`; + const url = `${getURL("/")}${this.filter}.json?topic_ids=${topic_ids.join( + "," + )}`; return ajax({ url, data: this.params }).then(result => { let i = 0; diff --git a/app/assets/javascripts/discourse/app/models/topic.js b/app/assets/javascripts/discourse/app/models/topic.js index af4b87fbe27..4f5305fec63 100644 --- a/app/assets/javascripts/discourse/app/models/topic.js +++ b/app/assets/javascripts/discourse/app/models/topic.js @@ -1,3 +1,4 @@ +import getURL from "discourse-common/lib/get-url"; import I18n from "I18n"; import EmberObject from "@ember/object"; import { not, notEmpty, equal, and, or } from "@ember/object/computed"; @@ -25,7 +26,7 @@ import User from "discourse/models/user"; export function loadTopicView(topic, args) { const data = _.merge({}, args); - const url = `${Discourse.getURL("/t/")}${topic.id}`; + const url = `${getURL("/t/")}${topic.id}`; const jsonUrl = (data.nearPost ? `${url}/${data.nearPost}` : url) + ".json"; delete data.nearPost; @@ -259,7 +260,7 @@ const Topic = RestModel.extend({ if (slug.trim().length === 0) { slug = "topic"; } - return `${Discourse.getURL("/t/")}${slug}/${id}`; + return `${getURL("/t/")}${slug}/${id}`; }, // Helper to build a Url with a post number @@ -739,7 +740,7 @@ Topic.reopenClass({ // Load a topic, but accepts a set of filters find(topicId, opts) { - let url = Discourse.getURL("/t/") + topicId; + let url = getURL("/t/") + topicId; if (opts.nearPost) { url += `/${opts.nearPost}`; } diff --git a/app/assets/javascripts/discourse/app/models/user.js b/app/assets/javascripts/discourse/app/models/user.js index 6e287ccf72f..a6356182f33 100644 --- a/app/assets/javascripts/discourse/app/models/user.js +++ b/app/assets/javascripts/discourse/app/models/user.js @@ -1,3 +1,5 @@ +import { getURLWithCDN } from "discourse-common/lib/get-url"; +import getURL from "discourse-common/lib/get-url"; import I18n from "I18n"; import { A } from "@ember/array"; import { isEmpty } from "@ember/utils"; @@ -109,11 +111,7 @@ const User = RestModel.extend({ if (isEmpty(bgUrl) || !Discourse.SiteSettings.allow_profile_backgrounds) { return "".htmlSafe(); } - return ( - "background-image: url(" + - Discourse.getURLWithCDN(bgUrl) + - ")" - ).htmlSafe(); + return ("background-image: url(" + getURLWithCDN(bgUrl) + ")").htmlSafe(); }, @discourseComputed() @@ -183,22 +181,22 @@ const User = RestModel.extend({ @discourseComputed() mutedTopicsPath() { return defaultHomepage() === "latest" - ? Discourse.getURL("/?state=muted") - : Discourse.getURL("/latest?state=muted"); + ? getURL("/?state=muted") + : getURL("/latest?state=muted"); }, @discourseComputed() watchingTopicsPath() { return defaultHomepage() === "latest" - ? Discourse.getURL("/?state=watching") - : Discourse.getURL("/latest?state=watching"); + ? getURL("/?state=watching") + : getURL("/latest?state=watching"); }, @discourseComputed() trackingTopicsPath() { return defaultHomepage() === "latest" - ? Discourse.getURL("/?state=tracking") - : Discourse.getURL("/latest?state=tracking"); + ? getURL("/?state=tracking") + : getURL("/latest?state=tracking"); }, @discourseComputed("username") diff --git a/app/assets/javascripts/discourse/app/pre-initializers/discourse-bootstrap.js b/app/assets/javascripts/discourse/app/pre-initializers/discourse-bootstrap.js index 29570b5db2f..d8eb01dadc6 100644 --- a/app/assets/javascripts/discourse/app/pre-initializers/discourse-bootstrap.js +++ b/app/assets/javascripts/discourse/app/pre-initializers/discourse-bootstrap.js @@ -7,6 +7,8 @@ import { isTesting, isProduction } from "discourse-common/config/environment"; +import { setupURL, setupS3CDN } from "discourse-common/lib/get-url"; +import deprecated from "discourse-common/lib/deprecated"; export default { name: "discourse-bootstrap", @@ -35,8 +37,28 @@ export default { } app.CDN = setupData.cdn; - app.BaseUrl = setupData.baseUrl; - app.BaseUri = setupData.baseUri; + + let baseUrl = setupData.baseUrl; + Object.defineProperty(app, "BaseUrl", { + get() { + deprecated(`use "get-url" helpers instead of Discourse.BaseUrl`, { + since: "2.5", + dropFrom: "2.6" + }); + return baseUrl; + } + }); + let baseUri = setupData.baseUri; + Object.defineProperty(app, "BaseUri", { + get() { + deprecated(`use "get-url" helpers instead of Discourse.BaseUri`, { + since: "2.5", + dropFrom: "2.6" + }); + return baseUri; + } + }); + setupURL(setupData.cdn, baseUrl, setupData.baseUri); setEnvironment(setupData.environment); app.SiteSettings = PreloadStore.get("siteSettings"); app.ThemeSettings = PreloadStore.get("themeSettings"); @@ -69,6 +91,7 @@ export default { if (setupData.s3BaseUrl) { app.S3CDN = setupData.s3Cdn; app.S3BaseUrl = setupData.s3BaseUrl; + setupS3CDN(setupData.s3BaseUrl, setupData.s3Cdn); } RSVP.configure("onerror", function(e) { diff --git a/app/assets/javascripts/discourse/app/routes/application.js b/app/assets/javascripts/discourse/app/routes/application.js index b30dffebf81..cd9c6dd4a0b 100644 --- a/app/assets/javascripts/discourse/app/routes/application.js +++ b/app/assets/javascripts/discourse/app/routes/application.js @@ -1,3 +1,4 @@ +import getURL from "discourse-common/lib/get-url"; import I18n from "I18n"; import { once } from "@ember/runloop"; import DiscourseRoute from "discourse/routes/discourse"; @@ -46,8 +47,8 @@ const ApplicationRoute = DiscourseRoute.extend(OpenComposer, { _collectTitleTokens(tokens) { tokens.push(this.siteTitle); if ( - (window.location.pathname === Discourse.getURL("/") || - window.location.pathname === Discourse.getURL("/login")) && + (window.location.pathname === getURL("/") || + window.location.pathname === getURL("/login")) && this.shortSiteDescription !== "" ) { tokens.push(this.shortSiteDescription); @@ -250,9 +251,7 @@ const ApplicationRoute = DiscourseRoute.extend(OpenComposer, { handleShowLogin() { if (this.siteSettings.enable_sso) { const returnPath = encodeURIComponent(window.location.pathname); - window.location = Discourse.getURL( - "/session/sso?return_path=" + returnPath - ); + window.location = getURL("/session/sso?return_path=" + returnPath); } else { this._autoLogin("login", "login-modal", () => this.controllerFor("login").resetForm() @@ -263,9 +262,7 @@ const ApplicationRoute = DiscourseRoute.extend(OpenComposer, { handleShowCreateAccount() { if (this.siteSettings.enable_sso) { const returnPath = encodeURIComponent(window.location.pathname); - window.location = Discourse.getURL( - "/session/sso?return_path=" + returnPath - ); + window.location = getURL("/session/sso?return_path=" + returnPath); } else { this._autoLogin("createAccount", "create-account"); } diff --git a/app/assets/javascripts/discourse/app/services/logs-notice.js b/app/assets/javascripts/discourse/app/services/logs-notice.js index c84dadb944b..5faaaa2805e 100644 --- a/app/assets/javascripts/discourse/app/services/logs-notice.js +++ b/app/assets/javascripts/discourse/app/services/logs-notice.js @@ -1,3 +1,4 @@ +import getURL from "discourse-common/lib/get-url"; import I18n from "I18n"; import { isEmpty } from "@ember/utils"; import EmberObject from "@ember/object"; @@ -42,7 +43,7 @@ const LogsNotice = EmberObject.extend({ ), rate, limit: siteSettingLimit, - url: Discourse.getURL("/logs") + url: getURL("/logs") }) ); }); diff --git a/app/assets/javascripts/discourse/app/templates/modal/bookmark.hbs b/app/assets/javascripts/discourse/app/templates/modal/bookmark.hbs index 5dc82257676..be9a93dbfa1 100644 --- a/app/assets/javascripts/discourse/app/templates/modal/bookmark.hbs +++ b/app/assets/javascripts/discourse/app/templates/modal/bookmark.hbs @@ -96,7 +96,7 @@ {{/tap-tile-grid}} {{else}} -
{{html-safe (i18n "bookmarks.no_timezone" basePath=basePath)}}
+
{{html-safe (i18n "bookmarks.no_timezone" basePath=(get-url "/"))}}
{{/if}} diff --git a/app/assets/javascripts/discourse/app/widgets/actions-summary.js b/app/assets/javascripts/discourse/app/widgets/actions-summary.js index 25e00358971..9e15f6d5233 100644 --- a/app/assets/javascripts/discourse/app/widgets/actions-summary.js +++ b/app/assets/javascripts/discourse/app/widgets/actions-summary.js @@ -1,3 +1,4 @@ +import getURL from "discourse-common/lib/get-url"; import I18n from "I18n"; import { createWidget } from "discourse/widgets/widget"; import { avatarFor } from "discourse/widgets/post"; @@ -48,7 +49,7 @@ createWidget("small-user-list", { if (postUrl) { description = h( "a", - { attributes: { href: Discourse.getURL(postUrl) } }, + { attributes: { href: getURL(postUrl) } }, description ); } diff --git a/app/assets/javascripts/discourse/app/widgets/default-notification-item.js b/app/assets/javascripts/discourse/app/widgets/default-notification-item.js index e44a35d3419..6840c4d3476 100644 --- a/app/assets/javascripts/discourse/app/widgets/default-notification-item.js +++ b/app/assets/javascripts/discourse/app/widgets/default-notification-item.js @@ -15,6 +15,7 @@ import { setTransientHeader } from "discourse/lib/ajax"; import { userPath } from "discourse/lib/url"; import { iconNode } from "discourse-common/lib/icon-library"; import { ajax } from "discourse/lib/ajax"; +import getURL from "discourse-common/lib/get-url"; export const DefaultNotificationItem = createWidget( "default-notification-item", @@ -46,9 +47,7 @@ export const DefaultNotificationItem = createWidget( let username = data.username; username = username ? "?username=" + username.toLowerCase() : ""; - return Discourse.getURL( - "/badges/" + badgeId + "/" + badgeSlug + username - ); + return getURL("/badges/" + badgeId + "/" + badgeSlug + username); } const topicId = attrs.topic_id; @@ -134,8 +133,9 @@ export const DefaultNotificationItem = createWidget( const id = this.attrs.id; setTransientHeader("Discourse-Clear-Notifications", id); if (document && document.cookie) { - let path = Discourse.BaseUri || "/"; - document.cookie = `cn=${id}; path=${path}; expires=Fri, 31 Dec 9999 23:59:59 GMT`; + document.cookie = `cn=${id}; path=${getURL( + "/" + )}; expires=Fri, 31 Dec 9999 23:59:59 GMT`; } if (wantsNewWindow(e)) { return; diff --git a/app/assets/javascripts/discourse/app/widgets/hamburger-categories.js b/app/assets/javascripts/discourse/app/widgets/hamburger-categories.js index dd1b1693e59..5369f9c5936 100644 --- a/app/assets/javascripts/discourse/app/widgets/hamburger-categories.js +++ b/app/assets/javascripts/discourse/app/widgets/hamburger-categories.js @@ -1,3 +1,4 @@ +import getURL from "discourse-common/lib/get-url"; import I18n from "I18n"; import { createWidget } from "discourse/widgets/widget"; import { h } from "virtual-dom"; @@ -52,7 +53,7 @@ export default createWidget("hamburger-categories", { tagName: "ul.category-links.clearfix", html(attrs) { - const href = Discourse.getURL("/categories"); + const href = getURL("/categories"); let title = I18n.t("filters.categories.title"); if (attrs.moreCount > 0) { title = I18n.t("categories.n_more", { count: attrs.moreCount }); diff --git a/app/assets/javascripts/discourse/app/widgets/hamburger-menu.js b/app/assets/javascripts/discourse/app/widgets/hamburger-menu.js index 91aefaaa898..669d75928fc 100644 --- a/app/assets/javascripts/discourse/app/widgets/hamburger-menu.js +++ b/app/assets/javascripts/discourse/app/widgets/hamburger-menu.js @@ -1,3 +1,4 @@ +import getURL from "discourse-common/lib/get-url"; import I18n from "I18n"; import { later } from "@ember/runloop"; import { createWidget, applyDecorators } from "discourse/widgets/widget"; @@ -269,7 +270,7 @@ export default createWidget("hamburger-menu", { let faqUrl = this.siteSettings.faq_url; if (!faqUrl || faqUrl.length === 0) { - faqUrl = Discourse.getURL("/faq"); + faqUrl = getURL("/faq"); } const prioritizeFaq = diff --git a/app/assets/javascripts/discourse/app/widgets/header-topic-info.js b/app/assets/javascripts/discourse/app/widgets/header-topic-info.js index 64a81513e7a..99d4eaea366 100644 --- a/app/assets/javascripts/discourse/app/widgets/header-topic-info.js +++ b/app/assets/javascripts/discourse/app/widgets/header-topic-info.js @@ -1,3 +1,4 @@ +import getURL from "discourse-common/lib/get-url"; import I18n from "I18n"; import { applyDecorators, createWidget } from "discourse/widgets/widget"; import { h } from "virtual-dom"; @@ -27,7 +28,7 @@ createWidget("topic-header-participant", { url = user.get("path"); } else { content = [iconNode("users")]; - url = Discourse.getURL(`/g/${group.name}`); + url = getURL(`/g/${group.name}`); content.push(h("span", group.name)); } diff --git a/app/assets/javascripts/discourse/app/widgets/header.js b/app/assets/javascripts/discourse/app/widgets/header.js index 4699a58a86b..b6f2abe9b43 100644 --- a/app/assets/javascripts/discourse/app/widgets/header.js +++ b/app/assets/javascripts/discourse/app/widgets/header.js @@ -1,3 +1,4 @@ +import getURL from "discourse-common/lib/get-url"; import I18n from "I18n"; import { get } from "@ember/object"; import { schedule } from "@ember/runloop"; @@ -217,7 +218,7 @@ createWidget("header-icons", { iconId: "search-button", action: "toggleSearchMenu", active: attrs.searchVisible, - href: Discourse.getURL("/search") + href: getURL("/search") }); const icons = [search, hamburger]; diff --git a/app/assets/javascripts/discourse/app/widgets/home-logo.js b/app/assets/javascripts/discourse/app/widgets/home-logo.js index 5c7454df117..9af8f2b2739 100644 --- a/app/assets/javascripts/discourse/app/widgets/home-logo.js +++ b/app/assets/javascripts/discourse/app/widgets/home-logo.js @@ -1,3 +1,4 @@ +import getURL from "discourse-common/lib/get-url"; import { createWidget } from "discourse/widgets/widget"; import { h } from "virtual-dom"; import { iconNode } from "discourse-common/lib/icon-library"; @@ -8,7 +9,7 @@ export default createWidget("home-logo", { tagName: "div.title", settings: { - href: Discourse.getURL("/") + href: getURL("/") }, href() { @@ -44,7 +45,7 @@ export default createWidget("home-logo", { return h("img#site-logo.logo-small", { key: "logo-small", attributes: { - src: Discourse.getURL(logoSmallUrl), + src: getURL(logoSmallUrl), width: 36, alt: title } @@ -55,12 +56,12 @@ export default createWidget("home-logo", { } else if (showMobileLogo) { return h("img#site-logo.logo-big", { key: "logo-mobile", - attributes: { src: Discourse.getURL(mobileLogoUrl), alt: title } + attributes: { src: getURL(mobileLogoUrl), alt: title } }); } else if (logoUrl.length) { return h("img#site-logo.logo-big", { key: "logo-big", - attributes: { src: Discourse.getURL(logoUrl), alt: title } + attributes: { src: getURL(logoUrl), alt: title } }); } else { return h("h1#site-text-logo.text-logo", { key: "logo-text" }, title); diff --git a/app/assets/javascripts/discourse/app/widgets/link.js b/app/assets/javascripts/discourse/app/widgets/link.js index 3d10f189a69..1d19eada131 100644 --- a/app/assets/javascripts/discourse/app/widgets/link.js +++ b/app/assets/javascripts/discourse/app/widgets/link.js @@ -1,3 +1,4 @@ +import getURL from "discourse-common/lib/get-url"; import I18n from "I18n"; import { wantsNewWindow } from "discourse/lib/intercept-click"; import { createWidget } from "discourse/widgets/widget"; @@ -17,12 +18,12 @@ export default createWidget("link", { if (attrs.model) { params.push(attrs.model); } - return Discourse.getURL( + return getURL( router._routerMicrolib.generate.apply(router._routerMicrolib, params) ); } } else { - return Discourse.getURL(attrs.href); + return getURL(attrs.href); } }, diff --git a/app/assets/javascripts/discourse/app/widgets/post.js b/app/assets/javascripts/discourse/app/widgets/post.js index 467b25a1172..83e2fd2f083 100644 --- a/app/assets/javascripts/discourse/app/widgets/post.js +++ b/app/assets/javascripts/discourse/app/widgets/post.js @@ -1,3 +1,4 @@ +import { default as getURL, getURLWithCDN } from "discourse-common/lib/get-url"; import I18n from "I18n"; import PostCooked from "discourse/widgets/post-cooked"; import DecoratorHelper from "discourse/widgets/decorator-helper"; @@ -43,7 +44,7 @@ export function avatarImg(wanted, attrs) { alt: "", width: size, height: size, - src: Discourse.getURLWithCDN(url), + src: getURLWithCDN(url), title }, className @@ -353,7 +354,7 @@ createWidget("post-group-request", { }, html(attrs) { - const href = Discourse.getURL( + const href = getURL( "/g/" + attrs.requestedGroupName + "/requests?filter=" + attrs.username ); diff --git a/app/assets/javascripts/discourse/app/widgets/poster-name.js b/app/assets/javascripts/discourse/app/widgets/poster-name.js index f587a19d9aa..04457539ce7 100644 --- a/app/assets/javascripts/discourse/app/widgets/poster-name.js +++ b/app/assets/javascripts/discourse/app/widgets/poster-name.js @@ -1,3 +1,4 @@ +import getURL from "discourse-common/lib/get-url"; import I18n from "I18n"; import { iconNode } from "discourse-common/lib/icon-library"; import { createWidget, applyDecorators } from "discourse/widgets/widget"; @@ -19,7 +20,7 @@ createWidget("poster-name-title", { html(attrs) { let titleContents = attrs.title; if (attrs.primaryGroupName && attrs.titleIsGroup) { - const href = Discourse.getURL(`/g/${attrs.primaryGroupName}`); + const href = getURL(`/g/${attrs.primaryGroupName}`); titleContents = h( "a.user-group", { diff --git a/app/assets/javascripts/discourse/app/widgets/private-message-map.js b/app/assets/javascripts/discourse/app/widgets/private-message-map.js index 824e198b1bc..5738312e597 100644 --- a/app/assets/javascripts/discourse/app/widgets/private-message-map.js +++ b/app/assets/javascripts/discourse/app/widgets/private-message-map.js @@ -1,3 +1,4 @@ +import getURL from "discourse-common/lib/get-url"; import I18n from "I18n"; import { makeArray } from "discourse-common/lib/helpers"; import { createWidget } from "discourse/widgets/widget"; @@ -27,7 +28,7 @@ createWidget("pm-map-user-group", { tagName: "div.user.group", transform(attrs) { - return { href: Discourse.getURL(`/g/${attrs.group.name}`) }; + return { href: getURL(`/g/${attrs.group.name}`) }; }, template: hbs` diff --git a/app/assets/javascripts/discourse/app/widgets/search-menu.js b/app/assets/javascripts/discourse/app/widgets/search-menu.js index cec34e75a9b..50f89a9a55a 100644 --- a/app/assets/javascripts/discourse/app/widgets/search-menu.js +++ b/app/assets/javascripts/discourse/app/widgets/search-menu.js @@ -1,3 +1,4 @@ +import getURL from "discourse-common/lib/get-url"; import { get } from "@ember/object"; import { debounce } from "@ember/runloop"; import { popupAjaxError } from "discourse/lib/ajax-error"; @@ -118,7 +119,7 @@ export default createWidget("search-menu", { url = `${url}?${params.join("&")}`; } - return Discourse.getURL(url); + return getURL(url); }, panelContents() { diff --git a/app/assets/javascripts/select-kit/addon/components/category-drop.js b/app/assets/javascripts/select-kit/addon/components/category-drop.js index ebe5eec4b2e..3722e734f5f 100644 --- a/app/assets/javascripts/select-kit/addon/components/category-drop.js +++ b/app/assets/javascripts/select-kit/addon/components/category-drop.js @@ -1,3 +1,4 @@ +import getURL from "discourse-common/lib/get-url"; import I18n from "I18n"; import { readOnly } from "@ember/object/computed"; import { computed } from "@ember/object"; @@ -126,14 +127,14 @@ export default ComboBoxComponent.extend({ "parentCategoryUrl", "selectKit.options.subCategory", function() { - return Discourse.getURL( + return getURL( this.selectKit.options.subCategory ? this.parentCategoryUrl || "/" : "/" ); } ), noCategoriesUrl: computed("parentCategoryUrl", function() { - return Discourse.getURL(`${this.parentCategoryUrl}/none`); + return getURL(`${this.parentCategoryUrl}/none`); }), search(filter) { diff --git a/app/assets/javascripts/select-kit/addon/components/tag-drop.js b/app/assets/javascripts/select-kit/addon/components/tag-drop.js index 26641e6be24..6f93d7e9264 100644 --- a/app/assets/javascripts/select-kit/addon/components/tag-drop.js +++ b/app/assets/javascripts/select-kit/addon/components/tag-drop.js @@ -1,3 +1,4 @@ +import getURL from "discourse-common/lib/get-url"; import Category from "discourse/models/category"; import { readOnly, or, equal, gte } from "@ember/object/computed"; import { i18n, setting } from "discourse/lib/computed"; @@ -73,9 +74,9 @@ export default ComboBoxComponent.extend(TagsMixin, { allTagsUrl: computed("firstCategory", "secondCategory", function() { if (this.currentCategory) { - return Discourse.getURL(`${this.currentCategoryUrl}?allTags=1`); + return getURL(`${this.currentCategoryUrl}?allTags=1`); } else { - return Discourse.getURL("/"); + return getURL("/"); } }), @@ -86,7 +87,7 @@ export default ComboBoxComponent.extend(TagsMixin, { this.currentCategory.id }`; } - return Discourse.getURL(`${url}/${NONE_TAG_ID}`); + return getURL(`${url}/${NONE_TAG_ID}`); }), allTagsLabel: i18n("tagging.selector_all_tags"), @@ -189,7 +190,7 @@ export default ComboBoxComponent.extend(TagsMixin, { } } - DiscourseURL.routeTo(Discourse.getURL(url)); + DiscourseURL.routeTo(getURL(url)); } } }); diff --git a/app/assets/javascripts/select-kit/addon/mixins/tags.js b/app/assets/javascripts/select-kit/addon/mixins/tags.js index 8e96cf4f79a..5bdd8879671 100644 --- a/app/assets/javascripts/select-kit/addon/mixins/tags.js +++ b/app/assets/javascripts/select-kit/addon/mixins/tags.js @@ -1,3 +1,4 @@ +import getURL from "discourse-common/lib/get-url"; import I18n from "I18n"; import { reads } from "@ember/object/computed"; import { ajax } from "discourse/lib/ajax"; @@ -8,7 +9,7 @@ import { isEmpty } from "@ember/utils"; export default Mixin.create({ searchTags(url, data, callback) { - return ajax(Discourse.getURL(url), { + return ajax(getURL(url), { quietMillis: 200, cache: true, dataType: "json", diff --git a/lib/pretty_text.rb b/lib/pretty_text.rb index 642b627c3df..e17a90e44bc 100644 --- a/lib/pretty_text.rb +++ b/lib/pretty_text.rb @@ -86,6 +86,7 @@ module PrettyText ctx_load_manifest(ctx, "markdown-it-bundle.js") root_path = "#{Rails.root}/app/assets/javascripts/" + apply_es6_file(ctx, root_path, "discourse-common/addon/lib/get-url") apply_es6_file(ctx, root_path, "discourse/app/lib/to-markdown") apply_es6_file(ctx, root_path, "discourse/app/lib/utilities") diff --git a/test/javascripts/lib/computed-test.js b/test/javascripts/lib/computed-test.js index b2eda9dcd79..35e47d801ae 100644 --- a/test/javascripts/lib/computed-test.js +++ b/test/javascripts/lib/computed-test.js @@ -9,6 +9,7 @@ import { url, htmlSafe } from "discourse/lib/computed"; +import { setPrefix } from "discourse-common/lib/get-url"; QUnit.module("lib:computed", { beforeEach() { @@ -148,7 +149,7 @@ QUnit.test("url", assert => { "it supports urls without a prefix" ); - Discourse.BaseUri = "/prefixed"; + setPrefix("/prefixed"); t = testClass.create({ username: "eviltrout" }); assert.equal( t.get("userUrl"), diff --git a/test/javascripts/lib/discourse-test.js b/test/javascripts/lib/discourse-test.js index 3d04bdb3507..4b2395c68ea 100644 --- a/test/javascripts/lib/discourse-test.js +++ b/test/javascripts/lib/discourse-test.js @@ -2,43 +2,6 @@ import { logIn, updateCurrentUser } from "helpers/qunit-helpers"; QUnit.module("lib:discourse"); -QUnit.test("getURL on subfolder install", assert => { - Discourse.BaseUri = "/forum"; - assert.equal(Discourse.getURL("/"), "/forum/", "root url has subfolder"); - assert.equal( - Discourse.getURL("/u/neil"), - "/forum/u/neil", - "relative url has subfolder" - ); - - assert.equal( - Discourse.getURL("/svg-sprite/forum.example.com/svg-sprite.js"), - "/forum/svg-sprite/forum.example.com/svg-sprite.js", - "works when the url has the prefix in the middle" - ); - - assert.equal( - Discourse.getURL("/forum/t/123"), - "/forum/t/123", - "does not prefix if the URL is already prefixed" - ); -}); - -QUnit.test("getURLWithCDN on subfolder install with S3", assert => { - Discourse.BaseUri = "/forum"; - - Discourse.S3CDN = "https://awesome.cdn/site"; - Discourse.S3BaseUrl = "//test.s3-us-west-1.amazonaws.com/site"; - - let url = "//test.s3-us-west-1.amazonaws.com/site/forum/awesome.png"; - let expected = "https://awesome.cdn/site/forum/awesome.png"; - - assert.equal(Discourse.getURLWithCDN(url), expected, "at correct path"); - - Discourse.S3CDN = null; - Discourse.S3BaseUrl = null; -}); - QUnit.test("title counts are updated correctly", assert => { Discourse.set("hasFocus", true); Discourse.set("contextCount", 0); diff --git a/test/javascripts/lib/get-url-test.js b/test/javascripts/lib/get-url-test.js new file mode 100644 index 00000000000..6a97f428943 --- /dev/null +++ b/test/javascripts/lib/get-url-test.js @@ -0,0 +1,88 @@ +import { + default as getURL, + setupURL, + setupS3CDN, + getURLWithCDN, + isAbsoluteURL, + getAbsoluteURL, + setPrefix, + withoutPrefix +} from "discourse-common/lib/get-url"; + +QUnit.module("lib:get-url"); + +QUnit.test("isAbsoluteURL", assert => { + setupURL(null, "https://example.com", "/forum"); + assert.ok(isAbsoluteURL("https://example.com/test/thing")); + assert.ok(!isAbsoluteURL("http://example.com/test/thing")); + assert.ok(!isAbsoluteURL("https://discourse.org/test/thing")); +}); + +QUnit.test("getAbsoluteURL", assert => { + setupURL(null, "https://example.com", "/forum"); + assert.equal(getAbsoluteURL("/cool/path"), "https://example.com/cool/path"); +}); + +QUnit.test("withoutPrefix", assert => { + setPrefix("/eviltrout"); + assert.equal(withoutPrefix("/eviltrout/hello"), "/hello"); + assert.equal(withoutPrefix("/eviltrout/"), "/"); + assert.equal(withoutPrefix("/eviltrout"), ""); + + setPrefix(""); + assert.equal(withoutPrefix("/eviltrout/hello"), "/eviltrout/hello"); + assert.equal(withoutPrefix("/eviltrout"), "/eviltrout"); + assert.equal(withoutPrefix("/"), "/"); + + setPrefix(null); + assert.equal(withoutPrefix("/eviltrout/hello"), "/eviltrout/hello"); + assert.equal(withoutPrefix("/eviltrout"), "/eviltrout"); + assert.equal(withoutPrefix("/"), "/"); +}); + +QUnit.test("getURL with empty paths", assert => { + setupURL(null, "https://example.com", "/"); + assert.equal(getURL("/"), "/"); + assert.equal(getURL(""), ""); + setupURL(null, "https://example.com", ""); + assert.equal(getURL("/"), "/"); + assert.equal(getURL(""), ""); + setupURL(null, "https://example.com", undefined); + assert.equal(getURL("/"), "/"); + assert.equal(getURL(""), ""); +}); + +QUnit.test("getURL on subfolder install", assert => { + setupURL(null, "", "/forum"); + assert.equal(getURL("/"), "/forum/", "root url has subfolder"); + assert.equal( + getURL("/u/neil"), + "/forum/u/neil", + "relative url has subfolder" + ); + + assert.equal( + getURL("/svg-sprite/forum.example.com/svg-sprite.js"), + "/forum/svg-sprite/forum.example.com/svg-sprite.js", + "works when the url has the prefix in the middle" + ); + + assert.equal( + getURL("/forum/t/123"), + "/forum/t/123", + "does not prefix if the URL is already prefixed" + ); +}); + +QUnit.test("getURLWithCDN on subfolder install with S3", assert => { + setupURL(null, "", "/forum"); + setupS3CDN( + "//test.s3-us-west-1.amazonaws.com/site", + "https://awesome.cdn/site" + ); + + let url = "//test.s3-us-west-1.amazonaws.com/site/forum/awesome.png"; + let expected = "https://awesome.cdn/site/forum/awesome.png"; + + assert.equal(getURLWithCDN(url), expected, "at correct path"); +}); diff --git a/test/javascripts/lib/url-test.js b/test/javascripts/lib/url-test.js index 5c33defdf5c..b5f755a1433 100644 --- a/test/javascripts/lib/url-test.js +++ b/test/javascripts/lib/url-test.js @@ -1,4 +1,5 @@ import DiscourseURL, { userPath } from "discourse/lib/url"; +import { setPrefix } from "discourse-common/lib/get-url"; QUnit.module("lib:url"); @@ -59,8 +60,8 @@ QUnit.test("userPath", assert => { assert.equal(userPath("hp.json"), "/u/hp.json"); }); -QUnit.test("userPath with BaseUri", assert => { - Discourse.BaseUri = "/forum"; +QUnit.test("userPath with prefix", assert => { + setPrefix("/forum"); assert.equal(userPath(), "/forum/u"); assert.equal(userPath("eviltrout"), "/forum/u/eviltrout"); assert.equal(userPath("hp.json"), "/forum/u/hp.json"); diff --git a/test/javascripts/models/email-log-test.js b/test/javascripts/models/email-log-test.js index f6e00b14e20..7391960decf 100644 --- a/test/javascripts/models/email-log-test.js +++ b/test/javascripts/models/email-log-test.js @@ -1,4 +1,5 @@ import EmailLog from "admin/models/email-log"; +import { setPrefix } from "discourse-common/lib/get-url"; QUnit.module("Discourse.EmailLog"); @@ -7,7 +8,7 @@ QUnit.test("create", assert => { }); QUnit.test("subfolder support", assert => { - Discourse.BaseUri = "/forum"; + setPrefix("/forum"); const attrs = { id: 60, to_address: "wikiman@asdf.com", diff --git a/test/javascripts/models/report-test.js b/test/javascripts/models/report-test.js index 821a88eee8f..cfd09f3d4d7 100644 --- a/test/javascripts/models/report-test.js +++ b/test/javascripts/models/report-test.js @@ -1,4 +1,5 @@ import Report from "admin/models/report"; +import { setPrefix } from "discourse-common/lib/get-url"; QUnit.module("Report"); @@ -528,7 +529,7 @@ QUnit.test("computed labels", assert => { assert.equal(computedFilesizeLabel.value, 582641); // subfolder support - Discourse.BaseUri = "/forum"; + setPrefix("/forum"); const postLink = computedLabels[5].compute(row).formatedValue; assert.equal( diff --git a/test/javascripts/test_helper.js b/test/javascripts/test_helper.js index cc599032a10..f20b2251ed5 100644 --- a/test/javascripts/test_helper.js +++ b/test/javascripts/test_helper.js @@ -151,8 +151,10 @@ QUnit.testStart(function(ctx) { // Allow our tests to change site settings and have them reset before the next test Discourse.SiteSettings = dup(Discourse.SiteSettingsOriginal); - Discourse.BaseUri = ""; - Discourse.BaseUrl = "http://localhost:3000"; + + let getURL = require("discourse-common/lib/get-url"); + getURL.setupURL(null, "http://localhost:3000", ""); + getURL.setupS3CDN(null, null); let User = require("discourse/models/user").default; let Session = require("discourse/models/session").default; diff --git a/test/javascripts/widgets/home-logo-test.js b/test/javascripts/widgets/home-logo-test.js index bffe7ee19a2..c30c1a56ec4 100644 --- a/test/javascripts/widgets/home-logo-test.js +++ b/test/javascripts/widgets/home-logo-test.js @@ -1,4 +1,5 @@ import { moduleForWidget, widgetTest } from "helpers/widget-test"; +import { setPrefix } from "discourse-common/lib/get-url"; moduleForWidget("home-logo"); @@ -101,7 +102,7 @@ widgetTest("mobile without logo", { widgetTest("basics, subfolder", { template: '{{mount-widget widget="home-logo" args=args}}', beforeEach() { - Discourse.BaseUri = "/forum"; + setPrefix("/forum"); this.siteSettings.site_logo_url = bigLogo; this.siteSettings.site_logo_small_url = smallLogo; this.siteSettings.title = title; @@ -118,7 +119,7 @@ widgetTest("basics, subfolder", { widgetTest("basics, subfolder - minimized", { template: '{{mount-widget widget="home-logo" args=args}}', beforeEach() { - Discourse.BaseUri = "/forum"; + setPrefix("/forum"); this.siteSettings.site_logo_url = bigLogo; this.siteSettings.site_logo_small_url = smallLogo; this.siteSettings.title = title; @@ -135,7 +136,7 @@ widgetTest("basics, subfolder - minimized", { widgetTest("mobile logo, subfolder", { template: '{{mount-widget widget="home-logo" args=args}}', beforeEach() { - Discourse.BaseUri = "/forum"; + setPrefix("/forum"); this.siteSettings.site_mobile_logo_url = mobileLogo; this.siteSettings.site_logo_small_url = smallLogo; this.site.mobileView = true;