forked from EVOgeek/Vmeda.Online
		
	MOBILE-4081 h5p: Fix H5P assets broken on iOS update
This commit is contained in:
		
							parent
							
								
									bf98c699da
								
							
						
					
					
						commit
						51ba1186d5
					
				@ -18,6 +18,7 @@ import { CoreSites } from '@services/sites';
 | 
				
			|||||||
import { CoreMimetypeUtils } from '@services/utils/mimetype';
 | 
					import { CoreMimetypeUtils } from '@services/utils/mimetype';
 | 
				
			||||||
import { CoreTextUtils } from '@services/utils/text';
 | 
					import { CoreTextUtils } from '@services/utils/text';
 | 
				
			||||||
import { CoreUtils } from '@services/utils/utils';
 | 
					import { CoreUtils } from '@services/utils/utils';
 | 
				
			||||||
 | 
					import { CorePath } from '@singletons/path';
 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
    CoreH5PCore,
 | 
					    CoreH5PCore,
 | 
				
			||||||
    CoreH5PDependencyAsset,
 | 
					    CoreH5PDependencyAsset,
 | 
				
			||||||
@ -64,7 +65,7 @@ export class CoreH5PFileStorage {
 | 
				
			|||||||
            const path = CoreText.concatenatePaths(cachedAssetsPath, fileName);
 | 
					            const path = CoreText.concatenatePaths(cachedAssetsPath, fileName);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Store concatenated content.
 | 
					            // Store concatenated content.
 | 
				
			||||||
            const content = await this.concatenateFiles(assets, type);
 | 
					            const content = await this.concatenateFiles(assets, type, cachedAssetsPath);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            await CoreFile.writeFile(path, content);
 | 
					            await CoreFile.writeFile(path, content);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -82,11 +83,11 @@ export class CoreH5PFileStorage {
 | 
				
			|||||||
     * Adds all files of a type into one file.
 | 
					     * Adds all files of a type into one file.
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @param assets A list of files.
 | 
					     * @param assets A list of files.
 | 
				
			||||||
     * @param type The type of files in assets. Either 'scripts' or 'styles'
 | 
					     * @param type The type of files in assets. Either 'scripts' or 'styles'.
 | 
				
			||||||
 | 
					     * @param newFolder The new folder where the concatenated content will be stored.
 | 
				
			||||||
     * @return Promise resolved with all of the files content in one string.
 | 
					     * @return Promise resolved with all of the files content in one string.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    protected async concatenateFiles(assets: CoreH5PDependencyAsset[], type: string): Promise<string> {
 | 
					    protected async concatenateFiles(assets: CoreH5PDependencyAsset[], type: string, newFolder: string): Promise<string> {
 | 
				
			||||||
        const basePath = CoreFile.convertFileSrc(CoreFile.getBasePathInstant());
 | 
					 | 
				
			||||||
        let content = '';
 | 
					        let content = '';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for (const i in assets) {
 | 
					        for (const i in assets) {
 | 
				
			||||||
@ -104,46 +105,22 @@ export class CoreH5PFileStorage {
 | 
				
			|||||||
            // Rewrite relative URLs used inside stylesheets.
 | 
					            // Rewrite relative URLs used inside stylesheets.
 | 
				
			||||||
            const matches = fileContent.match(/url\(['"]?([^"')]+)['"]?\)/ig);
 | 
					            const matches = fileContent.match(/url\(['"]?([^"')]+)['"]?\)/ig);
 | 
				
			||||||
            const assetPath = asset.path.replace(/(^\/|\/$)/g, ''); // Path without start/end slashes.
 | 
					            const assetPath = asset.path.replace(/(^\/|\/$)/g, ''); // Path without start/end slashes.
 | 
				
			||||||
            const treated = {};
 | 
					            const treated: Record<string, string> = {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (matches && matches.length) {
 | 
					            if (matches && matches.length) {
 | 
				
			||||||
                matches.forEach((match) => {
 | 
					                matches.forEach((match) => {
 | 
				
			||||||
                    let url = match.replace(/(url\(['"]?|['"]?\)$)/ig, '');
 | 
					                    const url = match.replace(/(url\(['"]?|['"]?\)$)/ig, '');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    if (treated[url] || url.match(/^(data:|([a-z0-9]+:)?\/)/i)) {
 | 
					                    if (treated[url] || url.match(/^(data:|([a-z0-9]+:)?\/)/i)) {
 | 
				
			||||||
                        return; // Not relative or already treated, skip.
 | 
					                        return; // Not relative or already treated, skip.
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    const pathSplit = assetPath.split('/');
 | 
					 | 
				
			||||||
                    treated[url] = url;
 | 
					                    treated[url] = url;
 | 
				
			||||||
 | 
					                    const assetPathFolder = CoreFile.getFileAndDirectoryFromPath(assetPath).directory;
 | 
				
			||||||
                    /* Find "../" in the URL. If it exists, we have to remove "../" and switch the last folder in the
 | 
					 | 
				
			||||||
                        filepath for the first folder in the url. */
 | 
					 | 
				
			||||||
                    if (url.match(/^\.\.\//)) {
 | 
					 | 
				
			||||||
                        // Split and remove empty values.
 | 
					 | 
				
			||||||
                        const urlSplit = url.split('/').filter((i) => i);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                        // Remove the file name from the asset path.
 | 
					 | 
				
			||||||
                        pathSplit.pop();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                        // Remove the first element from the file URL: ../ .
 | 
					 | 
				
			||||||
                        urlSplit.shift();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                        // Put the url's first folder into the asset path.
 | 
					 | 
				
			||||||
                        pathSplit[pathSplit.length - 1] = urlSplit[0];
 | 
					 | 
				
			||||||
                        urlSplit.shift();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                        // Create the new URL and replace it in the file contents.
 | 
					 | 
				
			||||||
                        url = pathSplit.join('/') + '/' + urlSplit.join('/');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    } else {
 | 
					 | 
				
			||||||
                        pathSplit[pathSplit.length - 1] = url; // Put the whole path to the end of the asset path.
 | 
					 | 
				
			||||||
                        url = pathSplit.join('/');
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    fileContent = fileContent.replace(
 | 
					                    fileContent = fileContent.replace(
 | 
				
			||||||
                        new RegExp(CoreTextUtils.escapeForRegex(match), 'g'),
 | 
					                        new RegExp(CoreTextUtils.escapeForRegex(match), 'g'),
 | 
				
			||||||
                        'url("' + CoreText.concatenatePaths(basePath, url) + '")',
 | 
					                        'url("' + CorePath.changeRelativePath(assetPathFolder, url, newFolder) + '")',
 | 
				
			||||||
                    );
 | 
					                    );
 | 
				
			||||||
                });
 | 
					                });
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
				
			|||||||
@ -25,8 +25,8 @@ import { CoreUtils } from './utils/utils';
 | 
				
			|||||||
import { CoreApp } from './app';
 | 
					import { CoreApp } from './app';
 | 
				
			||||||
import { CoreZoomLevel } from '@features/settings/services/settings-helper';
 | 
					import { CoreZoomLevel } from '@features/settings/services/settings-helper';
 | 
				
			||||||
import { CorePromisedValue } from '@classes/promised-value';
 | 
					import { CorePromisedValue } from '@classes/promised-value';
 | 
				
			||||||
 | 
					import { CoreFile } from './file';
 | 
				
			||||||
const VERSION_APPLIED = 'version_applied';
 | 
					import { CorePlatform } from './platform';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Factory to handle app updates. This factory shouldn't be used outside of core.
 | 
					 * Factory to handle app updates. This factory shouldn't be used outside of core.
 | 
				
			||||||
@ -36,6 +36,9 @@ const VERSION_APPLIED = 'version_applied';
 | 
				
			|||||||
@Injectable({ providedIn: 'root' })
 | 
					@Injectable({ providedIn: 'root' })
 | 
				
			||||||
export class CoreUpdateManagerProvider {
 | 
					export class CoreUpdateManagerProvider {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected static readonly VERSION_APPLIED = 'version_applied';
 | 
				
			||||||
 | 
					    protected static readonly PREVIOUS_APP_FOLDER = 'previous_app_folder';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected logger: CoreLogger;
 | 
					    protected logger: CoreLogger;
 | 
				
			||||||
    protected doneDeferred: CorePromisedValue<void>;
 | 
					    protected doneDeferred: CorePromisedValue<void>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -63,13 +66,22 @@ export class CoreUpdateManagerProvider {
 | 
				
			|||||||
        const promises: Promise<unknown>[] = [];
 | 
					        const promises: Promise<unknown>[] = [];
 | 
				
			||||||
        const versionCode = CoreConstants.CONFIG.versioncode;
 | 
					        const versionCode = CoreConstants.CONFIG.versioncode;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const versionApplied = await CoreConfig.get<number>(VERSION_APPLIED, 0);
 | 
					        const [versionApplied, previousAppFolder, currentAppFolder] = await Promise.all([
 | 
				
			||||||
 | 
					            CoreConfig.get<number>(CoreUpdateManagerProvider.VERSION_APPLIED, 0),
 | 
				
			||||||
 | 
					            CoreConfig.get<string>(CoreUpdateManagerProvider.PREVIOUS_APP_FOLDER, ''),
 | 
				
			||||||
 | 
					            CorePlatform.isMobile() ? CoreUtils.ignoreErrors(CoreFile.getBasePath(), '') : '',
 | 
				
			||||||
 | 
					        ]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (versionCode > versionApplied) {
 | 
					        if (versionCode > versionApplied) {
 | 
				
			||||||
            promises.push(this.checkCurrentSiteAllowed());
 | 
					            promises.push(this.checkCurrentSiteAllowed());
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (versionCode >= 3950 && versionApplied < 3950 && versionApplied > 0) {
 | 
					        if (
 | 
				
			||||||
 | 
					            (versionCode >= 3950 && versionApplied < 3950 && versionApplied > 0) ||
 | 
				
			||||||
 | 
					            (currentAppFolder && currentAppFolder !== previousAppFolder)
 | 
				
			||||||
 | 
					        ) {
 | 
				
			||||||
 | 
					            // Delete content indexes if the app folder has changed.
 | 
				
			||||||
 | 
					            // This happens in iOS every time the app is updated, even if the version hasn't changed.
 | 
				
			||||||
            promises.push(CoreH5P.h5pPlayer.deleteAllContentIndexes());
 | 
					            promises.push(CoreH5P.h5pPlayer.deleteAllContentIndexes());
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -80,7 +92,10 @@ export class CoreUpdateManagerProvider {
 | 
				
			|||||||
        try {
 | 
					        try {
 | 
				
			||||||
            await Promise.all(promises);
 | 
					            await Promise.all(promises);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            await CoreConfig.set(VERSION_APPLIED, versionCode);
 | 
					            await Promise.all([
 | 
				
			||||||
 | 
					                CoreConfig.set(CoreUpdateManagerProvider.VERSION_APPLIED, versionCode),
 | 
				
			||||||
 | 
					                currentAppFolder ? CoreConfig.set(CoreUpdateManagerProvider.PREVIOUS_APP_FOLDER, currentAppFolder) : undefined,
 | 
				
			||||||
 | 
					            ]);
 | 
				
			||||||
        } catch (error) {
 | 
					        } catch (error) {
 | 
				
			||||||
            this.logger.error(`Error applying update from ${versionApplied} to ${versionCode}`, error);
 | 
					            this.logger.error(`Error applying update from ${versionApplied} to ${versionCode}`, error);
 | 
				
			||||||
        } finally {
 | 
					        } finally {
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										102
									
								
								src/core/singletons/path.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										102
									
								
								src/core/singletons/path.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,102 @@
 | 
				
			|||||||
 | 
					// (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.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { CoreText } from './text';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Singleton with helper functions for paths.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export class CorePath {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Avoid creating singleton instances.
 | 
				
			||||||
 | 
					    private constructor() {
 | 
				
			||||||
 | 
					        // Nothing to do.
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Calculate a relative path from a folder to another folder.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * E.g. if initial folder is foo/bar, and final folder is foo/baz/xyz, it will return ../bar/xyz.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param initialFolder The initial folder path.
 | 
				
			||||||
 | 
					     * @param finalFolder The final folder. The "root" should be the same as initialFolder.
 | 
				
			||||||
 | 
					     * @return Relative path.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    static calculateRelativePath(initialFolder: string, finalFolder: string): string {
 | 
				
			||||||
 | 
					        initialFolder = CoreText.removeStartingSlash(CoreText.removeEndingSlash(initialFolder));
 | 
				
			||||||
 | 
					        finalFolder = CoreText.removeStartingSlash(CoreText.removeEndingSlash(finalFolder));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (initialFolder === finalFolder) {
 | 
				
			||||||
 | 
					            return '';
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const initialFolderSplit = initialFolder === '' ? [] : initialFolder.split('/');
 | 
				
			||||||
 | 
					        const finalFolderSplit = finalFolder === '' ? [] : finalFolder.split('/');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let firstDiffIndex = initialFolderSplit.length > 0 && finalFolderSplit.length > 0 ?
 | 
				
			||||||
 | 
					            initialFolderSplit.findIndex((value, index) => value !== finalFolderSplit[index]) :
 | 
				
			||||||
 | 
					            0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (firstDiffIndex === -1) {
 | 
				
			||||||
 | 
					            // All elements in initial folder are equal. The first diff is the first element in the final folder.
 | 
				
			||||||
 | 
					            firstDiffIndex = initialFolderSplit.length;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const newPathToFinalFolder = finalFolderSplit.slice(firstDiffIndex).join('/');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return '../'.repeat(initialFolderSplit.length - firstDiffIndex) + newPathToFinalFolder;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Convert a relative path (based on a certain folder) to a relative path based on a different folder.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * E.g. if current folder is foo/bar, relative URL is test.jpg and new folder is foo/baz,
 | 
				
			||||||
 | 
					     * it will return ../bar/test.jpg.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param currentFolder The current folder path.
 | 
				
			||||||
 | 
					     * @param path The relative path.
 | 
				
			||||||
 | 
					     * @param newFolder The folder to use to calculate the new relative path. The "root" should be the same as currentFolder.
 | 
				
			||||||
 | 
					     * @return Relative path.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    static changeRelativePath(currentFolder: string, path: string, newFolder: string): string {
 | 
				
			||||||
 | 
					        return CoreText.concatenatePaths(CorePath.calculateRelativePath(newFolder, currentFolder), path);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Concatenate two paths, adding a slash between them if needed.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param leftPath Left path.
 | 
				
			||||||
 | 
					     * @param rightPath Right path.
 | 
				
			||||||
 | 
					     * @return Concatenated path.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    static concatenatePaths(leftPath: string, rightPath: string): string {
 | 
				
			||||||
 | 
					        if (!leftPath) {
 | 
				
			||||||
 | 
					            return rightPath;
 | 
				
			||||||
 | 
					        } else if (!rightPath) {
 | 
				
			||||||
 | 
					            return leftPath;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const lastCharLeft = leftPath.slice(-1);
 | 
				
			||||||
 | 
					        const firstCharRight = rightPath.charAt(0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (lastCharLeft === '/' && firstCharRight === '/') {
 | 
				
			||||||
 | 
					            return leftPath + rightPath.substring(1);
 | 
				
			||||||
 | 
					        } else if (lastCharLeft !== '/' && firstCharRight !== '/') {
 | 
				
			||||||
 | 
					            return leftPath + '/' + rightPath;
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            return leftPath + rightPath;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										55
									
								
								src/core/singletons/tests/path.test.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								src/core/singletons/tests/path.test.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,55 @@
 | 
				
			|||||||
 | 
					// (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.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { CorePath } from '@singletons/path';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					describe('CorePath', () => {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    it('calculates relative paths from one folder to another', () => {
 | 
				
			||||||
 | 
					        expect(CorePath.calculateRelativePath('foo/bar', 'foo/bar')).toEqual('');
 | 
				
			||||||
 | 
					        expect(CorePath.calculateRelativePath('/foo/bar', 'foo/bar/')).toEqual('');
 | 
				
			||||||
 | 
					        expect(CorePath.calculateRelativePath('foo/bar', 'foo/baz')).toEqual('../baz');
 | 
				
			||||||
 | 
					        expect(CorePath.calculateRelativePath('foo', 'baz')).toEqual('../baz');
 | 
				
			||||||
 | 
					        expect(CorePath.calculateRelativePath('foo/bar/baz', 'foo/baz')).toEqual('../../baz');
 | 
				
			||||||
 | 
					        expect(CorePath.calculateRelativePath('foo/baz', 'foo/bar/baz')).toEqual('../bar/baz');
 | 
				
			||||||
 | 
					        expect(CorePath.calculateRelativePath('foo/bar/baz', 'foo/bar')).toEqual('../');
 | 
				
			||||||
 | 
					        expect(CorePath.calculateRelativePath('foo/bar', 'foo/bar/baz')).toEqual('baz');
 | 
				
			||||||
 | 
					        expect(CorePath.calculateRelativePath('', 'foo')).toEqual('foo');
 | 
				
			||||||
 | 
					        expect(CorePath.calculateRelativePath('foo', '')).toEqual('../');
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    it('changes relative paths to a different folder', () => {
 | 
				
			||||||
 | 
					        expect(CorePath.changeRelativePath('foo/bar', 'test.png', 'foo/bar')).toEqual('test.png');
 | 
				
			||||||
 | 
					        expect(CorePath.changeRelativePath('/foo/bar', 'test.png', 'foo/bar/')).toEqual('test.png');
 | 
				
			||||||
 | 
					        expect(CorePath.changeRelativePath('foo/bar', 'test.png', 'foo/baz')).toEqual('../bar/test.png');
 | 
				
			||||||
 | 
					        expect(CorePath.changeRelativePath('foo/bar', '../xyz/test.png', 'foo/baz')).toEqual('../bar/../xyz/test.png');
 | 
				
			||||||
 | 
					        expect(CorePath.changeRelativePath('foo', 'bar/test.png', 'baz')).toEqual('../foo/bar/test.png');
 | 
				
			||||||
 | 
					        expect(CorePath.changeRelativePath('foo/bar/baz', 'test.png', 'foo/baz')).toEqual('../bar/baz/test.png');
 | 
				
			||||||
 | 
					        expect(CorePath.changeRelativePath('foo/bar/baz', 'test.png', 'foo/bar')).toEqual('baz/test.png');
 | 
				
			||||||
 | 
					        expect(CorePath.changeRelativePath('foo/bar/baz', 'test.png', 'foo/bar/xyz')).toEqual('../baz/test.png');
 | 
				
			||||||
 | 
					        expect(CorePath.changeRelativePath('', 'test.png', 'foo')).toEqual('../test.png');
 | 
				
			||||||
 | 
					        expect(CorePath.changeRelativePath('foo', 'test.png', '')).toEqual('foo/test.png');
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    it('concatenates paths', () => {
 | 
				
			||||||
 | 
					        expect(CorePath.concatenatePaths('', 'foo/bar')).toEqual('foo/bar');
 | 
				
			||||||
 | 
					        expect(CorePath.concatenatePaths('foo/bar', '')).toEqual('foo/bar');
 | 
				
			||||||
 | 
					        expect(CorePath.concatenatePaths('foo', 'bar')).toEqual('foo/bar');
 | 
				
			||||||
 | 
					        expect(CorePath.concatenatePaths('foo/', 'bar')).toEqual('foo/bar');
 | 
				
			||||||
 | 
					        expect(CorePath.concatenatePaths('foo', '/bar')).toEqual('foo/bar');
 | 
				
			||||||
 | 
					        expect(CorePath.concatenatePaths('foo/', '/bar')).toEqual('foo/bar');
 | 
				
			||||||
 | 
					        expect(CorePath.concatenatePaths('foo/bar', 'baz')).toEqual('foo/bar/baz');
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
@ -36,14 +36,4 @@ describe('CoreText singleton', () => {
 | 
				
			|||||||
        expect(CoreText.removeStartingSlash('//foo')).toEqual('/foo');
 | 
					        expect(CoreText.removeStartingSlash('//foo')).toEqual('/foo');
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    it('concatenates paths', () => {
 | 
					 | 
				
			||||||
        expect(CoreText.concatenatePaths('', 'foo/bar')).toEqual('foo/bar');
 | 
					 | 
				
			||||||
        expect(CoreText.concatenatePaths('foo/bar', '')).toEqual('foo/bar');
 | 
					 | 
				
			||||||
        expect(CoreText.concatenatePaths('foo', 'bar')).toEqual('foo/bar');
 | 
					 | 
				
			||||||
        expect(CoreText.concatenatePaths('foo/', 'bar')).toEqual('foo/bar');
 | 
					 | 
				
			||||||
        expect(CoreText.concatenatePaths('foo', '/bar')).toEqual('foo/bar');
 | 
					 | 
				
			||||||
        expect(CoreText.concatenatePaths('foo/', '/bar')).toEqual('foo/bar');
 | 
					 | 
				
			||||||
        expect(CoreText.concatenatePaths('foo/bar', 'baz')).toEqual('foo/bar/baz');
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
				
			|||||||
@ -12,6 +12,8 @@
 | 
				
			|||||||
// See the License for the specific language governing permissions and
 | 
					// See the License for the specific language governing permissions and
 | 
				
			||||||
// limitations under the License.
 | 
					// limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { CorePath } from './path';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Singleton with helper functions for text manipulation.
 | 
					 * Singleton with helper functions for text manipulation.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@ -74,24 +76,10 @@ export class CoreText {
 | 
				
			|||||||
     * @param leftPath Left path.
 | 
					     * @param leftPath Left path.
 | 
				
			||||||
     * @param rightPath Right path.
 | 
					     * @param rightPath Right path.
 | 
				
			||||||
     * @return Concatenated path.
 | 
					     * @return Concatenated path.
 | 
				
			||||||
 | 
					     * @deprecated since 4.1.0. Please use CorePath.concatenatePaths instead.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    static concatenatePaths(leftPath: string, rightPath: string): string {
 | 
					    static concatenatePaths(leftPath: string, rightPath: string): string {
 | 
				
			||||||
        if (!leftPath) {
 | 
					        return CorePath.concatenatePaths(leftPath, rightPath);
 | 
				
			||||||
            return rightPath;
 | 
					 | 
				
			||||||
        } else if (!rightPath) {
 | 
					 | 
				
			||||||
            return leftPath;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        const lastCharLeft = leftPath.slice(-1);
 | 
					 | 
				
			||||||
        const firstCharRight = rightPath.charAt(0);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (lastCharLeft === '/' && firstCharRight === '/') {
 | 
					 | 
				
			||||||
            return leftPath + rightPath.substring(1);
 | 
					 | 
				
			||||||
        } else if (lastCharLeft !== '/' && firstCharRight !== '/') {
 | 
					 | 
				
			||||||
            return leftPath + '/' + rightPath;
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            return leftPath + rightPath;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user