Skip to content

Commit

Permalink
preferences: fix regex incompatible with Firefox
Browse files Browse the repository at this point in the history
Firefox doesn't handle lookahead/lookbehind patterns in regexes, leading
to Theia applications not starting when ran inside Firefox.

This commit replaces the problematic regex with a method that produces
the same result.

Signed-off-by: Paul Maréchal <paul.marechal@ericsson.com>
  • Loading branch information
paul-marechal committed May 7, 2020
1 parent ac8efa2 commit fa7fb7d
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 4 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/********************************************************************************
* Copyright (C) 2020 Ericsson and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the Eclipse
* Public License v. 2.0 are satisfied: GNU General Public License, version 2
* with the GNU Classpath Exception which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
********************************************************************************/

/* eslint-disable @typescript-eslint/no-explicit-any */

import { enableJSDOM } from '@theia/core/lib/browser/test/jsdom';
const disableJSDOM = enableJSDOM();

import { expect } from 'chai';
import { Container } from 'inversify';
import { PreferenceTreeGenerator } from './preference-tree-generator';
import { PreferenceSchemaProvider } from '@theia/core/lib/browser';
import { PreferenceConfigurations } from '@theia/core/lib/browser/preferences/preference-configurations';

disableJSDOM();

describe('preference-tree-generator', () => {

let preferenceTreeGenerator: PreferenceTreeGenerator;

beforeEach(() => {
const container = new Container();
container.bind<any>(PreferenceSchemaProvider).toConstantValue(undefined);
container.bind<any>(PreferenceConfigurations).toConstantValue(undefined);
preferenceTreeGenerator = container.resolve(PreferenceTreeGenerator);
});

it('PreferenceTreeGenerator.split', () => {
// We want to ensure that our `split` function emulates the following regex properly:
const splitter = /[\W_]|(?<=[^A-Z])(?=[A-Z])/;
const testString = 'aaaBbb.Ccc d E fff GGGgg_iiiJ0a';
expect(preferenceTreeGenerator['split'](testString)).deep.eq(testString.split(splitter));
});

});
20 changes: 16 additions & 4 deletions packages/preferences/src/browser/util/preference-tree-generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,7 @@ export class PreferenceTreeGenerator {
});

protected createLeafNode = (property: string, preferencesGroup: Preference.Branch): SelectableTreeNode => {
const splitter = /[\W_]|(?<=[^A-Z])(?=[A-Z])/; // Any non-word character or the 0-length space between a non-upper-case character and an upper-case character
const propertySpecifier = property.split(splitter).slice(1);
const propertySpecifier = this.split(property).slice(1);
const name = propertySpecifier.map(word => word.slice(0, 1).toLocaleUpperCase() + word.slice(1)).join(' ').trim();
return {
id: property,
Expand Down Expand Up @@ -100,11 +99,24 @@ export class PreferenceTreeGenerator {

protected toTitleCase(nonTitle: string): string {
// Any non-word character or the 0-length space between a non-upper-case character and an upper-case character
const splitter = /[\W_]|(?<=[^A-Z])(?=[A-Z])/;
return nonTitle.split(splitter).map(word => this.capitalizeFirst(word)).join(' ').trim();
return this.split(nonTitle).map(word => this.capitalizeFirst(word)).join(' ').trim();
}

protected capitalizeFirst(maybeLowerCase: string): string {
return maybeLowerCase.slice(0, 1).toLocaleUpperCase() + maybeLowerCase.slice(1);
}

/**
* Split based on any non-word character or the 0-length space between a non-upper-case character and an upper-case character
*/
private split(string: string): string[] {
const split: string[] = [];
const regex = /[A-Z]+[a-z0-9]*|[A-Z]*[a-z0-9]+/g;
// eslint-disable-next-line no-null/no-null
let match; while ((match = regex.exec(string)) !== null) {
split.push(match[0]);
}
return split;
}

}

0 comments on commit fa7fb7d

Please sign in to comment.