mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Fix spelling (#3181)
Co-authored-by: Josh Soref <jsoref@users.noreply.github.com>
This commit is contained in:
parent
9903417fed
commit
e87b4836be
@ -6,7 +6,7 @@ In this section you will learn how this extension works under the hood.
|
||||
The Hello World sample extension does three things:
|
||||
|
||||
- Implements `onActivate()` and outputs a message to the console.
|
||||
- Implements `onDectivate()` and outputs a message to the console.
|
||||
- Implements `onDeactivate()` and outputs a message to the console.
|
||||
- Registers `ClusterPage` so that the page is visible in the left-side menu of the cluster dashboard.
|
||||
|
||||
Let's take a closer look at our Hello World sample's source code and see how these three things are achieved.
|
||||
|
||||
@ -72,4 +72,4 @@ To dive deeper, consider looking at [Common Capabilities](../capabilities/common
|
||||
If you find problems with the Lens Extension Generator, or have feature requests, you are welcome to raise an [issue](https://github.com/lensapp/generator-lens-ext/issues).
|
||||
You can find the latest Lens contribution guidelines [here](https://docs.k8slens.dev/latest/contributing).
|
||||
|
||||
The Generator source code is hosted at [Github](https://github.com/lensapp/generator-lens-ext).
|
||||
The Generator source code is hosted at [GitHub](https://github.com/lensapp/generator-lens-ext).
|
||||
|
||||
@ -213,7 +213,7 @@ export class CertificatePage extends React.Component<{ extension: LensRendererEx
|
||||
return (
|
||||
<TabLayout>
|
||||
<KubeObjectListLayout
|
||||
className="Certicates" store={certificatesStore}
|
||||
className="Certificates" store={certificatesStore}
|
||||
sortingCallbacks={{
|
||||
[sortBy.name]: (certificate: Certificate) => certificate.getName(),
|
||||
[sortBy.namespace]: (certificate: Certificate) => certificate.metadata.namespace,
|
||||
|
||||
@ -94,7 +94,7 @@ export default class SamplePageMainExtension extends Main.LensExtension {
|
||||
```
|
||||
|
||||
When the menu item is clicked the `navigate()` method looks for and displays a global page with id `"myGlobalPage"`.
|
||||
This page would be defined in your extension's `Renderer.LensExtension` implmentation (See [`Renderer.LensExtension`](renderer-extension.md)).
|
||||
This page would be defined in your extension's `Renderer.LensExtension` implementation (See [`Renderer.LensExtension`](renderer-extension.md)).
|
||||
|
||||
### `addCatalogSource()` and `removeCatalogSource()` Methods
|
||||
|
||||
|
||||
@ -90,7 +90,7 @@ This is the cluster that the resource stack will be applied to, and the construc
|
||||
Similarly, `ExampleClusterFeature` implements an `uninstall()` method which simply invokes the `kubectlDeleteFolder()` method of the `Renderer.K8sApi.ResourceStack` class.
|
||||
`kubectlDeleteFolder()` tries to delete from the cluster all kubernetes resources found in the folder passed to it, again in this case `../resources`.
|
||||
|
||||
`ExampleClusterFeature` also implements an `isInstalled()` method, which demonstrates how you can utiliize the kubernetes api to inspect the resource stack status.
|
||||
`ExampleClusterFeature` also implements an `isInstalled()` method, which demonstrates how you can utilize the kubernetes api to inspect the resource stack status.
|
||||
`isInstalled()` simply tries to find a pod named `example-pod`, as a way to determine if the pod is already installed.
|
||||
This method can be useful in creating a context-sensitive UI for installing/uninstalling the feature, as demonstrated in the next sample code.
|
||||
|
||||
|
||||
@ -148,8 +148,8 @@ export class ExamplePreferenceInput extends React.Component {
|
||||
return (
|
||||
<Checkbox
|
||||
label="I understand appPreferences"
|
||||
value={ExamplePreferencesStore.getInstace().enabled}
|
||||
onChange={v => { ExamplePreferencesStore.getInstace().enabled = v; }}
|
||||
value={ExamplePreferencesStore.getInstance().enabled}
|
||||
onChange={v => { ExamplePreferencesStore.getInstance().enabled = v; }}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@ -43,4 +43,4 @@ Say you have your project folder at `~/my-extension/` and you want to create an
|
||||
npm pack
|
||||
```
|
||||
|
||||
This will create a NPM tarball that can be hosted on Github Releases or any other publicly available file hosting service.
|
||||
This will create a NPM tarball that can be hosted on GitHub Releases or any other publicly available file hosting service.
|
||||
|
||||
@ -56,7 +56,7 @@ class TestCatalogCategory2 extends CatalogCategory {
|
||||
}
|
||||
|
||||
describe("CatalogCategoryRegistry", () => {
|
||||
it("should remove only the category registered when running the disopser", () => {
|
||||
it("should remove only the category registered when running the disposer", () => {
|
||||
const registry = new TestCatalogCategoryRegistry();
|
||||
|
||||
expect(registry.items.length).toBe(0);
|
||||
|
||||
@ -52,7 +52,7 @@ export interface HotbarStoreModel {
|
||||
activeHotbarId: string;
|
||||
}
|
||||
|
||||
export const defaultHotbarCells = 12; // Number is choosen to easy hit any item with keyboard
|
||||
export const defaultHotbarCells = 12; // Number is chosen to easy hit any item with keyboard
|
||||
|
||||
export class HotbarStore extends BaseStore<HotbarStoreModel> {
|
||||
@observable hotbars: Hotbar[] = [];
|
||||
@ -203,7 +203,7 @@ export class HotbarStore extends BaseStore<HotbarStoreModel> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Remvove all hotbar items that reference the `uid`.
|
||||
* Remove all hotbar items that reference the `uid`.
|
||||
* @param uid The `EntityId` that each hotbar item refers to
|
||||
* @returns A function that will (in an action) undo the removing of the hotbar items. This function will not complete if the hotbar has changed.
|
||||
*/
|
||||
|
||||
@ -193,9 +193,9 @@ const hiddenTableColumns: PreferenceDescription<[string, string[]][], Map<string
|
||||
toStore(val) {
|
||||
const res: [string, string[]][] = [];
|
||||
|
||||
for (const [table, columnes] of val) {
|
||||
if (columnes.size) {
|
||||
res.push([table, Array.from(columnes)]);
|
||||
for (const [table, columns] of val) {
|
||||
if (columns.size) {
|
||||
res.push([table, Array.from(columns)]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -27,7 +27,7 @@ export class ExtendedMap<K, V> extends Map<K, V> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value behind `key`. If it was not pressent, first insert the value returned by `getVal`
|
||||
* Get the value behind `key`. If it was not present, first insert the value returned by `getVal`
|
||||
* @param key The key to insert into the map with
|
||||
* @param getVal A function that returns a new instance of `V`.
|
||||
* @returns The value in the map
|
||||
|
||||
@ -84,7 +84,7 @@ jest.mock(
|
||||
(channel: string, listener: (event: any, ...args: any[]) => void) => {
|
||||
if (channel === "extensions:main") {
|
||||
// First initialize with extensions 1 and 2
|
||||
// and then broadcast event to remove extensioin 2 and add extension number 3
|
||||
// and then broadcast event to remove extension 2 and add extension number 3
|
||||
setTimeout(() => {
|
||||
listener({}, [
|
||||
[
|
||||
|
||||
@ -36,7 +36,7 @@ export abstract class IpcMain extends IpcRegistrar {
|
||||
* Listen for broadcasts within your extension
|
||||
* @param channel The channel to listen for broadcasts on
|
||||
* @param listener The function that will be called with the arguments of the broadcast
|
||||
* @returns An optional disopser, Lens will cleanup when the extension is disabled or uninstalled even if this is not called
|
||||
* @returns An optional disposer, Lens will cleanup when the extension is disabled or uninstalled even if this is not called
|
||||
*/
|
||||
listen(channel: string, listener: (event: Electron.IpcRendererEvent, ...args: any[]) => any): Disposer {
|
||||
const prefixedChannel = `extensions@${this[IpcPrefix]}:${channel}`;
|
||||
|
||||
@ -74,7 +74,7 @@ export class LensExtension {
|
||||
* getExtensionFileFolder returns the path to an already created folder. This
|
||||
* folder is for the sole use of this extension.
|
||||
*
|
||||
* Note: there is no security done on this folder, only obfiscation of the
|
||||
* Note: there is no security done on this folder, only obfuscation of the
|
||||
* folder name.
|
||||
*/
|
||||
async getExtensionFileFolder(): Promise<string> {
|
||||
|
||||
@ -207,7 +207,7 @@ describe("ContextHandler", () => {
|
||||
expect(service.id === "id_0");
|
||||
});
|
||||
|
||||
it("shouldn't pick the second provider of 2 succcess(es) after 1 failure(s)", async () => {
|
||||
it("shouldn't pick the second provider of 2 success(es) after 1 failure(s)", async () => {
|
||||
const reg = PrometheusProviderRegistry.getInstance();
|
||||
let count = 0;
|
||||
|
||||
|
||||
@ -146,7 +146,7 @@ export class HelmRepoManager extends Singleton {
|
||||
return stdout;
|
||||
}
|
||||
|
||||
public static async addСustomRepo(repoAttributes : HelmRepo) {
|
||||
public static async addCustomRepo(repoAttributes : HelmRepo) {
|
||||
logger.info(`[HELM]: adding repo "${repoAttributes.name}" from ${repoAttributes.url}`);
|
||||
const helm = await helmCli.binaryPath();
|
||||
|
||||
|
||||
@ -137,7 +137,7 @@ app.on("ready", async () => {
|
||||
/**
|
||||
* The following sync MUST be done before HotbarStore creation, because that
|
||||
* store has migrations that will remove items that previous migrations add
|
||||
* if this is not presant
|
||||
* if this is not present
|
||||
*/
|
||||
syncGeneralEntities();
|
||||
|
||||
|
||||
@ -93,7 +93,7 @@ function createTrayMenu(windowManager: WindowManager): Menu {
|
||||
click() {
|
||||
windowManager
|
||||
.navigate(preferencesURL())
|
||||
.catch(error => logger.error(`${TRAY_LOG_PREFIX}: Failed to nativate to Preferences`, { error }));
|
||||
.catch(error => logger.error(`${TRAY_LOG_PREFIX}: Failed to navigate to Preferences`, { error }));
|
||||
},
|
||||
}
|
||||
];
|
||||
|
||||
@ -114,7 +114,7 @@ function _parseKubeApi(path: string): IKubeApiParsed {
|
||||
* There is no well defined selection from an array of items that were
|
||||
* separated by '/'
|
||||
*
|
||||
* Solution is to create a huristic. Namely:
|
||||
* Solution is to create a heuristic. Namely:
|
||||
* 1. if '.' in left[0] then apiGroup <- left[0]
|
||||
* 2. if left[1] matches /^v[0-9]/ then apiGroup, apiVersion <- left[0], left[1]
|
||||
* 3. otherwise assume apiVersion <- left[0]
|
||||
|
||||
@ -53,7 +53,7 @@ import { TerminalStore } from "./components/dock/terminal.store";
|
||||
configurePackages();
|
||||
|
||||
/**
|
||||
* If this is a development buid, wait a second to attach
|
||||
* If this is a development build, wait a second to attach
|
||||
* Chrome Debugger to renderer process
|
||||
* https://stackoverflow.com/questions/52844870/debugging-electron-renderer-process-with-vscode
|
||||
*/
|
||||
|
||||
@ -58,7 +58,7 @@ export class ReleaseStore extends ItemStore<HelmRelease> {
|
||||
});
|
||||
}
|
||||
|
||||
watchSelecteNamespaces(): (() => void) {
|
||||
watchSelectedNamespaces(): (() => void) {
|
||||
return reaction(() => namespaceStore.context.contextNamespaces, namespaces => {
|
||||
this.loadAll(namespaces);
|
||||
});
|
||||
|
||||
@ -56,7 +56,7 @@ export class HelmReleases extends Component<Props> {
|
||||
componentDidMount() {
|
||||
disposeOnUnmount(this, [
|
||||
releaseStore.watchAssociatedSecrets(),
|
||||
releaseStore.watchSelecteNamespaces(),
|
||||
releaseStore.watchSelectedNamespaces(),
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
@ -225,7 +225,7 @@ export class ExtensionInstallationStateStore {
|
||||
}
|
||||
|
||||
/**
|
||||
* If there is at least one extension currently ininstalling
|
||||
* If there is at least one extension currently uninstalling
|
||||
*/
|
||||
static get anyUninstalling(): boolean {
|
||||
return ExtensionInstallationStateStore.uninstalling > 0;
|
||||
|
||||
@ -49,7 +49,7 @@ import { docsUrl } from "../../../common/vars";
|
||||
|
||||
function getMessageFromError(error: any): string {
|
||||
if (!error || typeof error !== "object") {
|
||||
return "an error has occured";
|
||||
return "an error has occurred";
|
||||
}
|
||||
|
||||
if (error.message) {
|
||||
@ -63,7 +63,7 @@ function getMessageFromError(error: any): string {
|
||||
const rawMessage = String(error);
|
||||
|
||||
if (rawMessage === String({})) {
|
||||
return "an error has occured";
|
||||
return "an error has occurred";
|
||||
}
|
||||
|
||||
return rawMessage;
|
||||
|
||||
@ -107,7 +107,7 @@ export class AddHelmRepoDialog extends React.Component<Props> {
|
||||
|
||||
async addCustomRepo() {
|
||||
try {
|
||||
await HelmRepoManager.addСustomRepo(this.helmRepo);
|
||||
await HelmRepoManager.addCustomRepo(this.helmRepo);
|
||||
Notifications.ok(<>Helm repository <b>{this.helmRepo.name}</b> has added</>);
|
||||
this.props.onAddRepo();
|
||||
this.close();
|
||||
@ -145,7 +145,7 @@ export class AddHelmRepoDialog extends React.Component<Props> {
|
||||
/>
|
||||
{this.renderFileInput(`Key file`, FileType.KeyFile, AddHelmRepoDialog.keyExtensions)}
|
||||
{this.renderFileInput(`Ca file`, FileType.CaFile, AddHelmRepoDialog.certExtensions)}
|
||||
{this.renderFileInput(`Cerificate file`, FileType.CertFile, AddHelmRepoDialog.certExtensions)}
|
||||
{this.renderFileInput(`Certificate file`, FileType.CertFile, AddHelmRepoDialog.certExtensions)}
|
||||
<SubTitle title="Chart Repository Credentials" />
|
||||
<Input
|
||||
placeholder="Username"
|
||||
|
||||
@ -81,7 +81,7 @@ export class Preferences extends React.Component {
|
||||
const fragment = hash.slice(1); // hash is /^(#\w.)?$/
|
||||
|
||||
if (fragment) {
|
||||
// ignore empty framents
|
||||
// ignore empty fragments
|
||||
document.getElementById(fragment)?.scrollIntoView();
|
||||
}
|
||||
}, {
|
||||
|
||||
@ -47,7 +47,7 @@ describe("<BottomBar />", () => {
|
||||
expect(container).toBeInstanceOf(HTMLElement);
|
||||
});
|
||||
|
||||
it("renders w/o errors when .getItems() returns unexpected (not type complient) data", async () => {
|
||||
it("renders w/o errors when .getItems() returns unexpected (not type compliant) data", async () => {
|
||||
StatusBarRegistry.getInstance().getItems = jest.fn().mockImplementationOnce(() => undefined);
|
||||
expect(() => render(<BottomBar />)).not.toThrow();
|
||||
StatusBarRegistry.getInstance().getItems = jest.fn().mockImplementationOnce(() => "hello");
|
||||
|
||||
@ -52,8 +52,8 @@ export class ClusterAccessibleNamespaces extends React.Component<Props> {
|
||||
}}
|
||||
validators={systemName}
|
||||
items={Array.from(this.namespaces)}
|
||||
remove={({ oldItem: oldNamesapce }) => {
|
||||
this.namespaces.delete(oldNamesapce);
|
||||
remove={({ oldItem: oldNamespace }) => {
|
||||
this.namespaces.delete(oldNamespace);
|
||||
this.props.cluster.accessibleNamespaces = Array.from(this.namespaces);
|
||||
}}
|
||||
inputTheme="round-black"
|
||||
|
||||
@ -35,7 +35,7 @@ export class ErrorBoundary extends React.Component {
|
||||
<Sentry.ErrorBoundary
|
||||
fallback={({ error, componentStack, resetError }) => {
|
||||
const slackLink = <a href={slackUrl} rel="noreferrer" target="_blank">Slack</a>;
|
||||
const githubLink = <a href={issuesTrackerUrl} rel="noreferrer" target="_blank">Github</a>;
|
||||
const githubLink = <a href={issuesTrackerUrl} rel="noreferrer" target="_blank">GitHub</a>;
|
||||
const pageUrl = location.pathname;
|
||||
|
||||
return (
|
||||
|
||||
@ -127,7 +127,7 @@ export class FilePicker extends React.Component<Props> {
|
||||
return files;
|
||||
}
|
||||
|
||||
handleIndiviualFileSizes(files: File[]): File[] {
|
||||
handleIndividualFileSizes(files: File[]): File[] {
|
||||
const { onOverSizeLimit, maxSize } = this.props;
|
||||
|
||||
switch (onOverSizeLimit) {
|
||||
@ -178,7 +178,7 @@ export class FilePicker extends React.Component<Props> {
|
||||
|
||||
try {
|
||||
const numberLimitedFiles = this.handleFileCount(files);
|
||||
const sizeLimitedFiles = this.handleIndiviualFileSizes(numberLimitedFiles);
|
||||
const sizeLimitedFiles = this.handleIndividualFileSizes(numberLimitedFiles);
|
||||
const totalSizeLimitedFiles = this.handleTotalFileSizes(sizeLimitedFiles);
|
||||
|
||||
if ("uploadDir" in this.props) {
|
||||
|
||||
@ -63,7 +63,7 @@ interface SplitStatusesByLevel {
|
||||
}
|
||||
|
||||
/**
|
||||
* This fuction returns the class level for corresponding to the highest status level
|
||||
* This function returns the class level for corresponding to the highest status level
|
||||
* and the statuses split by their levels.
|
||||
* @param src a list of status items
|
||||
*/
|
||||
|
||||
@ -383,8 +383,8 @@
|
||||
|
||||
blockquote {
|
||||
padding: 8px 1em;
|
||||
color: $helmDescriptionBlockqouteColor;
|
||||
border-left: 0.25em solid $helmDescriptionBlockqouteBorder;
|
||||
color: $helmDescriptionBlockquoteColor;
|
||||
border-left: 0.25em solid $helmDescriptionBlockquoteBorder;
|
||||
background: $helmDescriptionBlockquoteBackground;
|
||||
}
|
||||
|
||||
|
||||
@ -39,7 +39,7 @@ export interface Notification {
|
||||
message: NotificationMessage;
|
||||
status?: NotificationStatus;
|
||||
timeout?: number; // auto-hiding timeout in milliseconds, 0 = no hide
|
||||
onClose?(): void; // additonal logic on when the notification times out or is closed by the "x"
|
||||
onClose?(): void; // additional logic on when the notification times out or is closed by the "x"
|
||||
}
|
||||
|
||||
export class NotificationsStore {
|
||||
|
||||
@ -100,7 +100,7 @@ interface Props {
|
||||
minExtent?: number;
|
||||
|
||||
/**
|
||||
* The following events are triggerred with respect to the above values.
|
||||
* The following events are triggered with respect to the above values.
|
||||
* - The "__Exceed" call will be made when the unbounded extent goes from
|
||||
* < the above to >= the above
|
||||
* - The "__Subceed" call is similar but is triggered when the unbounded
|
||||
|
||||
@ -44,8 +44,8 @@
|
||||
"helmStableRepo": "#3d90ce",
|
||||
"helmIncubatorRepo": "#ff7043",
|
||||
"helmDescriptionHr": "#41474a",
|
||||
"helmDescriptionBlockqouteColor": "#bbb",
|
||||
"helmDescriptionBlockqouteBorder": "#8a8f93",
|
||||
"helmDescriptionBlockquoteColor": "#bbb",
|
||||
"helmDescriptionBlockquoteBorder": "#8a8f93",
|
||||
"helmDescriptionBlockquoteBackground": "#3b4348",
|
||||
"helmDescriptionHeaders": "#3e4147",
|
||||
"helmDescriptionH6": "#6a737d",
|
||||
@ -113,7 +113,7 @@
|
||||
"iconActiveColor": "#ffffff",
|
||||
"iconActiveBackground": "#ffffff18",
|
||||
"filterAreaBackground": "#23272b",
|
||||
"chartLiveBarBackgound": "#00000033",
|
||||
"chartLiveBarBackground": "#00000033",
|
||||
"chartStripesColor": "#ffffff08",
|
||||
"chartCapacityColor": "#4c545f",
|
||||
"pieChartDefaultColor": "#30353a",
|
||||
|
||||
@ -45,8 +45,8 @@
|
||||
"helmStableRepo": "#3d90ce",
|
||||
"helmIncubatorRepo": "#ff7043",
|
||||
"helmDescriptionHr": "#dddddd",
|
||||
"helmDescriptionBlockqouteColor": "#555555",
|
||||
"helmDescriptionBlockqouteBorder": "#8a8f93",
|
||||
"helmDescriptionBlockquoteColor": "#555555",
|
||||
"helmDescriptionBlockquoteBorder": "#8a8f93",
|
||||
"helmDescriptionBlockquoteBackground": "#eeeeee",
|
||||
"helmDescriptionHeaders": "#3e4147",
|
||||
"helmDescriptionH6": "#6a737d",
|
||||
@ -114,7 +114,7 @@
|
||||
"iconActiveColor": "#ffffff",
|
||||
"iconActiveBackground": "#a6a6a694",
|
||||
"filterAreaBackground": "#f7f7f7",
|
||||
"chartLiveBarBackgound": "#00000033",
|
||||
"chartLiveBarBackground": "#00000033",
|
||||
"chartStripesColor": "#00000009",
|
||||
"chartCapacityColor": "#cccccc",
|
||||
"pieChartDefaultColor": "#efefef",
|
||||
|
||||
@ -74,8 +74,8 @@ $helmImgBackground: var(--helmImgBackground);
|
||||
$helmStableRepo: var(--helmStableRepo);
|
||||
$helmIncubatorRepo: var(--helmIncubatorRepo);
|
||||
$helmDescriptionHr: var(--helmDescriptionHr);
|
||||
$helmDescriptionBlockqouteColor: var(--helmDescriptionBlockqouteColor);
|
||||
$helmDescriptionBlockqouteBorder: var(--helmDescriptionBlockqouteBorder);
|
||||
$helmDescriptionBlockquoteColor: var(--helmDescriptionBlockquoteColor);
|
||||
$helmDescriptionBlockquoteBorder: var(--helmDescriptionBlockquoteBorder);
|
||||
$helmDescriptionBlockquoteBackground: var(--helmDescriptionBlockquoteBackground);
|
||||
$helmDescriptionHeaders: var(--helmDescriptionHeaders);
|
||||
$helmDescriptionH6: var(--helmDescriptionH6);
|
||||
@ -132,7 +132,7 @@ $drawerItemNameColor: var(--drawerItemNameColor);
|
||||
$drawerItemValueColor: var(--drawerItemValueColor);
|
||||
|
||||
// Charts
|
||||
$chartLiveBarBackgound: var(--chartLiveBarBackgound);
|
||||
$chartLiveBarBackground: var(--chartLiveBarBackground);
|
||||
$chartStripesColor: var(--chartStripesColor);
|
||||
$chartCapacityColor: var(--chartCapacityColor);
|
||||
$pieChartDefaultColor: var(--pieChartDefaultColor);
|
||||
|
||||
@ -28,7 +28,7 @@ describe("parseJsonPath", () => {
|
||||
expect(res).toBe(".metadata.labels['kubesphere.io/alias-name']");
|
||||
});
|
||||
|
||||
test("should convert keys with escpaped charatecrs to use indexed notation", () => {
|
||||
test("should convert keys with escaped characters to use indexed notation", () => {
|
||||
const res = parseJsonPath(".metadata.labels.kubesphere\\\"io/alias-name");
|
||||
|
||||
expect(res).toBe(".metadata.labels['kubesphere\"io/alias-name']");
|
||||
|
||||
@ -48,7 +48,7 @@ function convertToIndexNotation(key: string, firstItem = false) {
|
||||
}
|
||||
|
||||
return `['${key}']`;
|
||||
} else { // no illegal chracters found, do not touch
|
||||
} else { // no illegal characters found, do not touch
|
||||
const prefix = firstItem ? "" : ".";
|
||||
|
||||
return `${prefix}${key}`;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user