DEV: Move Discourse.getURL and related functions to a module (#9966)

* DEV: Move `Discourse.getURL` and related functions to a module

* DEV: Remove `Discourse.getURL` and `Discourse.getURLWithCDN`

* FIX: `get-url` is required for server side code

* DEV: Deprecate `BaseUri` too.
This commit is contained in:
Robin Ward
2020-06-03 12:45:26 -04:00
committed by GitHub
parent d27b877a40
commit ba00cc8ec4
90 changed files with 401 additions and 260 deletions

View File

@ -1,3 +1,4 @@
import getURL from "discourse-common/lib/get-url";
import I18n from "I18n"; import I18n from "I18n";
import { later, schedule } from "@ember/runloop"; import { later, schedule } from "@ember/runloop";
import Component from "@ember/component"; import Component from "@ember/component";
@ -31,7 +32,7 @@ export default Component.extend({
@on("init") @on("init")
_initialize() { _initialize() {
this.resumable = new Resumable({ this.resumable = new Resumable({
target: Discourse.getURL(this.target), target: getURL(this.target),
maxFiles: 1, // only 1 file at a time maxFiles: 1, // only 1 file at a time
headers: { headers: {
"X-CSRF-Token": document.querySelector("meta[name='csrf-token']") "X-CSRF-Token": document.querySelector("meta[name='csrf-token']")

View File

@ -8,6 +8,7 @@ import AdminDashboard from "admin/models/admin-dashboard";
import Report from "admin/models/report"; import Report from "admin/models/report";
import PeriodComputationMixin from "admin/mixins/period-computation"; import PeriodComputationMixin from "admin/mixins/period-computation";
import { computed } from "@ember/object"; import { computed } from "@ember/object";
import getURL from "discourse-common/lib/get-url";
function staticReport(reportType) { function staticReport(reportType) {
return computed("reports.[]", function() { return computed("reports.[]", function() {
@ -20,7 +21,6 @@ export default Controller.extend(PeriodComputationMixin, {
dashboardFetchedAt: null, dashboardFetchedAt: null,
exceptionController: inject("exception"), exceptionController: inject("exception"),
logSearchQueriesEnabled: setting("log_search_queries"), logSearchQueriesEnabled: setting("log_search_queries"),
basePath: Discourse.BaseUri,
@discourseComputed("siteSettings.dashboard_general_tab_activity_metrics") @discourseComputed("siteSettings.dashboard_general_tab_activity_metrics")
activityMetrics(metrics) { activityMetrics(metrics) {
@ -107,7 +107,7 @@ export default Controller.extend(PeriodComputationMixin, {
@discourseComputed @discourseComputed
trendingSearchDisabledLabel() { trendingSearchDisabledLabel() {
return I18n.t("admin.dashboard.reports.trending_search.disabled", { 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) { _reportsForPeriodURL(period) {
return Discourse.getURL(`/admin?period=${period}`); return getURL(`/admin?period=${period}`);
} }
}); });

View File

@ -1,3 +1,4 @@
import getURL from "discourse-common/lib/get-url";
import discourseComputed from "discourse-common/utils/decorators"; import discourseComputed from "discourse-common/utils/decorators";
import Controller from "@ember/controller"; import Controller from "@ember/controller";
import PeriodComputationMixin from "admin/mixins/period-computation"; import PeriodComputationMixin from "admin/mixins/period-computation";
@ -45,6 +46,6 @@ export default Controller.extend(PeriodComputationMixin, {
}, },
_reportsForPeriodURL(period) { _reportsForPeriodURL(period) {
return Discourse.getURL(`/admin/dashboard/moderation?period=${period}`); return getURL(`/admin/dashboard/moderation?period=${period}`);
} }
}); });

View File

@ -6,6 +6,7 @@ import Controller, { inject as controller } from "@ember/controller";
import { popupAjaxError } from "discourse/lib/ajax-error"; import { popupAjaxError } from "discourse/lib/ajax-error";
import { extractDomainFromUrl } from "discourse/lib/utilities"; import { extractDomainFromUrl } from "discourse/lib/utilities";
import EmberObject from "@ember/object"; import EmberObject from "@ember/object";
import { isAbsoluteURL } from "discourse-common/lib/get-url";
export default Controller.extend({ export default Controller.extend({
adminWebHooks: controller(), adminWebHooks: controller(),
@ -109,7 +110,7 @@ export default Controller.extend({
domain === "localhost" || domain === "localhost" ||
domain.match(/192\.168\.\d+\.\d+/) || domain.match(/192\.168\.\d+\.\d+/) ||
domain.match(/127\.\d+\.\d+\.\d+/) || domain.match(/127\.\d+\.\d+\.\d+/) ||
url.startsWith(Discourse.BaseUrl) isAbsoluteURL(url)
) { ) {
return bootbox.confirm( return bootbox.confirm(
I18n.t("admin.web_hooks.warn_local_payload_url"), I18n.t("admin.web_hooks.warn_local_payload_url"),

View File

@ -1,3 +1,4 @@
import getURL from "discourse-common/lib/get-url";
import I18n from "I18n"; import I18n from "I18n";
import discourseComputed from "discourse-common/utils/decorators"; import discourseComputed from "discourse-common/utils/decorators";
import { filter, or, gt, lt, not } from "@ember/object/computed"; import { filter, or, gt, lt, not } from "@ember/object/computed";
@ -43,7 +44,7 @@ const AdminUser = User.extend({
@discourseComputed @discourseComputed
bounceLink() { bounceLink() {
return Discourse.getURL("/admin/email/bounced"); return getURL("/admin/email/bounced");
}, },
canResetBounceScore: gt("bounce_score", 0), canResetBounceScore: gt("bounce_score", 0),
@ -306,7 +307,7 @@ const AdminUser = User.extend({
type: "POST", type: "POST",
data: { username_or_email: this.username } data: { username_or_email: this.username }
}) })
.then(() => (document.location = Discourse.getURL("/"))) .then(() => (document.location = getURL("/")))
.catch(e => { .catch(e => {
if (e.status === 404) { if (e.status === 404) {
bootbox.alert(I18n.t("admin.impersonate.not_found")); bootbox.alert(I18n.t("admin.impersonate.not_found"));
@ -395,11 +396,11 @@ const AdminUser = User.extend({
.then(function(data) { .then(function(data) {
if (data.success) { if (data.success) {
if (data.username) { if (data.username) {
document.location = Discourse.getURL( document.location = getURL(
`/admin/users/${user.get("id")}/${data.username}` `/admin/users/${user.get("id")}/${data.username}`
); );
} else { } else {
document.location = Discourse.getURL("/admin/users/list/active"); document.location = getURL("/admin/users/list/active");
} }
} else { } else {
bootbox.alert(I18n.t("admin.user.anonymize_failed")); bootbox.alert(I18n.t("admin.user.anonymize_failed"));
@ -456,7 +457,7 @@ const AdminUser = User.extend({
if (/^\/admin\/users\/list\//.test(location)) { if (/^\/admin\/users\/list\//.test(location)) {
document.location = location; document.location = location;
} else { } else {
document.location = Discourse.getURL("/admin/users/list/active"); document.location = getURL("/admin/users/list/active");
} }
} else { } else {
bootbox.alert(I18n.t("admin.user.delete_failed")); bootbox.alert(I18n.t("admin.user.delete_failed"));

View File

@ -1,3 +1,4 @@
import getURL from "discourse-common/lib/get-url";
import I18n from "I18n"; import I18n from "I18n";
import { ajax } from "discourse/lib/ajax"; import { ajax } from "discourse/lib/ajax";
import { extractError } from "discourse/lib/ajax-error"; import { extractError } from "discourse/lib/ajax-error";
@ -66,7 +67,7 @@ Backup.reopenClass({
bootbox.alert(result.message); bootbox.alert(result.message);
} else { } else {
// redirect to homepage (session might be lost) // redirect to homepage (session might be lost)
window.location = Discourse.getURL("/"); window.location = getURL("/");
} }
}); });
} }

View File

@ -1,3 +1,4 @@
import getURL from "discourse-common/lib/get-url";
import { ajax } from "discourse/lib/ajax"; import { ajax } from "discourse/lib/ajax";
import AdminUser from "admin/models/admin-user"; import AdminUser from "admin/models/admin-user";
import EmberObject from "@ember/object"; import EmberObject from "@ember/object";
@ -13,7 +14,7 @@ EmailLog.reopenClass({
} }
if (attrs.post_url) { if (attrs.post_url) {
attrs.post_url = Discourse.getURL(attrs.post_url); attrs.post_url = getURL(attrs.post_url);
} }
return this._super(attrs); return this._super(attrs);

View File

@ -1,3 +1,4 @@
import getURL from "discourse-common/lib/get-url";
import I18n from "I18n"; import I18n from "I18n";
import discourseComputed from "discourse-common/utils/decorators"; import discourseComputed from "discourse-common/utils/decorators";
import { makeArray } from "discourse-common/lib/helpers"; import { makeArray } from "discourse-common/lib/helpers";
@ -37,7 +38,7 @@ const Report = EmberObject.extend({
.locale("en") .locale("en")
.format("YYYY-MM-DD"); .format("YYYY-MM-DD");
return Discourse.getURL( return getURL(
`/admin/reports/${type}?start_date=${start_date}&end_date=${end_date}` `/admin/reports/${type}?start_date=${start_date}&end_date=${end_date}`
); );
}, },
@ -335,7 +336,7 @@ const Report = EmberObject.extend({
avatar_template: row[properties.avatar] avatar_template: row[properties.avatar]
}); });
const href = Discourse.getURL(`/admin/users/${userId}/${username}`); const href = getURL(`/admin/users/${userId}/${username}`);
const avatarImg = renderAvatar(user, { const avatarImg = renderAvatar(user, {
imageSize: "tiny", imageSize: "tiny",
@ -356,7 +357,7 @@ const Report = EmberObject.extend({
const formatedValue = () => { const formatedValue = () => {
const topicId = row[properties.id]; const topicId = row[properties.id];
const href = Discourse.getURL(`/t/-/${topicId}`); const href = getURL(`/t/-/${topicId}`);
return `<a href='${href}'>${escapeExpression(topicTitle)}</a>`; return `<a href='${href}'>${escapeExpression(topicTitle)}</a>`;
}; };
@ -370,7 +371,7 @@ const Report = EmberObject.extend({
const postTitle = row[properties.truncated_raw]; const postTitle = row[properties.truncated_raw];
const postNumber = row[properties.number]; const postNumber = row[properties.number];
const topicId = row[properties.topic_id]; const topicId = row[properties.topic_id];
const href = Discourse.getURL(`/t/-/${topicId}/${postNumber}`); const href = getURL(`/t/-/${topicId}/${postNumber}`);
return { return {
property: properties.title, property: properties.title,
@ -434,7 +435,7 @@ const Report = EmberObject.extend({
_linkLabel(properties, row) { _linkLabel(properties, row) {
const property = properties[0]; const property = properties[0];
const value = Discourse.getURL(row[property]); const value = getURL(row[property]);
const formatedValue = (href, anchor) => { const formatedValue = (href, anchor) => {
return `<a href="${escapeExpression(href)}">${escapeExpression( return `<a href="${escapeExpression(href)}">${escapeExpression(
anchor anchor

View File

@ -1,3 +1,4 @@
import getURL from "discourse-common/lib/get-url";
import I18n from "I18n"; import I18n from "I18n";
import EmberObject from "@ember/object"; import EmberObject from "@ember/object";
import DiscourseRoute from "discourse/routes/discourse"; import DiscourseRoute from "discourse/routes/discourse";
@ -40,7 +41,7 @@ export default DiscourseRoute.extend({
); );
if (log.operation === "restore") { if (log.operation === "restore") {
// redirect to homepage when the restore is done (session might be lost) // redirect to homepage when the restore is done (session might be lost)
window.location = Discourse.getURL("/"); window.location = getURL("/");
} }
} else { } else {
this.controllerFor("adminBackupsLogs") this.controllerFor("adminBackupsLogs")

View File

@ -147,7 +147,7 @@
filters=trendingSearchFilters filters=trendingSearchFilters
isEnabled=logSearchQueriesEnabled isEnabled=logSearchQueriesEnabled
disabledLabel=trendingSearchDisabledLabel}} 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 "/"))}}
</div> </div>
{{/if}} {{/if}}
</div> </div>

View File

@ -1,4 +1,5 @@
let baseUri; let cdn, baseUrl, baseUri;
let S3BaseUrl, S3CDN;
export default function getURL(url) { export default function getURL(url) {
if (!url) return url; if (!url) return url;
@ -17,3 +18,42 @@ export default function getURL(url) {
return baseUri + 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;
}

View File

@ -1,10 +1,11 @@
import getURL from "discourse-common/lib/get-url";
import { ajax } from "discourse/lib/ajax"; import { ajax } from "discourse/lib/ajax";
import RestAdapter from "discourse/adapters/rest"; import RestAdapter from "discourse/adapters/rest";
import PreloadStore from "discourse/lib/preload-store"; import PreloadStore from "discourse/lib/preload-store";
export function finderFor(filter, params) { export function finderFor(filter, params) {
return function() { return function() {
let url = Discourse.getURL("/") + filter + ".json"; let url = getURL("/") + filter + ".json";
if (params) { if (params) {
const keys = Object.keys(params), const keys = Object.keys(params),

View File

@ -4,6 +4,8 @@ import { computed } from "@ember/object";
import { buildResolver } from "discourse-common/resolver"; import { buildResolver } from "discourse-common/resolver";
import { bind } from "@ember/runloop"; import { bind } from "@ember/runloop";
import discourseComputed, { observes } from "discourse-common/utils/decorators"; 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 = []; const _pluginCallbacks = [];
@ -42,26 +44,19 @@ const Discourse = Application.extend({
}, },
getURL(url) { getURL(url) {
if (!url) return url; deprecated(
"Import `getURL` from `discourse-common/lib/get-url` instead of `Discourse.getURL`",
// if it's a non relative URL, return it. { since: "2.5", dropFrom: "2.6" }
if (url !== "/" && !/^\/[^\/]/.test(url)) return url; );
return getURL(url);
if (url[0] !== "/") url = "/" + url;
if (url.startsWith(this.BaseUri)) return url;
return this.BaseUri + url;
}, },
getURLWithCDN(url) { getURLWithCDN(url) {
url = this.getURL(url); deprecated(
// only relative urls "Import `getURLWithCDN` from `discourse-common/lib/get-url` instead of `Discourse.getURLWithCDN`",
if (this.CDN && /^\/[^\/]/.test(url)) { { since: "2.5", dropFrom: "2.6" }
url = this.CDN + url; );
} else if (this.S3CDN) { return getURLWithCDN(url);
url = url.replace(this.S3BaseUrl, this.S3CDN);
}
return url;
}, },
Resolver: buildResolver("discourse"), Resolver: buildResolver("discourse"),

View File

@ -1,3 +1,4 @@
import { getURLWithCDN } from "discourse-common/lib/get-url";
import discourseComputed from "discourse-common/utils/decorators"; import discourseComputed from "discourse-common/utils/decorators";
import Component from "@ember/component"; import Component from "@ember/component";
import { htmlSafe } from "@ember/template"; import { htmlSafe } from "@ember/template";
@ -7,7 +8,7 @@ export default Component.extend({
@discourseComputed("src") @discourseComputed("src")
cdnSrc(src) { cdnSrc(src) {
return Discourse.getURLWithCDN(src); return getURLWithCDN(src);
}, },
@discourseComputed("width", "height") @discourseComputed("width", "height")

View File

@ -1,3 +1,4 @@
import getURL from "discourse-common/lib/get-url";
import I18n from "I18n"; import I18n from "I18n";
import { debounce, later, next, schedule, throttle } from "@ember/runloop"; import { debounce, later, next, schedule, throttle } from "@ember/runloop";
import Component from "@ember/component"; import Component from "@ember/component";
@ -650,9 +651,7 @@ export default Component.extend({
const $element = $(this.element); const $element = $(this.element);
$element.fileupload({ $element.fileupload({
url: Discourse.getURL( url: getURL(`/uploads.json?client_id=${this.messageBus.clientId}`),
`/uploads.json?client_id=${this.messageBus.clientId}`
),
dataType: "json", dataType: "json",
pasteZone: $element pasteZone: $element
}); });

View File

@ -1,3 +1,4 @@
import getURL from "discourse-common/lib/get-url";
import discourseComputed from "discourse-common/utils/decorators"; import discourseComputed from "discourse-common/utils/decorators";
import Component from "@ember/component"; import Component from "@ember/component";
@ -13,6 +14,6 @@ export default Component.extend({
@discourseComputed("tagRecord.id") @discourseComputed("tagRecord.id")
href(tagRecordId) { href(tagRecordId) {
return Discourse.getURL("/tag/" + tagRecordId); return getURL("/tag/" + tagRecordId);
} }
}); });

View File

@ -1,3 +1,4 @@
import getURL from "discourse-common/lib/get-url";
import discourseComputed from "discourse-common/utils/decorators"; import discourseComputed from "discourse-common/utils/decorators";
import { isEmpty } from "@ember/utils"; import { isEmpty } from "@ember/utils";
import { not } from "@ember/object/computed"; import { not } from "@ember/object/computed";
@ -27,10 +28,10 @@ export default buildCategoryPanel("general", {
}, },
canSelectParentCategory: not("category.isUncategorizedCategory"), canSelectParentCategory: not("category.isUncategorizedCategory"),
uncategorizedSiteSettingLink: Discourse.getURL( uncategorizedSiteSettingLink: getURL(
"/admin/site_settings/category/all_results?filter=allow_uncategorized_topics" "/admin/site_settings/category/all_results?filter=allow_uncategorized_topics"
), ),
customizeTextContentLink: Discourse.getURL( customizeTextContentLink: getURL(
"/admin/customize/site_texts?q=uncategorized" "/admin/customize/site_texts?q=uncategorized"
), ),

View File

@ -1,3 +1,4 @@
import getURL from "discourse-common/lib/get-url";
import I18n from "I18n"; import I18n from "I18n";
import { bind, cancel } from "@ember/runloop"; import { bind, cancel } from "@ember/runloop";
import Component from "@ember/component"; import Component from "@ember/component";
@ -105,7 +106,7 @@ export default Component.extend({
if (this.site.wizard_required) { if (this.site.wizard_required) {
const requiredText = I18n.t("wizard_required", { const requiredText = I18n.t("wizard_required", {
url: Discourse.getURL("/wizard") url: getURL("/wizard")
}); });
notices.push(Notice.create({ text: requiredText, id: "alert-wizard" })); notices.push(Notice.create({ text: requiredText, id: "alert-wizard" }));
} }

View File

@ -1,3 +1,4 @@
import getURL from "discourse-common/lib/get-url";
import discourseComputed from "discourse-common/utils/decorators"; import discourseComputed from "discourse-common/utils/decorators";
import { alias } from "@ember/object/computed"; import { alias } from "@ember/object/computed";
import Component from "@ember/component"; import Component from "@ember/component";
@ -10,6 +11,6 @@ export default Component.extend({
@discourseComputed @discourseComputed
siteUrl() { siteUrl() {
return `${location.protocol}//${location.host}${Discourse.getURL("/")}`; return `${location.protocol}//${location.host}${getURL("/")}`;
} }
}); });

View File

@ -1,3 +1,4 @@
import getURL from "discourse-common/lib/get-url";
import I18n from "I18n"; import I18n from "I18n";
import discourseComputed from "discourse-common/utils/decorators"; import discourseComputed from "discourse-common/utils/decorators";
import { debounce } from "@ember/runloop"; import { debounce } from "@ember/runloop";
@ -14,7 +15,7 @@ export default Component.extend({
@discourseComputed @discourseComputed
demoAvatarUrl() { demoAvatarUrl() {
return Discourse.getURL("/images/avatar.png"); return getURL("/images/avatar.png");
}, },
@discourseComputed("model.flair_type") @discourseComputed("model.flair_type")
@ -105,7 +106,7 @@ export default Component.extend({
@action @action
setFlairImage(upload) { setFlairImage(upload) {
this.model.setProperties({ this.model.setProperties({
flair_url: Discourse.getURL(upload.url), flair_url: getURL(upload.url),
flair_upload_id: upload.id flair_upload_id: upload.id
}); });
}, },

View File

@ -1,9 +1,10 @@
import getURL from "discourse-common/lib/get-url";
import discourseComputed from "discourse-common/utils/decorators"; import discourseComputed from "discourse-common/utils/decorators";
import Component from "@ember/component"; import Component from "@ember/component";
export default Component.extend({ export default Component.extend({
@discourseComputed("post.url") @discourseComputed("post.url")
postUrl(url) { postUrl(url) {
return Discourse.getURL(url); return getURL(url);
} }
}); });

View File

@ -1,3 +1,4 @@
import { getURLWithCDN } from "discourse-common/lib/get-url";
import discourseComputed from "discourse-common/utils/decorators"; import discourseComputed from "discourse-common/utils/decorators";
import { isEmpty } from "@ember/utils"; import { isEmpty } from "@ember/utils";
import { next } from "@ember/runloop"; import { next } from "@ember/runloop";
@ -43,7 +44,7 @@ export default Component.extend(UploadMixin, {
return "".htmlSafe(); return "".htmlSafe();
} }
return Discourse.getURLWithCDN(url); return getURLWithCDN(url);
}, },
@discourseComputed("imageCDNURL") @discourseComputed("imageCDNURL")

View File

@ -1,3 +1,4 @@
import getURL from "discourse-common/lib/get-url";
import discourseComputed from "discourse-common/utils/decorators"; import discourseComputed from "discourse-common/utils/decorators";
import Component from "@ember/component"; import Component from "@ember/component";
@ -23,7 +24,7 @@ export default Component.extend({
@discourseComputed @discourseComputed
searchLink() { searchLink() {
return Discourse.getURL( return getURL(
`/search?expanded=true&q=%40${this.targetUser.username}%20in%3Apersonal-direct` `/search?expanded=true&q=%40${this.targetUser.username}%20in%3Apersonal-direct`
); );
}, },

View File

@ -1,3 +1,4 @@
import getURL from "discourse-common/lib/get-url";
import I18n from "I18n"; import I18n from "I18n";
import discourseComputed from "discourse-common/utils/decorators"; import discourseComputed from "discourse-common/utils/decorators";
import { computed, get } from "@ember/object"; import { computed, get } from "@ember/object";
@ -25,7 +26,7 @@ export default Component.extend({
} }
const opts = { const opts = {
latestLink: `<a href="${Discourse.getURL("/latest")}">${I18n.t( latestLink: `<a href="${getURL("/latest")}">${I18n.t(
"topic.view_latest_topics" "topic.view_latest_topics"
)}</a>` )}</a>`
}; };
@ -43,7 +44,7 @@ export default Component.extend({
} else { } else {
opts.catLink = opts.catLink =
'<a href="' + '<a href="' +
Discourse.getURL("/categories") + getURL("/categories") +
'">' + '">' +
I18n.t("topic.browse_all_categories") + I18n.t("topic.browse_all_categories") +
"</a>"; "</a>";

View File

@ -1,3 +1,4 @@
import { getURLWithCDN } from "discourse-common/lib/get-url";
import I18n from "I18n"; import I18n from "I18n";
import { isEmpty } from "@ember/utils"; import { isEmpty } from "@ember/utils";
import { alias, gte, and, gt, not, or } from "@ember/object/computed"; 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 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; thisElem.style.backgroundImage = bg;
}, },

View File

@ -270,11 +270,6 @@ export default Controller.extend(ModalFunctionality, {
return this.nextMonth().format(I18n.t("dates.long_no_year")); return this.nextMonth().format(I18n.t("dates.long_no_year"));
}, },
@discourseComputed()
basePath() {
return Discourse.BaseUri;
},
@discourseComputed("userTimezone") @discourseComputed("userTimezone")
userHasTimezoneSet(userTimezone) { userHasTimezoneSet(userTimezone) {
return !_.isEmpty(userTimezone); return !_.isEmpty(userTimezone);

View File

@ -1,3 +1,4 @@
import getURL from "discourse-common/lib/get-url";
import I18n from "I18n"; import I18n from "I18n";
import { isEmpty } from "@ember/utils"; import { isEmpty } from "@ember/utils";
import { and, or, alias, reads } from "@ember/object/computed"; import { and, or, alias, reads } from "@ember/object/computed";
@ -561,7 +562,7 @@ export default Controller.extend({
) { ) {
groups.forEach(group => { groups.forEach(group => {
let body; let body;
const groupLink = Discourse.getURL(`/g/${group.name}/members`); const groupLink = getURL(`/g/${group.name}/members`);
if (group.max_mentions < group.user_count) { if (group.max_mentions < group.user_count) {
body = I18n.t("composer.group_mentioned_limit", { body = I18n.t("composer.group_mentioned_limit", {

View File

@ -1,3 +1,4 @@
import getURL from "discourse-common/lib/get-url";
import I18n from "I18n"; import I18n from "I18n";
import { A } from "@ember/array"; import { A } from "@ember/array";
import { isEmpty } from "@ember/utils"; import { isEmpty } from "@ember/utils";
@ -86,10 +87,9 @@ export default Controller.extend(
@discourseComputed @discourseComputed
disclaimerHtml() { disclaimerHtml() {
return I18n.t("create_account.disclaimer", { 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: privacy_link:
this.get("siteSettings.privacy_policy_url") || this.get("siteSettings.privacy_policy_url") || getURL("/privacy")
Discourse.getURL("/privacy")
}); });
}, },

View File

@ -1,3 +1,4 @@
import getURL from "discourse-common/lib/get-url";
import discourseComputed from "discourse-common/utils/decorators"; import discourseComputed from "discourse-common/utils/decorators";
import Controller from "@ember/controller"; import Controller from "@ember/controller";
import { SECOND_FACTOR_METHODS } from "discourse/models/user"; 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"; import { getWebauthnCredential } from "discourse/lib/webauthn";
export default Controller.extend({ export default Controller.extend({
lockImageUrl: Discourse.getURL("/images/lock.svg"), lockImageUrl: getURL("/images/lock.svg"),
@discourseComputed("model") @discourseComputed("model")
secondFactorRequired(model) { secondFactorRequired(model) {

View File

@ -6,6 +6,7 @@ import { ajax } from "discourse/lib/ajax";
import ModalFunctionality from "discourse/mixins/modal-functionality"; import ModalFunctionality from "discourse/mixins/modal-functionality";
import { escapeExpression } from "discourse/lib/utilities"; import { escapeExpression } from "discourse/lib/utilities";
import { extractError } from "discourse/lib/ajax-error"; import { extractError } from "discourse/lib/ajax-error";
import getURL from "discourse-common/lib/get-url";
export default Controller.extend(ModalFunctionality, { export default Controller.extend(ModalFunctionality, {
offerHelp: null, offerHelp: null,
@ -30,7 +31,7 @@ export default Controller.extend(ModalFunctionality, {
help() { help() {
this.setProperties({ this.setProperties({
offerHelp: I18n.t("forgot_password.help", { offerHelp: I18n.t("forgot_password.help", {
basePath: Discourse.BaseUri basePath: getURL("/")
}), }),
helpSeen: true helpSeen: true
}); });

View File

@ -1,3 +1,4 @@
import getURL from "discourse-common/lib/get-url";
import I18n from "I18n"; import I18n from "I18n";
import discourseComputed from "discourse-common/utils/decorators"; import discourseComputed from "discourse-common/utils/decorators";
import { isEmpty } from "@ember/utils"; import { isEmpty } from "@ember/utils";
@ -372,8 +373,8 @@ export default Controller.extend(ModalFunctionality, {
// redirect client to the original URL // redirect client to the original URL
$.removeCookie("destination_url"); $.removeCookie("destination_url");
window.location.href = destinationUrl; window.location.href = destinationUrl;
} else if (window.location.pathname === Discourse.getURL("/login")) { } else if (window.location.pathname === getURL("/login")) {
window.location = Discourse.getURL("/"); window.location = getURL("/");
} else { } else {
window.location.reload(); window.location.reload();
} }

View File

@ -1,3 +1,4 @@
import getURL from "discourse-common/lib/get-url";
import I18n from "I18n"; import I18n from "I18n";
import { alias, or, readOnly } from "@ember/object/computed"; import { alias, or, readOnly } from "@ember/object/computed";
import Controller from "@ember/controller"; import Controller from "@ember/controller";
@ -41,10 +42,10 @@ export default Controller.extend(PasswordValidation, {
@discourseComputed("redirectTo") @discourseComputed("redirectTo")
redirectHref(redirectTo) { redirectHref(redirectTo) {
return Discourse.getURL(redirectTo || "/"); return getURL(redirectTo || "/");
}, },
lockImageUrl: Discourse.getURL("/images/lock.svg"), lockImageUrl: getURL("/images/lock.svg"),
actions: { actions: {
submit() { submit() {

View File

@ -1,3 +1,4 @@
import getURL from "discourse-common/lib/get-url";
import I18n from "I18n"; import I18n from "I18n";
import { not, or, gt } from "@ember/object/computed"; import { not, or, gt } from "@ember/object/computed";
import Controller from "@ember/controller"; import Controller from "@ember/controller";
@ -195,7 +196,7 @@ export default Controller.extend(CanCheckEmails, {
() => { () => {
bootbox.alert( bootbox.alert(
I18n.t("user.deleted_yourself"), I18n.t("user.deleted_yourself"),
() => (window.location = Discourse.getURL("/")) () => (window.location = getURL("/"))
); );
}, },
() => { () => {

View File

@ -1,3 +1,4 @@
import getURL from "discourse-common/lib/get-url";
import I18n from "I18n"; import I18n from "I18n";
import { get } from "@ember/object"; import { get } from "@ember/object";
import { registerUnbound } from "discourse-common/lib/helpers"; import { registerUnbound } from "discourse-common/lib/helpers";
@ -104,9 +105,7 @@ function defaultCategoryLinkRenderer(category, opts) {
let restricted = get(category, "read_restricted"); let restricted = get(category, "read_restricted");
let url = opts.url let url = opts.url
? opts.url ? opts.url
: Discourse.getURL( : getURL(`/c/${Category.slugFor(category)}/${get(category, "id")}`);
`/c/${Category.slugFor(category)}/${get(category, "id")}`
);
let href = opts.link === false ? "" : url; let href = opts.link === false ? "" : url;
let tagName = opts.link === false || opts.link === "false" ? "span" : "a"; let tagName = opts.link === false || opts.link === "false" ? "span" : "a";
let extraClasses = opts.extraClasses ? " " + opts.extraClasses : ""; let extraClasses = opts.extraClasses ? " " + opts.extraClasses : "";

View File

@ -1,3 +1,4 @@
import getURL from "discourse-common/lib/get-url";
// Initialize the message bus to receive messages. // Initialize the message bus to receive messages.
import userPresent from "discourse/lib/user-presence"; import userPresent from "discourse/lib/user-presence";
import { handleLogoff } from "discourse/lib/ajax"; import { handleLogoff } from "discourse/lib/ajax";
@ -84,7 +85,7 @@ export default {
return ajax(opts); return ajax(opts);
}; };
messageBus.baseUrl = Discourse.getURL("/"); messageBus.baseUrl = getURL("/");
} }
if (user) { if (user) {

View File

@ -1,3 +1,6 @@
import { isAbsoluteURL } from "discourse-common/lib/get-url";
import getURL from "discourse-common/lib/get-url";
export default { export default {
name: "register-service-worker", name: "register-service-worker",
@ -30,7 +33,7 @@ export default {
}); });
navigator.serviceWorker navigator.serviceWorker
.register(`${Discourse.BaseUri}/${Discourse.ServiceWorkerURL}`) .register(`${getURL(Discourse.ServiceWorkerURL)}`)
.catch(error => { .catch(error => {
// eslint-disable-next-line no-console // eslint-disable-next-line no-console
console.info(`Failed to register Service Worker: ${error}`); console.info(`Failed to register Service Worker: ${error}`);
@ -46,7 +49,7 @@ export default {
}, },
unregister(registration) { unregister(registration) {
if (registration.scope.startsWith(Discourse.BaseUrl)) { if (isAbsoluteURL(registration.scope)) {
registration.unregister(); registration.unregister();
} }
} }

View File

@ -1,3 +1,4 @@
import getURL from "discourse-common/lib/get-url";
import I18n from "I18n"; import I18n from "I18n";
import { run } from "@ember/runloop"; import { run } from "@ember/runloop";
import userPresent from "discourse/lib/user-presence"; 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 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; let promise;
@ -169,7 +170,7 @@ export function ajax() {
if ( if (
args.type && args.type &&
args.type.toUpperCase() !== "GET" && args.type.toUpperCase() !== "GET" &&
url !== Discourse.getURL("/clicks/track") && url !== getURL("/clicks/track") &&
!Session.currentProp("csrfToken") !Session.currentProp("csrfToken")
) { ) {
promise = new Promise((resolve, reject) => { promise = new Promise((resolve, reject) => {

View File

@ -1,3 +1,4 @@
import getURL from "discourse-common/lib/get-url";
import discourseDebounce from "discourse/lib/debounce"; import discourseDebounce from "discourse/lib/debounce";
import { CANCELLED_STATUS } from "discourse/lib/autocomplete"; import { CANCELLED_STATUS } from "discourse/lib/autocomplete";
import Category from "discourse/models/category"; import Category from "discourse/models/category";
@ -27,7 +28,7 @@ function searchTags(term, categories, limit) {
); );
const debouncedSearch = discourseDebounce((q, cats, resultFunc) => { const debouncedSearch = discourseDebounce((q, cats, resultFunc) => {
oldSearch = $.ajax(Discourse.getURL("/tags/filter/search"), { oldSearch = $.ajax(getURL("/tags/filter/search"), {
type: "GET", type: "GET",
cache: true, cache: true,
data: { limit: limit, q } data: { limit: limit, q }

View File

@ -1,3 +1,4 @@
import getURL from "discourse-common/lib/get-url";
import I18n from "I18n"; import I18n from "I18n";
import { later } from "@ember/runloop"; import { later } from "@ember/runloop";
import { ajax } from "discourse/lib/ajax"; import { ajax } from "discourse/lib/ajax";
@ -106,9 +107,9 @@ export default {
data.append("url", href); data.append("url", href);
data.append("post_id", postId); data.append("post_id", postId);
data.append("topic_id", topicId); data.append("topic_id", topicId);
navigator.sendBeacon(Discourse.getURL("/clicks/track"), data); navigator.sendBeacon(getURL("/clicks/track"), data);
} else { } else {
trackPromise = ajax(Discourse.getURL("/clicks/track"), { trackPromise = ajax(getURL("/clicks/track"), {
type: "POST", type: "POST",
data: { data: {
url: href, url: href,

View File

@ -1,3 +1,4 @@
import getURL from "discourse-common/lib/get-url";
import I18n from "I18n"; import I18n from "I18n";
import { computed } from "@ember/object"; import { computed } from "@ember/object";
import { htmlSafe as htmlSafeTemplateHelper } from "@ember/template"; import { htmlSafe as htmlSafeTemplateHelper } from "@ember/template";
@ -126,7 +127,7 @@ export function fmt(...args) {
export function url(...args) { export function url(...args) {
const format = args.pop(); const format = args.pop();
return computed(...args, function() { 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))));
}); });
} }

View File

@ -1,6 +1,7 @@
import EmberObject from "@ember/object"; import EmberObject from "@ember/object";
import { defaultHomepage } from "discourse/lib/utilities"; import { defaultHomepage } from "discourse/lib/utilities";
import { guidFor } from "@ember/object/internals"; import { guidFor } from "@ember/object/internals";
import { withoutPrefix } from "discourse-common/lib/get-url";
let popstateFired = false; let popstateFired = false;
const supportsHistoryState = window.history && "state" in window.history; const supportsHistoryState = window.history && "state" in window.history;
const popstateCallbacks = []; const popstateCallbacks = [];
@ -62,10 +63,7 @@ const DiscourseLocation = EmberObject.extend({
@method getURL @method getURL
*/ */
getURL() { getURL() {
let url = this.location.pathname; let url = withoutPrefix(this.location.pathname);
url = url.replace(new RegExp(`^${Discourse.BaseUri}`), "");
const search = this.location.search || ""; const search = this.location.search || "";
url += search; url += search;
return url; return url;

View File

@ -471,9 +471,7 @@ export default {
}, },
_bindToPath(path, key) { _bindToPath(path, key) {
this.keyTrapper.bind(key, () => this.keyTrapper.bind(key, () => DiscourseURL.routeTo(path));
DiscourseURL.routeTo(Discourse.BaseUri + path)
);
}, },
_bindToClick(selector, binding) { _bindToClick(selector, binding) {

View File

@ -1,3 +1,4 @@
import getURL from "discourse-common/lib/get-url";
import { schedule } from "@ember/runloop"; import { schedule } from "@ember/runloop";
import { ajax } from "discourse/lib/ajax"; import { ajax } from "discourse/lib/ajax";
import { userPath } from "discourse/lib/url"; import { userPath } from "discourse/lib/url";
@ -15,7 +16,7 @@ function replaceSpan($e, username, opts) {
extraClass = "notify"; extraClass = "notify";
} }
$e.replaceWith( $e.replaceWith(
`<a href='${Discourse.getURL("/g/") + `<a href='${getURL("/g/") +
username}' class='mention-group ${extraClass}' ${extra}>@${username}</a>` username}' class='mention-group ${extraClass}' ${extra}>@${username}</a>`
); );
} else { } else {

View File

@ -1,3 +1,4 @@
import { default as getURL, getURLWithCDN } from "discourse-common/lib/get-url";
import { run } from "@ember/runloop"; import { run } from "@ember/runloop";
import { ajax } from "discourse/lib/ajax"; import { ajax } from "discourse/lib/ajax";
import { Promise } from "rsvp"; import { Promise } from "rsvp";
@ -51,9 +52,7 @@ export default function loadScript(url, opts) {
// Scripts should always load from CDN // Scripts should always load from CDN
// CSS is type text, to accept it from a CDN we would need to handle CORS // CSS is type text, to accept it from a CDN we would need to handle CORS
const fullUrl = opts.css const fullUrl = opts.css ? getURL(url) : getURLWithCDN(url);
? Discourse.getURL(url)
: Discourse.getURLWithCDN(url);
$("script").each((i, tag) => { $("script").each((i, tag) => {
const src = tag.getAttribute("src"); const src = tag.getAttribute("src");

View File

@ -1,3 +1,4 @@
import getURL from "discourse-common/lib/get-url";
import { isEmpty } from "@ember/utils"; import { isEmpty } from "@ember/utils";
import { findAll } from "discourse/models/login-method"; import { findAll } from "discourse/models/login-method";
@ -23,9 +24,9 @@ export default function logout(siteSettings, keyValueStore) {
if (siteSettings.login_required && (sso || oneAuthenticator)) { if (siteSettings.login_required && (sso || oneAuthenticator)) {
// In this situation visiting most URLs will start the auth process again // In this situation visiting most URLs will start the auth process again
// Go to the `/login` page to avoid an immediate redirect // Go to the `/login` page to avoid an immediate redirect
window.location.href = Discourse.getURL("/login"); window.location.href = getURL("/login");
return; return;
} }
window.location.href = Discourse.getURL("/"); window.location.href = getURL("/");
} }

View File

@ -1,3 +1,4 @@
import getURL from "discourse-common/lib/get-url";
import { next } from "@ember/runloop"; import { next } from "@ember/runloop";
let _started = false; let _started = false;
let cache = {}; let cache = {};
@ -28,7 +29,7 @@ export function startPageTracking(router, appEvents) {
transition.urlMethod === "replace" && transition.queryParamsOnly; transition.urlMethod === "replace" && transition.queryParamsOnly;
router.send("refreshTitle"); 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 // Refreshing the title is debounced, so we need to trigger this in the
// next runloop to have the correct title. // next runloop to have the correct title.

View File

@ -1,3 +1,4 @@
import getURL from "discourse-common/lib/get-url";
import User from "discourse/models/user"; import User from "discourse/models/user";
import { escapeExpression } from "discourse/lib/utilities"; import { escapeExpression } from "discourse/lib/utilities";
@ -24,7 +25,7 @@ export function defaultRenderTag(tag, params) {
path = `/tag/${tag}`; path = `/tag/${tag}`;
} }
} }
const href = path ? ` href='${Discourse.getURL(path)}' ` : ""; const href = path ? ` href='${getURL(path)}' ` : "";
if (Discourse.SiteSettings.tag_style || params.style) { if (Discourse.SiteSettings.tag_style || params.style) {
classes.push(params.style || Discourse.SiteSettings.tag_style); classes.push(params.style || Discourse.SiteSettings.tag_style);

View File

@ -1,3 +1,4 @@
import getURL from "discourse-common/lib/get-url";
import I18n from "I18n"; import I18n from "I18n";
import { isEmpty } from "@ember/utils"; import { isEmpty } from "@ember/utils";
import EmberObject from "@ember/object"; import EmberObject from "@ember/object";
@ -67,7 +68,7 @@ export function translateResults(results, opts) {
flairBgColor, flairBgColor,
fullName, fullName,
name, name,
url: Discourse.getURL(`/g/${name}`) url: getURL(`/g/${name}`)
}; };
}) })
.compact(); .compact();
@ -77,7 +78,7 @@ export function translateResults(results, opts) {
const tagName = escapeExpression(tag.name); const tagName = escapeExpression(tag.name);
return EmberObject.create({ return EmberObject.create({
id: tagName, id: tagName,
url: Discourse.getURL("/tag/" + tagName) url: getURL("/tag/" + tagName)
}); });
}) })
.compact(); .compact();

View File

@ -1,3 +1,4 @@
import { getURLWithCDN } from "discourse-common/lib/get-url";
import PrettyText, { buildOptions } from "pretty-text/pretty-text"; import PrettyText, { buildOptions } from "pretty-text/pretty-text";
import { performEmojiUnescape, buildEmojiUrl } from "pretty-text/emoji"; import { performEmojiUnescape, buildEmojiUrl } from "pretty-text/emoji";
import WhiteLister from "pretty-text/white-lister"; import WhiteLister from "pretty-text/white-lister";
@ -7,8 +8,6 @@ import { formatUsername } from "discourse/lib/utilities";
import { Promise } from "rsvp"; import { Promise } from "rsvp";
import { htmlSafe } from "@ember/template"; import { htmlSafe } from "@ember/template";
const getURLWithCDN = url => Discourse.getURLWithCDN(url);
function getOpts(opts) { function getOpts(opts) {
const siteSettings = Discourse.__container__.lookup("site-settings:main"), const siteSettings = Discourse.__container__.lookup("site-settings:main"),
site = Discourse.__container__.lookup("site:main"); site = Discourse.__container__.lookup("site:main");

View File

@ -5,6 +5,7 @@ import offsetCalculator from "discourse/lib/offset-calculator";
import LockOn from "discourse/lib/lock-on"; import LockOn from "discourse/lib/lock-on";
import { defaultHomepage } from "discourse/lib/utilities"; import { defaultHomepage } from "discourse/lib/utilities";
import User from "discourse/models/user"; import User from "discourse/models/user";
import { default as getURL, withoutPrefix } from "discourse-common/lib/get-url";
const rewrites = []; const rewrites = [];
const TOPIC_REGEXP = /\/t\/([^\/]+)\/(\d+)\/?(\d+)?/; const TOPIC_REGEXP = /\/t\/([^\/]+)\/(\d+)\/?(\d+)?/;
@ -55,11 +56,11 @@ export function clearRewrites() {
} }
export function userPath(subPath) { export function userPath(subPath) {
return Discourse.getURL(subPath ? `/u/${subPath}` : "/u"); return getURL(subPath ? `/u/${subPath}` : "/u");
} }
export function groupPath(subPath) { export function groupPath(subPath) {
return Discourse.getURL(subPath ? `/g/${subPath}` : "/g"); return getURL(subPath ? `/g/${subPath}` : "/g");
} }
let _jumpScheduled = false; let _jumpScheduled = false;
@ -210,11 +211,10 @@ const DiscourseURL = EmberObject.extend({
} }
if (Discourse.get("requiresRefresh")) { if (Discourse.get("requiresRefresh")) {
return redirectTo(Discourse.getURL(path)); return redirectTo(getURL(path));
} }
const pathname = path.replace(/(https?\:)?\/\/[^\/]+/, ""); const pathname = path.replace(/(https?\:)?\/\/[^\/]+/, "");
const baseUri = Discourse.BaseUri;
if (!DiscourseURL.isInternal(path)) { if (!DiscourseURL.isInternal(path)) {
return redirectTo(path); return redirectTo(path);
@ -241,7 +241,7 @@ const DiscourseURL = EmberObject.extend({
path = path.replace(/(https?\:)?\/\/[^\/]+/, ""); path = path.replace(/(https?\:)?\/\/[^\/]+/, "");
// Rewrite /my/* urls // Rewrite /my/* urls
let myPath = `${baseUri}/my/`; let myPath = getURL("/my");
if (path.indexOf(myPath) === 0) { if (path.indexOf(myPath) === 0) {
const currentUser = User.current(); const currentUser = User.current();
if (currentUser) { if (currentUser) {
@ -256,11 +256,7 @@ const DiscourseURL = EmberObject.extend({
// handle prefixes // handle prefixes
if (path.indexOf("/") === 0) { if (path.indexOf("/") === 0) {
const rootURL = (baseUri === undefined ? "/" : baseUri).replace( path = withoutPrefix(path);
/\/$/,
""
);
path = path.replace(rootURL, "");
} }
path = rewritePath(path); path = rewritePath(path);
@ -293,7 +289,7 @@ const DiscourseURL = EmberObject.extend({
}, },
routeToUrl(url, opts = {}) { routeToUrl(url, opts = {}) {
this.routeTo(Discourse.getURL(url), opts); this.routeTo(getURL(url), opts);
}, },
rewrite(regexp, replacement, opts) { rewrite(regexp, replacement, opts) {
@ -301,7 +297,7 @@ const DiscourseURL = EmberObject.extend({
}, },
redirectTo(url) { 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. // This has been extracted so it can be tested.
origin() { origin() {
return ( let prefix = getURL("/");
window.location.origin + return window.location.origin + (prefix === "/" ? "" : prefix);
(Discourse.BaseUri === "/" ? "" : Discourse.BaseUri)
);
}, },
// TODO: These container calls can be replaced eventually if we migrate this to a service // TODO: These container calls can be replaced eventually if we migrate this to a service

View File

@ -2,6 +2,7 @@ import I18n from "I18n";
import { escape } from "pretty-text/sanitizer"; import { escape } from "pretty-text/sanitizer";
import toMarkdown from "discourse/lib/to-markdown"; import toMarkdown from "discourse/lib/to-markdown";
import Handlebars from "handlebars"; import Handlebars from "handlebars";
import { default as getURL, getURLWithCDN } from "discourse-common/lib/get-url";
const homepageSelector = "meta[name=discourse_current_homepage]"; 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))); return size * Math.min(3, Math.max(1, Math.round(pixelRatio)));
} }
const getURLWithCDN = url => Discourse.getURLWithCDN(url); export function avatarImg(options, customGetURL) {
export function avatarImg(options, getURL) {
getURL = getURL || getURLWithCDN;
const size = translateSize(options.size); const size = translateSize(options.size);
const url = avatarUrl(options.avatarTemplate, size); let path = avatarUrl(options.avatarTemplate, size);
// We won't render an invalid url // We won't render an invalid url
if (!url || url.length === 0) { if (!path || path.length === 0) {
return ""; return "";
} }
path = (customGetURL || getURLWithCDN)(path);
const classes = const classes =
"avatar" + (options.extraClasses ? " " + options.extraClasses : ""); "avatar" + (options.extraClasses ? " " + options.extraClasses : "");
@ -77,19 +75,7 @@ export function avatarImg(options, getURL) {
title = ` title='${escaped}' aria-label='${escaped}'`; title = ` title='${escaped}' aria-label='${escaped}'`;
} }
return ( return `<img alt='' width='${size}' height='${size}' src='${path}' class='${classes}'${title}>`;
"<img alt='' width='" +
size +
"' height='" +
size +
"' src='" +
getURL(url) +
"' class='" +
classes +
"'" +
title +
">"
);
} }
export function tinyAvatar(avatarTemplate, options) { export function tinyAvatar(avatarTemplate, options) {
@ -99,7 +85,7 @@ export function tinyAvatar(avatarTemplate, options) {
} }
export function postUrl(slug, topicId, postNumber) { export function postUrl(slug, topicId, postNumber) {
var url = Discourse.getURL("/t/"); var url = getURL("/t/");
if (slug) { if (slug) {
url += slug + "/"; url += slug + "/";
} else { } else {
@ -430,7 +416,7 @@ function reportToLogster(name, error) {
stacktrace: error.stack stacktrace: error.stack
}; };
Ember.$.ajax(`${Discourse.BaseUri}/logs/report_js_error`, { Ember.$.ajax(getURL("/logs/report_js_error"), {
data, data,
type: "POST", type: "POST",
cache: false cache: false
@ -447,7 +433,7 @@ export function rescueThemeError(name, error, api) {
return; return;
} }
const path = `${Discourse.BaseUri}/admin/customize/themes`; const path = getURL(`/admin/customize/themes`);
const message = I18n.t("themes.broken_theme_alert", { const message = I18n.t("themes.broken_theme_alert", {
theme: name, theme: name,
path: `<a href="${path}">${path}</a>` path: `<a href="${path}">${path}</a>`

View File

@ -3,11 +3,9 @@ import { defaultHomepage } from "discourse/lib/utilities";
import { rewritePath } from "discourse/lib/url"; import { rewritePath } from "discourse/lib/url";
import Site from "discourse/models/site"; import Site from "discourse/models/site";
import { isTesting } from "discourse-common/config/environment"; import { isTesting } from "discourse-common/config/environment";
import getURL from "discourse-common/lib/get-url";
const rootURL = Discourse.BaseUri;
const BareRouter = EmberRouter.extend({ const BareRouter = EmberRouter.extend({
rootURL,
location: isTesting() ? "none" : "discourse-location", location: isTesting() ? "none" : "discourse-location",
handleURL(url) { handleURL(url) {
@ -136,10 +134,10 @@ export function mapRoutes() {
} }
}); });
return BareRouter.extend().map(function() { return BareRouter.extend({
rootURL: getURL("/")
}).map(function() {
tree.mapRoutes(this); tree.mapRoutes(this);
this.route("unknown", { path: "*path" }); this.route("unknown", { path: "*path" });
}); });
} }
export default BareRouter;

View File

@ -1,3 +1,4 @@
import getURL from "discourse-common/lib/get-url";
import discourseComputed from "discourse-common/utils/decorators"; import discourseComputed from "discourse-common/utils/decorators";
import { none } from "@ember/object/computed"; import { none } from "@ember/object/computed";
import EmberObject from "@ember/object"; import EmberObject from "@ember/object";
@ -11,7 +12,7 @@ const Badge = RestModel.extend({
@discourseComputed @discourseComputed
url() { url() {
return Discourse.getURL(`/badges/${this.id}/${this.slug}`); return getURL(`/badges/${this.id}/${this.slug}`);
}, },
updateFromJson(json) { updateFromJson(json) {

View File

@ -1,3 +1,4 @@
import getURL from "discourse-common/lib/get-url";
import I18n from "I18n"; import I18n from "I18n";
import Category from "discourse/models/category"; import Category from "discourse/models/category";
import User from "discourse/models/user"; import User from "discourse/models/user";
@ -19,7 +20,7 @@ const Bookmark = RestModel.extend({
@computed @computed
get url() { get url() {
return Discourse.getURL(`/bookmarks/${this.id}`); return getURL(`/bookmarks/${this.id}`);
}, },
destroy() { destroy() {
@ -37,7 +38,7 @@ const Bookmark = RestModel.extend({
// Helper to build a Url with a post number // Helper to build a Url with a post number
urlForPostNumber(postNumber) { urlForPostNumber(postNumber) {
let url = Discourse.getURL(`/t/${this.topic_id}`); let url = getURL(`/t/${this.topic_id}`);
if (postNumber > 0) { if (postNumber > 0) {
url += `/${postNumber}`; url += `/${postNumber}`;
} }

View File

@ -1,3 +1,4 @@
import getURL from "discourse-common/lib/get-url";
import discourseComputed from "discourse-common/utils/decorators"; import discourseComputed from "discourse-common/utils/decorators";
import { get } from "@ember/object"; import { get } from "@ember/object";
import { ajax } from "discourse/lib/ajax"; import { ajax } from "discourse/lib/ajax";
@ -96,7 +97,7 @@ const Category = RestModel.extend({
@discourseComputed("name") @discourseComputed("name")
url() { url() {
return Discourse.getURL(`/c/${Category.slugFor(this)}/${this.id}`); return getURL(`/c/${Category.slugFor(this)}/${this.id}`);
}, },
@discourseComputed @discourseComputed

View File

@ -1,3 +1,4 @@
import getURL from "discourse-common/lib/get-url";
import I18n from "I18n"; import I18n from "I18n";
import discourseComputed from "discourse-common/utils/decorators"; import discourseComputed from "discourse-common/utils/decorators";
import EmberObject from "@ember/object"; import EmberObject from "@ember/object";
@ -33,7 +34,7 @@ const LoginMethod = EmberObject.extend({
return Promise.resolve(); return Promise.resolve();
} }
let authUrl = Discourse.getURL(`/auth/${this.name}`); let authUrl = getURL(`/auth/${this.name}`);
if (reconnect) { if (reconnect) {
params["reconnect"] = true; params["reconnect"] = true;

View File

@ -1,3 +1,4 @@
import getURL from "discourse-common/lib/get-url";
import I18n from "I18n"; import I18n from "I18n";
import discourseComputed from "discourse-common/utils/decorators"; import discourseComputed from "discourse-common/utils/decorators";
import { emojiUnescape } from "discourse/lib/text"; import { emojiUnescape } from "discourse/lib/text";
@ -105,7 +106,7 @@ NavItem.reopenClass({
extraNavItemDescriptors: [], extraNavItemDescriptors: [],
pathFor(filterType, context) { pathFor(filterType, context) {
let path = Discourse.getURL(""); let path = getURL("");
let includesCategoryContext = false; let includesCategoryContext = false;
let includesTagContext = false; let includesTagContext = false;

View File

@ -1,8 +1,9 @@
import RestModel from "discourse/models/rest"; import RestModel from "discourse/models/rest";
import { computed } from "@ember/object"; import { computed } from "@ember/object";
import { getAbsoluteURL } from "discourse-common/lib/get-url";
export default RestModel.extend({ export default RestModel.extend({
url: computed("slug", function() { url: computed("slug", function() {
return `${Discourse.BaseUrl}/pub/${this.slug}`; return getAbsoluteURL(`/pub/${this.slug}`);
}) })
}); });

View File

@ -3,6 +3,8 @@ import discourseComputed from "discourse-common/utils/decorators";
import EmberObject from "@ember/object"; import EmberObject from "@ember/object";
import { ajax } from "discourse/lib/ajax"; import { ajax } from "discourse/lib/ajax";
import User from "discourse/models/user"; 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. 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. When showing topics in lists and such this information should not be required.
@ -56,7 +58,7 @@ const TopicDetails = RestModel.extend({
} else { } else {
return I18n.t(localeString, { return I18n.t(localeString, {
username: User.currentProp("username_lower"), username: User.currentProp("username_lower"),
basePath: Discourse.BaseUri basePath: getURL("/")
}); });
} }
}, },

View File

@ -1,3 +1,4 @@
import getURL from "discourse-common/lib/get-url";
import { notEmpty } from "@ember/object/computed"; import { notEmpty } from "@ember/object/computed";
import EmberObject from "@ember/object"; import EmberObject from "@ember/object";
import { ajax } from "discourse/lib/ajax"; import { ajax } from "discourse/lib/ajax";
@ -124,9 +125,9 @@ const TopicList = RestModel.extend({
this.topics.filter(topic => topic_ids.indexOf(topic.id) >= 0) this.topics.filter(topic => topic_ids.indexOf(topic.id) >= 0)
); );
const url = `${Discourse.getURL("/")}${ const url = `${getURL("/")}${this.filter}.json?topic_ids=${topic_ids.join(
this.filter ","
}.json?topic_ids=${topic_ids.join(",")}`; )}`;
return ajax({ url, data: this.params }).then(result => { return ajax({ url, data: this.params }).then(result => {
let i = 0; let i = 0;

View File

@ -1,3 +1,4 @@
import getURL from "discourse-common/lib/get-url";
import I18n from "I18n"; import I18n from "I18n";
import EmberObject from "@ember/object"; import EmberObject from "@ember/object";
import { not, notEmpty, equal, and, or } from "@ember/object/computed"; 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) { export function loadTopicView(topic, args) {
const data = _.merge({}, 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"; const jsonUrl = (data.nearPost ? `${url}/${data.nearPost}` : url) + ".json";
delete data.nearPost; delete data.nearPost;
@ -259,7 +260,7 @@ const Topic = RestModel.extend({
if (slug.trim().length === 0) { if (slug.trim().length === 0) {
slug = "topic"; slug = "topic";
} }
return `${Discourse.getURL("/t/")}${slug}/${id}`; return `${getURL("/t/")}${slug}/${id}`;
}, },
// Helper to build a Url with a post number // Helper to build a Url with a post number
@ -739,7 +740,7 @@ Topic.reopenClass({
// Load a topic, but accepts a set of filters // Load a topic, but accepts a set of filters
find(topicId, opts) { find(topicId, opts) {
let url = Discourse.getURL("/t/") + topicId; let url = getURL("/t/") + topicId;
if (opts.nearPost) { if (opts.nearPost) {
url += `/${opts.nearPost}`; url += `/${opts.nearPost}`;
} }

View File

@ -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 I18n from "I18n";
import { A } from "@ember/array"; import { A } from "@ember/array";
import { isEmpty } from "@ember/utils"; import { isEmpty } from "@ember/utils";
@ -109,11 +111,7 @@ const User = RestModel.extend({
if (isEmpty(bgUrl) || !Discourse.SiteSettings.allow_profile_backgrounds) { if (isEmpty(bgUrl) || !Discourse.SiteSettings.allow_profile_backgrounds) {
return "".htmlSafe(); return "".htmlSafe();
} }
return ( return ("background-image: url(" + getURLWithCDN(bgUrl) + ")").htmlSafe();
"background-image: url(" +
Discourse.getURLWithCDN(bgUrl) +
")"
).htmlSafe();
}, },
@discourseComputed() @discourseComputed()
@ -183,22 +181,22 @@ const User = RestModel.extend({
@discourseComputed() @discourseComputed()
mutedTopicsPath() { mutedTopicsPath() {
return defaultHomepage() === "latest" return defaultHomepage() === "latest"
? Discourse.getURL("/?state=muted") ? getURL("/?state=muted")
: Discourse.getURL("/latest?state=muted"); : getURL("/latest?state=muted");
}, },
@discourseComputed() @discourseComputed()
watchingTopicsPath() { watchingTopicsPath() {
return defaultHomepage() === "latest" return defaultHomepage() === "latest"
? Discourse.getURL("/?state=watching") ? getURL("/?state=watching")
: Discourse.getURL("/latest?state=watching"); : getURL("/latest?state=watching");
}, },
@discourseComputed() @discourseComputed()
trackingTopicsPath() { trackingTopicsPath() {
return defaultHomepage() === "latest" return defaultHomepage() === "latest"
? Discourse.getURL("/?state=tracking") ? getURL("/?state=tracking")
: Discourse.getURL("/latest?state=tracking"); : getURL("/latest?state=tracking");
}, },
@discourseComputed("username") @discourseComputed("username")

View File

@ -7,6 +7,8 @@ import {
isTesting, isTesting,
isProduction isProduction
} from "discourse-common/config/environment"; } from "discourse-common/config/environment";
import { setupURL, setupS3CDN } from "discourse-common/lib/get-url";
import deprecated from "discourse-common/lib/deprecated";
export default { export default {
name: "discourse-bootstrap", name: "discourse-bootstrap",
@ -35,8 +37,28 @@ export default {
} }
app.CDN = setupData.cdn; 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); setEnvironment(setupData.environment);
app.SiteSettings = PreloadStore.get("siteSettings"); app.SiteSettings = PreloadStore.get("siteSettings");
app.ThemeSettings = PreloadStore.get("themeSettings"); app.ThemeSettings = PreloadStore.get("themeSettings");
@ -69,6 +91,7 @@ export default {
if (setupData.s3BaseUrl) { if (setupData.s3BaseUrl) {
app.S3CDN = setupData.s3Cdn; app.S3CDN = setupData.s3Cdn;
app.S3BaseUrl = setupData.s3BaseUrl; app.S3BaseUrl = setupData.s3BaseUrl;
setupS3CDN(setupData.s3BaseUrl, setupData.s3Cdn);
} }
RSVP.configure("onerror", function(e) { RSVP.configure("onerror", function(e) {

View File

@ -1,3 +1,4 @@
import getURL from "discourse-common/lib/get-url";
import I18n from "I18n"; import I18n from "I18n";
import { once } from "@ember/runloop"; import { once } from "@ember/runloop";
import DiscourseRoute from "discourse/routes/discourse"; import DiscourseRoute from "discourse/routes/discourse";
@ -46,8 +47,8 @@ const ApplicationRoute = DiscourseRoute.extend(OpenComposer, {
_collectTitleTokens(tokens) { _collectTitleTokens(tokens) {
tokens.push(this.siteTitle); tokens.push(this.siteTitle);
if ( if (
(window.location.pathname === Discourse.getURL("/") || (window.location.pathname === getURL("/") ||
window.location.pathname === Discourse.getURL("/login")) && window.location.pathname === getURL("/login")) &&
this.shortSiteDescription !== "" this.shortSiteDescription !== ""
) { ) {
tokens.push(this.shortSiteDescription); tokens.push(this.shortSiteDescription);
@ -250,9 +251,7 @@ const ApplicationRoute = DiscourseRoute.extend(OpenComposer, {
handleShowLogin() { handleShowLogin() {
if (this.siteSettings.enable_sso) { if (this.siteSettings.enable_sso) {
const returnPath = encodeURIComponent(window.location.pathname); const returnPath = encodeURIComponent(window.location.pathname);
window.location = Discourse.getURL( window.location = getURL("/session/sso?return_path=" + returnPath);
"/session/sso?return_path=" + returnPath
);
} else { } else {
this._autoLogin("login", "login-modal", () => this._autoLogin("login", "login-modal", () =>
this.controllerFor("login").resetForm() this.controllerFor("login").resetForm()
@ -263,9 +262,7 @@ const ApplicationRoute = DiscourseRoute.extend(OpenComposer, {
handleShowCreateAccount() { handleShowCreateAccount() {
if (this.siteSettings.enable_sso) { if (this.siteSettings.enable_sso) {
const returnPath = encodeURIComponent(window.location.pathname); const returnPath = encodeURIComponent(window.location.pathname);
window.location = Discourse.getURL( window.location = getURL("/session/sso?return_path=" + returnPath);
"/session/sso?return_path=" + returnPath
);
} else { } else {
this._autoLogin("createAccount", "create-account"); this._autoLogin("createAccount", "create-account");
} }

View File

@ -1,3 +1,4 @@
import getURL from "discourse-common/lib/get-url";
import I18n from "I18n"; import I18n from "I18n";
import { isEmpty } from "@ember/utils"; import { isEmpty } from "@ember/utils";
import EmberObject from "@ember/object"; import EmberObject from "@ember/object";
@ -42,7 +43,7 @@ const LogsNotice = EmberObject.extend({
), ),
rate, rate,
limit: siteSettingLimit, limit: siteSettingLimit,
url: Discourse.getURL("/logs") url: getURL("/logs")
}) })
); );
}); });

View File

@ -96,7 +96,7 @@
{{/tap-tile-grid}} {{/tap-tile-grid}}
{{else}} {{else}}
<div class="alert alert-info">{{html-safe (i18n "bookmarks.no_timezone" basePath=basePath)}}</div> <div class="alert alert-info">{{html-safe (i18n "bookmarks.no_timezone" basePath=(get-url "/"))}}</div>
{{/if}} {{/if}}
</div> </div>

View File

@ -1,3 +1,4 @@
import getURL from "discourse-common/lib/get-url";
import I18n from "I18n"; import I18n from "I18n";
import { createWidget } from "discourse/widgets/widget"; import { createWidget } from "discourse/widgets/widget";
import { avatarFor } from "discourse/widgets/post"; import { avatarFor } from "discourse/widgets/post";
@ -48,7 +49,7 @@ createWidget("small-user-list", {
if (postUrl) { if (postUrl) {
description = h( description = h(
"a", "a",
{ attributes: { href: Discourse.getURL(postUrl) } }, { attributes: { href: getURL(postUrl) } },
description description
); );
} }

View File

@ -15,6 +15,7 @@ import { setTransientHeader } from "discourse/lib/ajax";
import { userPath } from "discourse/lib/url"; import { userPath } from "discourse/lib/url";
import { iconNode } from "discourse-common/lib/icon-library"; import { iconNode } from "discourse-common/lib/icon-library";
import { ajax } from "discourse/lib/ajax"; import { ajax } from "discourse/lib/ajax";
import getURL from "discourse-common/lib/get-url";
export const DefaultNotificationItem = createWidget( export const DefaultNotificationItem = createWidget(
"default-notification-item", "default-notification-item",
@ -46,9 +47,7 @@ export const DefaultNotificationItem = createWidget(
let username = data.username; let username = data.username;
username = username ? "?username=" + username.toLowerCase() : ""; username = username ? "?username=" + username.toLowerCase() : "";
return Discourse.getURL( return getURL("/badges/" + badgeId + "/" + badgeSlug + username);
"/badges/" + badgeId + "/" + badgeSlug + username
);
} }
const topicId = attrs.topic_id; const topicId = attrs.topic_id;
@ -134,8 +133,9 @@ export const DefaultNotificationItem = createWidget(
const id = this.attrs.id; const id = this.attrs.id;
setTransientHeader("Discourse-Clear-Notifications", id); setTransientHeader("Discourse-Clear-Notifications", id);
if (document && document.cookie) { if (document && document.cookie) {
let path = Discourse.BaseUri || "/"; document.cookie = `cn=${id}; path=${getURL(
document.cookie = `cn=${id}; path=${path}; expires=Fri, 31 Dec 9999 23:59:59 GMT`; "/"
)}; expires=Fri, 31 Dec 9999 23:59:59 GMT`;
} }
if (wantsNewWindow(e)) { if (wantsNewWindow(e)) {
return; return;

View File

@ -1,3 +1,4 @@
import getURL from "discourse-common/lib/get-url";
import I18n from "I18n"; import I18n from "I18n";
import { createWidget } from "discourse/widgets/widget"; import { createWidget } from "discourse/widgets/widget";
import { h } from "virtual-dom"; import { h } from "virtual-dom";
@ -52,7 +53,7 @@ export default createWidget("hamburger-categories", {
tagName: "ul.category-links.clearfix", tagName: "ul.category-links.clearfix",
html(attrs) { html(attrs) {
const href = Discourse.getURL("/categories"); const href = getURL("/categories");
let title = I18n.t("filters.categories.title"); let title = I18n.t("filters.categories.title");
if (attrs.moreCount > 0) { if (attrs.moreCount > 0) {
title = I18n.t("categories.n_more", { count: attrs.moreCount }); title = I18n.t("categories.n_more", { count: attrs.moreCount });

View File

@ -1,3 +1,4 @@
import getURL from "discourse-common/lib/get-url";
import I18n from "I18n"; import I18n from "I18n";
import { later } from "@ember/runloop"; import { later } from "@ember/runloop";
import { createWidget, applyDecorators } from "discourse/widgets/widget"; import { createWidget, applyDecorators } from "discourse/widgets/widget";
@ -269,7 +270,7 @@ export default createWidget("hamburger-menu", {
let faqUrl = this.siteSettings.faq_url; let faqUrl = this.siteSettings.faq_url;
if (!faqUrl || faqUrl.length === 0) { if (!faqUrl || faqUrl.length === 0) {
faqUrl = Discourse.getURL("/faq"); faqUrl = getURL("/faq");
} }
const prioritizeFaq = const prioritizeFaq =

View File

@ -1,3 +1,4 @@
import getURL from "discourse-common/lib/get-url";
import I18n from "I18n"; import I18n from "I18n";
import { applyDecorators, createWidget } from "discourse/widgets/widget"; import { applyDecorators, createWidget } from "discourse/widgets/widget";
import { h } from "virtual-dom"; import { h } from "virtual-dom";
@ -27,7 +28,7 @@ createWidget("topic-header-participant", {
url = user.get("path"); url = user.get("path");
} else { } else {
content = [iconNode("users")]; content = [iconNode("users")];
url = Discourse.getURL(`/g/${group.name}`); url = getURL(`/g/${group.name}`);
content.push(h("span", group.name)); content.push(h("span", group.name));
} }

View File

@ -1,3 +1,4 @@
import getURL from "discourse-common/lib/get-url";
import I18n from "I18n"; import I18n from "I18n";
import { get } from "@ember/object"; import { get } from "@ember/object";
import { schedule } from "@ember/runloop"; import { schedule } from "@ember/runloop";
@ -217,7 +218,7 @@ createWidget("header-icons", {
iconId: "search-button", iconId: "search-button",
action: "toggleSearchMenu", action: "toggleSearchMenu",
active: attrs.searchVisible, active: attrs.searchVisible,
href: Discourse.getURL("/search") href: getURL("/search")
}); });
const icons = [search, hamburger]; const icons = [search, hamburger];

View File

@ -1,3 +1,4 @@
import getURL from "discourse-common/lib/get-url";
import { createWidget } from "discourse/widgets/widget"; import { createWidget } from "discourse/widgets/widget";
import { h } from "virtual-dom"; import { h } from "virtual-dom";
import { iconNode } from "discourse-common/lib/icon-library"; import { iconNode } from "discourse-common/lib/icon-library";
@ -8,7 +9,7 @@ export default createWidget("home-logo", {
tagName: "div.title", tagName: "div.title",
settings: { settings: {
href: Discourse.getURL("/") href: getURL("/")
}, },
href() { href() {
@ -44,7 +45,7 @@ export default createWidget("home-logo", {
return h("img#site-logo.logo-small", { return h("img#site-logo.logo-small", {
key: "logo-small", key: "logo-small",
attributes: { attributes: {
src: Discourse.getURL(logoSmallUrl), src: getURL(logoSmallUrl),
width: 36, width: 36,
alt: title alt: title
} }
@ -55,12 +56,12 @@ export default createWidget("home-logo", {
} else if (showMobileLogo) { } else if (showMobileLogo) {
return h("img#site-logo.logo-big", { return h("img#site-logo.logo-big", {
key: "logo-mobile", key: "logo-mobile",
attributes: { src: Discourse.getURL(mobileLogoUrl), alt: title } attributes: { src: getURL(mobileLogoUrl), alt: title }
}); });
} else if (logoUrl.length) { } else if (logoUrl.length) {
return h("img#site-logo.logo-big", { return h("img#site-logo.logo-big", {
key: "logo-big", key: "logo-big",
attributes: { src: Discourse.getURL(logoUrl), alt: title } attributes: { src: getURL(logoUrl), alt: title }
}); });
} else { } else {
return h("h1#site-text-logo.text-logo", { key: "logo-text" }, title); return h("h1#site-text-logo.text-logo", { key: "logo-text" }, title);

View File

@ -1,3 +1,4 @@
import getURL from "discourse-common/lib/get-url";
import I18n from "I18n"; import I18n from "I18n";
import { wantsNewWindow } from "discourse/lib/intercept-click"; import { wantsNewWindow } from "discourse/lib/intercept-click";
import { createWidget } from "discourse/widgets/widget"; import { createWidget } from "discourse/widgets/widget";
@ -17,12 +18,12 @@ export default createWidget("link", {
if (attrs.model) { if (attrs.model) {
params.push(attrs.model); params.push(attrs.model);
} }
return Discourse.getURL( return getURL(
router._routerMicrolib.generate.apply(router._routerMicrolib, params) router._routerMicrolib.generate.apply(router._routerMicrolib, params)
); );
} }
} else { } else {
return Discourse.getURL(attrs.href); return getURL(attrs.href);
} }
}, },

View File

@ -1,3 +1,4 @@
import { default as getURL, getURLWithCDN } from "discourse-common/lib/get-url";
import I18n from "I18n"; import I18n from "I18n";
import PostCooked from "discourse/widgets/post-cooked"; import PostCooked from "discourse/widgets/post-cooked";
import DecoratorHelper from "discourse/widgets/decorator-helper"; import DecoratorHelper from "discourse/widgets/decorator-helper";
@ -43,7 +44,7 @@ export function avatarImg(wanted, attrs) {
alt: "", alt: "",
width: size, width: size,
height: size, height: size,
src: Discourse.getURLWithCDN(url), src: getURLWithCDN(url),
title title
}, },
className className
@ -353,7 +354,7 @@ createWidget("post-group-request", {
}, },
html(attrs) { html(attrs) {
const href = Discourse.getURL( const href = getURL(
"/g/" + attrs.requestedGroupName + "/requests?filter=" + attrs.username "/g/" + attrs.requestedGroupName + "/requests?filter=" + attrs.username
); );

View File

@ -1,3 +1,4 @@
import getURL from "discourse-common/lib/get-url";
import I18n from "I18n"; import I18n from "I18n";
import { iconNode } from "discourse-common/lib/icon-library"; import { iconNode } from "discourse-common/lib/icon-library";
import { createWidget, applyDecorators } from "discourse/widgets/widget"; import { createWidget, applyDecorators } from "discourse/widgets/widget";
@ -19,7 +20,7 @@ createWidget("poster-name-title", {
html(attrs) { html(attrs) {
let titleContents = attrs.title; let titleContents = attrs.title;
if (attrs.primaryGroupName && attrs.titleIsGroup) { if (attrs.primaryGroupName && attrs.titleIsGroup) {
const href = Discourse.getURL(`/g/${attrs.primaryGroupName}`); const href = getURL(`/g/${attrs.primaryGroupName}`);
titleContents = h( titleContents = h(
"a.user-group", "a.user-group",
{ {

View File

@ -1,3 +1,4 @@
import getURL from "discourse-common/lib/get-url";
import I18n from "I18n"; import I18n from "I18n";
import { makeArray } from "discourse-common/lib/helpers"; import { makeArray } from "discourse-common/lib/helpers";
import { createWidget } from "discourse/widgets/widget"; import { createWidget } from "discourse/widgets/widget";
@ -27,7 +28,7 @@ createWidget("pm-map-user-group", {
tagName: "div.user.group", tagName: "div.user.group",
transform(attrs) { transform(attrs) {
return { href: Discourse.getURL(`/g/${attrs.group.name}`) }; return { href: getURL(`/g/${attrs.group.name}`) };
}, },
template: hbs` template: hbs`

View File

@ -1,3 +1,4 @@
import getURL from "discourse-common/lib/get-url";
import { get } from "@ember/object"; import { get } from "@ember/object";
import { debounce } from "@ember/runloop"; import { debounce } from "@ember/runloop";
import { popupAjaxError } from "discourse/lib/ajax-error"; import { popupAjaxError } from "discourse/lib/ajax-error";
@ -118,7 +119,7 @@ export default createWidget("search-menu", {
url = `${url}?${params.join("&")}`; url = `${url}?${params.join("&")}`;
} }
return Discourse.getURL(url); return getURL(url);
}, },
panelContents() { panelContents() {

View File

@ -1,3 +1,4 @@
import getURL from "discourse-common/lib/get-url";
import I18n from "I18n"; import I18n from "I18n";
import { readOnly } from "@ember/object/computed"; import { readOnly } from "@ember/object/computed";
import { computed } from "@ember/object"; import { computed } from "@ember/object";
@ -126,14 +127,14 @@ export default ComboBoxComponent.extend({
"parentCategoryUrl", "parentCategoryUrl",
"selectKit.options.subCategory", "selectKit.options.subCategory",
function() { function() {
return Discourse.getURL( return getURL(
this.selectKit.options.subCategory ? this.parentCategoryUrl || "/" : "/" this.selectKit.options.subCategory ? this.parentCategoryUrl || "/" : "/"
); );
} }
), ),
noCategoriesUrl: computed("parentCategoryUrl", function() { noCategoriesUrl: computed("parentCategoryUrl", function() {
return Discourse.getURL(`${this.parentCategoryUrl}/none`); return getURL(`${this.parentCategoryUrl}/none`);
}), }),
search(filter) { search(filter) {

View File

@ -1,3 +1,4 @@
import getURL from "discourse-common/lib/get-url";
import Category from "discourse/models/category"; import Category from "discourse/models/category";
import { readOnly, or, equal, gte } from "@ember/object/computed"; import { readOnly, or, equal, gte } from "@ember/object/computed";
import { i18n, setting } from "discourse/lib/computed"; import { i18n, setting } from "discourse/lib/computed";
@ -73,9 +74,9 @@ export default ComboBoxComponent.extend(TagsMixin, {
allTagsUrl: computed("firstCategory", "secondCategory", function() { allTagsUrl: computed("firstCategory", "secondCategory", function() {
if (this.currentCategory) { if (this.currentCategory) {
return Discourse.getURL(`${this.currentCategoryUrl}?allTags=1`); return getURL(`${this.currentCategoryUrl}?allTags=1`);
} else { } else {
return Discourse.getURL("/"); return getURL("/");
} }
}), }),
@ -86,7 +87,7 @@ export default ComboBoxComponent.extend(TagsMixin, {
this.currentCategory.id this.currentCategory.id
}`; }`;
} }
return Discourse.getURL(`${url}/${NONE_TAG_ID}`); return getURL(`${url}/${NONE_TAG_ID}`);
}), }),
allTagsLabel: i18n("tagging.selector_all_tags"), allTagsLabel: i18n("tagging.selector_all_tags"),
@ -189,7 +190,7 @@ export default ComboBoxComponent.extend(TagsMixin, {
} }
} }
DiscourseURL.routeTo(Discourse.getURL(url)); DiscourseURL.routeTo(getURL(url));
} }
} }
}); });

View File

@ -1,3 +1,4 @@
import getURL from "discourse-common/lib/get-url";
import I18n from "I18n"; import I18n from "I18n";
import { reads } from "@ember/object/computed"; import { reads } from "@ember/object/computed";
import { ajax } from "discourse/lib/ajax"; import { ajax } from "discourse/lib/ajax";
@ -8,7 +9,7 @@ import { isEmpty } from "@ember/utils";
export default Mixin.create({ export default Mixin.create({
searchTags(url, data, callback) { searchTags(url, data, callback) {
return ajax(Discourse.getURL(url), { return ajax(getURL(url), {
quietMillis: 200, quietMillis: 200,
cache: true, cache: true,
dataType: "json", dataType: "json",

View File

@ -86,6 +86,7 @@ module PrettyText
ctx_load_manifest(ctx, "markdown-it-bundle.js") ctx_load_manifest(ctx, "markdown-it-bundle.js")
root_path = "#{Rails.root}/app/assets/javascripts/" 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/to-markdown")
apply_es6_file(ctx, root_path, "discourse/app/lib/utilities") apply_es6_file(ctx, root_path, "discourse/app/lib/utilities")

View File

@ -9,6 +9,7 @@ import {
url, url,
htmlSafe htmlSafe
} from "discourse/lib/computed"; } from "discourse/lib/computed";
import { setPrefix } from "discourse-common/lib/get-url";
QUnit.module("lib:computed", { QUnit.module("lib:computed", {
beforeEach() { beforeEach() {
@ -148,7 +149,7 @@ QUnit.test("url", assert => {
"it supports urls without a prefix" "it supports urls without a prefix"
); );
Discourse.BaseUri = "/prefixed"; setPrefix("/prefixed");
t = testClass.create({ username: "eviltrout" }); t = testClass.create({ username: "eviltrout" });
assert.equal( assert.equal(
t.get("userUrl"), t.get("userUrl"),

View File

@ -2,43 +2,6 @@ import { logIn, updateCurrentUser } from "helpers/qunit-helpers";
QUnit.module("lib:discourse"); 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 => { QUnit.test("title counts are updated correctly", assert => {
Discourse.set("hasFocus", true); Discourse.set("hasFocus", true);
Discourse.set("contextCount", 0); Discourse.set("contextCount", 0);

View File

@ -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");
});

View File

@ -1,4 +1,5 @@
import DiscourseURL, { userPath } from "discourse/lib/url"; import DiscourseURL, { userPath } from "discourse/lib/url";
import { setPrefix } from "discourse-common/lib/get-url";
QUnit.module("lib:url"); QUnit.module("lib:url");
@ -59,8 +60,8 @@ QUnit.test("userPath", assert => {
assert.equal(userPath("hp.json"), "/u/hp.json"); assert.equal(userPath("hp.json"), "/u/hp.json");
}); });
QUnit.test("userPath with BaseUri", assert => { QUnit.test("userPath with prefix", assert => {
Discourse.BaseUri = "/forum"; setPrefix("/forum");
assert.equal(userPath(), "/forum/u"); assert.equal(userPath(), "/forum/u");
assert.equal(userPath("eviltrout"), "/forum/u/eviltrout"); assert.equal(userPath("eviltrout"), "/forum/u/eviltrout");
assert.equal(userPath("hp.json"), "/forum/u/hp.json"); assert.equal(userPath("hp.json"), "/forum/u/hp.json");

View File

@ -1,4 +1,5 @@
import EmailLog from "admin/models/email-log"; import EmailLog from "admin/models/email-log";
import { setPrefix } from "discourse-common/lib/get-url";
QUnit.module("Discourse.EmailLog"); QUnit.module("Discourse.EmailLog");
@ -7,7 +8,7 @@ QUnit.test("create", assert => {
}); });
QUnit.test("subfolder support", assert => { QUnit.test("subfolder support", assert => {
Discourse.BaseUri = "/forum"; setPrefix("/forum");
const attrs = { const attrs = {
id: 60, id: 60,
to_address: "wikiman@asdf.com", to_address: "wikiman@asdf.com",

View File

@ -1,4 +1,5 @@
import Report from "admin/models/report"; import Report from "admin/models/report";
import { setPrefix } from "discourse-common/lib/get-url";
QUnit.module("Report"); QUnit.module("Report");
@ -528,7 +529,7 @@ QUnit.test("computed labels", assert => {
assert.equal(computedFilesizeLabel.value, 582641); assert.equal(computedFilesizeLabel.value, 582641);
// subfolder support // subfolder support
Discourse.BaseUri = "/forum"; setPrefix("/forum");
const postLink = computedLabels[5].compute(row).formatedValue; const postLink = computedLabels[5].compute(row).formatedValue;
assert.equal( assert.equal(

View File

@ -151,8 +151,10 @@ QUnit.testStart(function(ctx) {
// Allow our tests to change site settings and have them reset before the next test // Allow our tests to change site settings and have them reset before the next test
Discourse.SiteSettings = dup(Discourse.SiteSettingsOriginal); 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 User = require("discourse/models/user").default;
let Session = require("discourse/models/session").default; let Session = require("discourse/models/session").default;

View File

@ -1,4 +1,5 @@
import { moduleForWidget, widgetTest } from "helpers/widget-test"; import { moduleForWidget, widgetTest } from "helpers/widget-test";
import { setPrefix } from "discourse-common/lib/get-url";
moduleForWidget("home-logo"); moduleForWidget("home-logo");
@ -101,7 +102,7 @@ widgetTest("mobile without logo", {
widgetTest("basics, subfolder", { widgetTest("basics, subfolder", {
template: '{{mount-widget widget="home-logo" args=args}}', template: '{{mount-widget widget="home-logo" args=args}}',
beforeEach() { beforeEach() {
Discourse.BaseUri = "/forum"; setPrefix("/forum");
this.siteSettings.site_logo_url = bigLogo; this.siteSettings.site_logo_url = bigLogo;
this.siteSettings.site_logo_small_url = smallLogo; this.siteSettings.site_logo_small_url = smallLogo;
this.siteSettings.title = title; this.siteSettings.title = title;
@ -118,7 +119,7 @@ widgetTest("basics, subfolder", {
widgetTest("basics, subfolder - minimized", { widgetTest("basics, subfolder - minimized", {
template: '{{mount-widget widget="home-logo" args=args}}', template: '{{mount-widget widget="home-logo" args=args}}',
beforeEach() { beforeEach() {
Discourse.BaseUri = "/forum"; setPrefix("/forum");
this.siteSettings.site_logo_url = bigLogo; this.siteSettings.site_logo_url = bigLogo;
this.siteSettings.site_logo_small_url = smallLogo; this.siteSettings.site_logo_small_url = smallLogo;
this.siteSettings.title = title; this.siteSettings.title = title;
@ -135,7 +136,7 @@ widgetTest("basics, subfolder - minimized", {
widgetTest("mobile logo, subfolder", { widgetTest("mobile logo, subfolder", {
template: '{{mount-widget widget="home-logo" args=args}}', template: '{{mount-widget widget="home-logo" args=args}}',
beforeEach() { beforeEach() {
Discourse.BaseUri = "/forum"; setPrefix("/forum");
this.siteSettings.site_mobile_logo_url = mobileLogo; this.siteSettings.site_mobile_logo_url = mobileLogo;
this.siteSettings.site_logo_small_url = smallLogo; this.siteSettings.site_logo_small_url = smallLogo;
this.site.mobileView = true; this.site.mobileView = true;