diff --git a/src/core/features/compile/services/compile.ts b/src/core/features/compile/services/compile.ts index 3803dbe44..958de26c1 100644 --- a/src/core/features/compile/services/compile.ts +++ b/src/core/features/compile/services/compile.ts @@ -78,6 +78,7 @@ import { Md5 } from 'ts-md5/dist/md5'; // Import core classes that can be useful for site plugins. import { CoreSyncBaseProvider } from '@classes/base-sync'; import { CoreArray } from '@singletons/array'; +import { CoreText } from '@singletons/text'; import { CoreUrl } from '@singletons/url'; import { CoreWindow } from '@singletons/window'; import { CoreCache } from '@classes/cache'; @@ -340,6 +341,7 @@ export class CoreCompileProvider { instance['Md5'] = Md5; instance['CoreSyncBaseProvider'] = CoreSyncBaseProvider; instance['CoreArray'] = CoreArray; + instance['CoreText'] = CoreText; instance['CoreUrl'] = CoreUrl; instance['CoreWindow'] = CoreWindow; instance['CoreCache'] = CoreCache; diff --git a/src/core/services/sites.ts b/src/core/services/sites.ts index 299be92e0..80a940dcb 100644 --- a/src/core/services/sites.ts +++ b/src/core/services/sites.ts @@ -52,6 +52,7 @@ import { CoreArray } from '../singletons/array'; import { CoreNetworkError } from '@classes/errors/network-error'; import { CoreNavigationOptions } from './navigator'; import { CoreSitesFactory } from './sites-factory'; +import { CoreText } from '@singletons/text'; export const CORE_SITE_SCHEMAS = new InjectionToken('CORE_SITE_SCHEMAS'); @@ -1635,10 +1636,10 @@ export class CoreSitesProvider { // If more than one site is returned it usually means there are different users stored. Use any of them. const site = await this.getSite(siteIds[0]); - const siteUrl = CoreTextUtils.removeEndingSlash( + const siteUrl = CoreText.removeEndingSlash( CoreUrlUtils.removeProtocolAndWWW(site.getURL()), ); - const treatedUrl = CoreTextUtils.removeEndingSlash(CoreUrlUtils.removeProtocolAndWWW(url)); + const treatedUrl = CoreText.removeEndingSlash(CoreUrlUtils.removeProtocolAndWWW(url)); if (siteUrl == treatedUrl) { result.site = site; diff --git a/src/core/services/utils/text.ts b/src/core/services/utils/text.ts index 310e12b3b..cc8428e69 100644 --- a/src/core/services/utils/text.ts +++ b/src/core/services/utils/text.ts @@ -25,6 +25,7 @@ import { Locutus } from '@singletons/locutus'; import { CoreViewerTextComponent } from '@features/viewer/components/text/text'; import { CoreFileHelper } from '@services/file-helper'; import { CoreDomUtils } from './dom'; +import { CoreText } from '@singletons/text'; /** * Different type of errors the app can treat. @@ -710,21 +711,10 @@ export class CoreTextUtilsProvider { } /** - * Remove ending slash from a path or URL. - * - * @param text Text to treat. - * @return Treated text. + * @deprecated Use CoreText instead. */ removeEndingSlash(text?: string): string { - if (!text) { - return ''; - } - - if (text.slice(-1) == '/') { - return text.substr(0, text.length - 1); - } - - return text; + return CoreText.removeEndingSlash(text); } /** diff --git a/src/core/singletons/tests/url.test.ts b/src/core/singletons/tests/url.test.ts index c9a7a4f95..b15d0e918 100644 --- a/src/core/singletons/tests/url.test.ts +++ b/src/core/singletons/tests/url.test.ts @@ -43,4 +43,17 @@ describe('CoreUrl singleton', () => { }); }); + it('compares domains and paths', () => { + expect(CoreUrl.sameDomainAndPath('https://school.edu', 'https://school.edu')).toBe(true); + expect(CoreUrl.sameDomainAndPath('https://school.edu', 'HTTPS://SCHOOL.EDU')).toBe(true); + expect(CoreUrl.sameDomainAndPath('https://school.edu/moodle', 'https://school.edu/moodle')).toBe(true); + expect(CoreUrl.sameDomainAndPath('https://school.edu/moodle', 'https://school.edu/moodle/')).toBe(true); + expect(CoreUrl.sameDomainAndPath('https://school.edu/moodle', 'https://school.edu/moodle#about')).toBe(true); + expect(CoreUrl.sameDomainAndPath('https://school.edu/moodle', 'HTTPS://SCHOOL.EDU/MOODLE')).toBe(true); + expect(CoreUrl.sameDomainAndPath('https://school.edu/moodle', 'HTTPS://SCHOOL.EDU/MOODLE/')).toBe(true); + expect(CoreUrl.sameDomainAndPath('https://school.edu/moodle', 'HTTPS://SCHOOL.EDU/MOODLE#ABOUT')).toBe(true); + + expect(CoreUrl.sameDomainAndPath('https://school.edu/moodle', 'https://school.edu/moodle/about')).toBe(false); + }); + }); diff --git a/src/core/singletons/text.ts b/src/core/singletons/text.ts new file mode 100644 index 000000000..c95fa2a5b --- /dev/null +++ b/src/core/singletons/text.ts @@ -0,0 +1,43 @@ +// (C) Copyright 2015 Moodle Pty Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** + * Singleton with helper functions for text manipulation. + */ +export class CoreText { + + // Avoid creating singleton instances. + private constructor() { + // Nothing to do. + } + + /** + * Remove ending slash from a path or URL. + * + * @param text Text to treat. + * @return Treated text. + */ + static removeEndingSlash(text?: string): string { + if (!text) { + return ''; + } + + if (text.slice(-1) == '/') { + return text.substr(0, text.length - 1); + } + + return text; + } + +} diff --git a/src/core/singletons/url.ts b/src/core/singletons/url.ts index 2f38ffbe5..5c8b1f10f 100644 --- a/src/core/singletons/url.ts +++ b/src/core/singletons/url.ts @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { CoreTextUtils } from '@services/utils/text'; +import { CoreText } from './text'; /** * Parts contained within a url. @@ -196,8 +196,11 @@ export class CoreUrl { const partsA = CoreUrl.parse(urlA); const partsB = CoreUrl.parse(urlB); - return partsA?.domain == partsB?.domain && - CoreTextUtils.removeEndingSlash(partsA?.path) == CoreTextUtils.removeEndingSlash(partsB?.path); + partsA && Object.entries(partsA).forEach(([part, value]) => partsA[part] = value?.toLowerCase()); + partsB && Object.entries(partsB).forEach(([part, value]) => partsB[part] = value?.toLowerCase()); + + return partsA?.domain === partsB?.domain + && CoreText.removeEndingSlash(partsA?.path) === CoreText.removeEndingSlash(partsB?.path); } }