From 7eaa97a55623ccaa384915fca00b1c11d9084df1 Mon Sep 17 00:00:00 2001 From: hensm Date: Wed, 27 Feb 2019 16:32:04 +0000 Subject: [PATCH] Convert ext options to typescript --- ext/src/global.d.ts | 13 + ext/src/options/{Bridge.jsx => Bridge.tsx} | 394 ++++++++++-------- .../{EditableList.jsx => EditableList.tsx} | 218 +++++----- ...tableListItem.jsx => EditableListItem.tsx} | 126 +++--- ext/src/options/defaultOptions.js | 13 - ext/src/options/defaultOptions.ts | 28 ++ ext/src/options/{index.jsx => index.tsx} | 218 +++++----- ext/webpack.config.js | 2 +- tslintCommon.json | 1 + 9 files changed, 566 insertions(+), 447 deletions(-) rename ext/src/options/{Bridge.jsx => Bridge.tsx} (85%) rename ext/src/options/{EditableList.jsx => EditableList.tsx} (82%) rename ext/src/options/{EditableListItem.jsx => EditableListItem.tsx} (69%) delete mode 100644 ext/src/options/defaultOptions.js create mode 100644 ext/src/options/defaultOptions.ts rename ext/src/options/{index.jsx => index.tsx} (91%) diff --git a/ext/src/global.d.ts b/ext/src/global.d.ts index 2f4cb16..54ba330 100644 --- a/ext/src/global.d.ts +++ b/ext/src/global.d.ts @@ -16,3 +16,16 @@ declare namespace browser.runtime { error: { message: string }; } } + +// Allow default attribute on + + ) + : ( )} - fetch(ENDPOINT_URL) - .then(res => { - window.clearTimeout(timeout); - return res.json() - }) - .then(this.onCheckUpdatesResponse) - .catch(this.onCheckUpdatesError); +
+ { this.state.updateStatus && !this.state.isUpdateAvailable + && this.state.updateStatus } +
+ } + + ); } - showUpdateStatus () { - if (this.updateStatusTimeout) { - window.clearTimeout(this.updateStatusTimeout); - } - this.updateStatusTimeout = window.setTimeout(() => { - this.setState({ - updateStatus: null - }); - }, 1500); - } - - async onUpdate () { - // Current window to base centered position on - const win = await browser.windows.getCurrent(); - const centeredProps = getWindowCenteredProps(win, 400, 150); - - const updaterPopup = await browser.windows.create({ - url: "../updater/index.html" - , type: "popup" - , ...centeredProps - }); - - // Size/position not set correctly on creation (bug?) - await browser.windows.update(updaterPopup.id, { - ...centeredProps - }); - - browser.runtime.onConnect.addListener(port => { - if (port.name === "updater") { - const asset = this.updateData.assets.find(asset => { - const fileExtension = asset.name.match(/.*\.(.*)$/).pop(); - const currentPlatform = (this.props.platform === "linux") - ? this.state.packageType - : this.props.platform; - - switch (fileExtension) { - case "exe": return "win" === currentPlatform; - case "pkg": return "mac" === currentPlatform; - case "deb": return "deb" === currentPlatform; - case "rpm": return "rpm" === currentPlatform; - } - }); - - port.postMessage({ - subject: "updater:/updateData" - , data: asset - }); - - port.onDisconnect.addListener(() => { - browser.windows.remove(updaterPopup.id); - }); - } - }); - } - - - async onCheckUpdatesResponse (res) { - const isUpdateAvailable = !this.props.info || semver.lt( - this.props.info.version, res.tag_name); - - if (isUpdateAvailable) { - this.updateData = res; - } - - this.setState({ - isCheckingUpdates: false - , isUpdateAvailable - , updateStatus: !isUpdateAvailable - ? _("optionsBridgeUpdateStatusNoUpdates") - : null - }); - - this.showUpdateStatus(); - } - - onCheckUpdatesError (err) { - this.setState({ - isCheckingUpdates: false - , wasErrorCheckingUpdates: true - , updateStatus: _("optionsBridgeUpdateStatusError") - }); - - this.showUpdateStatus(); - } - - onPackageTypeChange (ev) { - this.setState({ - packageType: ev.target.value - }); - } - - - renderStatus () { + private renderStatus () { const infoClasses = `bridge__info ${this.props.info ? "bridge__info--found" : "bridge__info--not-found"}`; - let statusIcon; - let statusTitle; - let statusText; + let statusIcon: string; + let statusTitle: string; + let statusText: string; if (!this.props.info) { statusIcon = "assets/icons8-cancel-120.png"; @@ -237,7 +211,7 @@ export default class Bridge extends Component { } else { if (this.props.info.isVersionCompatible) { statusIcon = "assets/icons8-ok-120.png"; - statusTitle = _("optionsBridgeFoundStatusTitle"; + statusTitle = _("optionsBridgeFoundStatusTitle"); } else { statusIcon = "assets/icons8-warn-120.png"; statusTitle = _("optionsBridgeIssueStatusTitle"); @@ -267,65 +241,115 @@ export default class Bridge extends Component { ); } - render () { - return ( -
- { this.props.loading - ? (
- { _("optionsBridgeLoading") } - -
- : this.renderStatus() } + private onCheckUpdates () { + this.setState({ + isCheckingUpdates: true + }); - { !this.props.loading && -
- { this.state.isUpdateAvailable - ? ( -
-

- { _("optionsBridgeUpdateAvailable") } -

-
- { this.props.platform === "linux" && - } - -
-
- ) : ( - - )} + fetch(ENDPOINT_URL) + .then(res => { + window.clearTimeout(timeout); + return res.json(); + }) + .then(this.onCheckUpdatesResponse) + .catch(this.onCheckUpdatesError); + } -
- { this.state.updateStatus && !this.state.isUpdateAvailable - && this.state.updateStatus } -
-
} -
- ); + private showUpdateStatus () { + if (this.updateStatusTimeout) { + window.clearTimeout(this.updateStatusTimeout); + } + this.updateStatusTimeout = window.setTimeout(() => { + this.setState({ + updateStatus: null + }); + }, 1500); + } + + private async onUpdate () { + // Current window to base centered position on + const win = await browser.windows.getCurrent(); + const centeredProps = getWindowCenteredProps(win, 400, 150); + + const updaterPopup = await browser.windows.create({ + url: "../updater/index.html" + , type: "popup" + , ...centeredProps + }); + + // Size/position not set correctly on creation (bug?) + await browser.windows.update(updaterPopup.id, { + ...centeredProps + }); + + browser.runtime.onConnect.addListener(port => { + if (port.name === "updater") { + const asset = this.updateData.assets.find((currentAsset: any) => { + const fileExtension = currentAsset.name.match(/.*\.(.*)$/).pop(); + const currentPlatform = (this.props.platform === "linux") + ? this.state.packageType + : this.props.platform; + + switch (fileExtension) { + case "exe": return "win" === currentPlatform; + case "pkg": return "mac" === currentPlatform; + case "deb": return "deb" === currentPlatform; + case "rpm": return "rpm" === currentPlatform; + } + }); + + port.postMessage({ + subject: "updater:/updateData" + , data: asset + }); + + port.onDisconnect.addListener(() => { + browser.windows.remove(updaterPopup.id); + }); + } + }); + } + + + private async onCheckUpdatesResponse (res: any) { + const isUpdateAvailable = !this.props.info || semver.lt( + this.props.info.version, res.tag_name); + + if (isUpdateAvailable) { + this.updateData = res; + } + + this.setState({ + isCheckingUpdates: false + , isUpdateAvailable + , updateStatus: !isUpdateAvailable + ? _("optionsBridgeUpdateStatusNoUpdates") + : null + }); + + this.showUpdateStatus(); + } + + private onCheckUpdatesError () { + this.setState({ + isCheckingUpdates: false + , wasErrorCheckingUpdates: true + , updateStatus: _("optionsBridgeUpdateStatusError") + }); + + this.showUpdateStatus(); + } + + private onPackageTypeChange (ev: React.ChangeEvent) { + this.setState({ + packageType: ev.target.value + }); } } diff --git a/ext/src/options/EditableList.jsx b/ext/src/options/EditableList.tsx similarity index 82% rename from ext/src/options/EditableList.jsx rename to ext/src/options/EditableList.tsx index a1b33cb..ee51bc1 100644 --- a/ext/src/options/EditableList.jsx +++ b/ext/src/options/EditableList.tsx @@ -1,12 +1,34 @@ +/* tslint:disable:max-line-length */ +"use strict"; + import React, { Component } from "react"; import EditableListItem from "./EditableListItem"; const _ = browser.i18n.getMessage; -export default class EditableList extends Component { - constructor (props) { +interface EditableListProps { + data: string[]; + itemPattern: RegExp; + onChange (data: string[]): void; + itemPatternError (err?: string): string; +} + +interface EditableListState { + items: Set; + addingNewItem: boolean; + rawView: boolean; + rawViewValue: string; +} + +export default class EditableList extends Component< + EditableListProps, EditableListState> { + + private rawViewTextArea: HTMLTextAreaElement; + + constructor (props: EditableListProps) { super(props); + this.state = { items: new Set(this.props.data) , addingNewItem: false @@ -24,99 +46,6 @@ export default class EditableList extends Component { this.handleNewItemEdit = this.handleNewItemEdit.bind(this); } - handleItemRemove (item) { - this.setState(currentState => { - const newItems = new Set(currentState.items); - newItems.delete(item); - return { - items: newItems - }; - }, () => { - this.props.onChange(Array.from(this.state.items)); - }); - } - - handleItemEdit (item, newValue) { - this.setState(currentState => ({ - items: new Set([...currentState.items] - .map(item_ => item_ === item ? newValue : item_)) - }), () => { - this.props.onChange(Array.from(this.state.items)); - }); - } - - handleSwitchView () { - this.setState(currentState => { - if (currentState.rawView) { - return { - rawView: false - , rawViewValue: "" - }; - } - - return { - rawView: true - , rawViewValue: Array.from(currentState.items.values()).join("\n") - }; - }); - } - - handleSaveRaw () { - this.setState(currentState => { - const newItems = currentState.rawViewValue.split("\n") - .filter(item => item !== ""); - - if ("itemPattern" in this.props) { - for (const item of newItems) { - if (!this.props.itemPattern.test(item)) { - this.rawViewTextArea.setCustomValidity( - this.props.itemPatternError(item)); - return; - } - } - - this.rawViewTextArea.setCustomValidity(""); - } - - return { - items: new Set(newItems) - }; - }, () => { - this.props.onChange(Array.from(this.state.items)); - }); - } - - handleRawViewTextAreaChange (ev) { - if (this.rawViewTextArea.scrollHeight > this.rawViewTextArea.clientHeight) { - this.rawViewTextArea.style.height = `${this.rawViewTextArea.scrollHeight}px`; - } - - this.setState({ - rawViewValue: ev.target.value - }); - } - - handleAddItem () { - this.setState({ - addingNewItem: true - }); - } - - handleNewItemRemove () { - this.setState({ - addingNewItem: false - }); - } - - handleNewItemEdit (item, newItem) { - this.setState(currentState => ({ - items: [ ...currentState.items, newItem ] - , addingNewItem: false - }), () => { - this.props.onChange(Array.from(this.state.items)); - }); - } - render () { const items = Array.from(this.state.items.values()); @@ -142,11 +71,11 @@ export default class EditableList extends Component { rows={ items.length} value={ this.state.rawViewValue} onChange={ this.handleRawViewTextAreaChange } - ref={ el => { this.rawViewTextArea = el }}> + ref={ el => { this.rawViewTextArea = el; }}> ) : (
    - { items.map((item, i) => + { items.map((item, i) => ); } + + private handleItemRemove (item: string) { + this.setState(currentState => { + const newItems = new Set(currentState.items); + newItems.delete(item); + return { + items: newItems + }; + }, () => { + this.props.onChange(Array.from(this.state.items)); + }); + } + + private handleItemEdit (item: string, newValue: string) { + this.setState(currentState => ({ + items: new Set([...currentState.items] + .map(currentItem => currentItem === item + ? newValue + : currentItem)) + }), () => { + this.props.onChange(Array.from(this.state.items)); + }); + } + + private handleSwitchView () { + this.setState(currentState => { + if (currentState.rawView) { + return { + rawView: false + , rawViewValue: "" + }; + } + + return { + rawView: true + , rawViewValue: Array.from(currentState.items.values()).join("\n") + }; + }); + } + + private handleSaveRaw () { + this.setState(currentState => { + const newItems = currentState.rawViewValue.split("\n") + .filter(item => item !== ""); + + if ("itemPattern" in this.props) { + for (const item of newItems) { + if (!this.props.itemPattern.test(item)) { + this.rawViewTextArea.setCustomValidity( + this.props.itemPatternError(item)); + return; + } + } + + this.rawViewTextArea.setCustomValidity(""); + } + + return { + items: new Set(newItems) + }; + }, () => { + this.props.onChange(Array.from(this.state.items)); + }); + } + + private handleRawViewTextAreaChange (ev: React.ChangeEvent) { + if (this.rawViewTextArea.scrollHeight > this.rawViewTextArea.clientHeight) { + this.rawViewTextArea.style.height = `${this.rawViewTextArea.scrollHeight}px`; + } + + this.setState({ + rawViewValue: ev.target.value + }); + } + + private handleAddItem () { + this.setState({ + addingNewItem: true + }); + } + + private handleNewItemRemove () { + this.setState({ + addingNewItem: false + }); + } + + private handleNewItemEdit (item: string, newItem: string) { + this.setState(currentState => ({ + items: new Set([ ...currentState.items, newItem ]) + , addingNewItem: false + }), () => { + this.props.onChange(Array.from(this.state.items)); + }); + } } diff --git a/ext/src/options/EditableListItem.jsx b/ext/src/options/EditableListItem.tsx similarity index 69% rename from ext/src/options/EditableListItem.jsx rename to ext/src/options/EditableListItem.tsx index 05a6ed1..0ad53e5 100644 --- a/ext/src/options/EditableListItem.jsx +++ b/ext/src/options/EditableListItem.tsx @@ -1,11 +1,33 @@ +/* tslint:disable:max-line-length */ +"use strict"; + import React, { Component } from "react"; const _ = browser.i18n.getMessage; -export default class EditableListItem extends Component { - constructor (props) { +interface EditableListItemProps { + text: string; + itemPattern: RegExp; + editing?: boolean; + itemPatternError (err?: string): string; + onRemove (item: string): void; + onEdit (item: string, newValue: string): void; +} + +interface EditableListItemState { + editing: boolean; + editValue: string; +} + +export default class EditableListItem extends Component< + EditableListItemProps, EditableListItemState> { + + private input: HTMLInputElement; + + constructor (props: EditableListItemProps) { super(props); + this.state = { editing: this.props.editing || false , editValue: "" @@ -18,54 +40,6 @@ export default class EditableListItem extends Component { this.handleInputKeyPress = this.handleInputKeyPress.bind(this); } - handleRemove () { - this.props.onRemove(this.props.text); - } - - handleEditBegin () { - this.setState({ - editing: true - , editValue: this.props.text - }, () => { - this.input.focus(); - }); - } - - handleEditEnd (ev) { - if (this.props.editing - && !this.props.itemPattern.test(this.state.editValue)) { - ev.target.setCustomValidity(this.props.itemPatternError()); - } - - if (!ev.target.validity.valid) { - return; - } - - this.props.onEdit(this.props.text, this.state.editValue); - this.setState({ - editing: false - , editValue: "" - }); - } - - handleInputChange (ev) { - this.setState({ - editValue: ev.target.value - }); - - if (!this.props.itemPattern.test(ev.target.value)) { - ev.target.setCustomValidity(this.props.itemPatternError()); - } else { - ev.target.setCustomValidity(""); - } - } - - handleInputKeyPress (ev) { - if (ev.key === "Enter") { - this.handleEditEnd({ target: ev.target }); - } - } - render () { const selected = this.state.editing ? "editable-list__item--selected" : ""; @@ -93,4 +67,56 @@ export default class EditableListItem extends Component { ); } + + private stopEditing (input: HTMLInputElement) { + if (this.props.editing + && !this.props.itemPattern.test(this.state.editValue)) { + input.setCustomValidity(this.props.itemPatternError()); + } + + if (!input.validity.valid) { + return; + } + + this.props.onEdit(this.props.text, this.state.editValue); + this.setState({ + editing: false + , editValue: "" + }); + } + + private handleRemove () { + this.props.onRemove(this.props.text); + } + + private handleEditBegin () { + this.setState({ + editing: true + , editValue: this.props.text + }, () => { + this.input.focus(); + }); + } + + private handleEditEnd (ev: React.FocusEvent) { + this.stopEditing(ev.target); + } + + private handleInputChange (ev: React.ChangeEvent) { + this.setState({ + editValue: ev.target.value + }); + + if (!this.props.itemPattern.test(ev.target.value)) { + ev.target.setCustomValidity(this.props.itemPatternError()); + } else { + ev.target.setCustomValidity(""); + } + } + + private handleInputKeyPress (ev: React.KeyboardEvent) { + if (ev.key === "Enter") { + this.stopEditing(ev.target as HTMLInputElement); + } + } } diff --git a/ext/src/options/defaultOptions.js b/ext/src/options/defaultOptions.js deleted file mode 100644 index dac682d..0000000 --- a/ext/src/options/defaultOptions.js +++ /dev/null @@ -1,13 +0,0 @@ -export default { - mediaEnabled: true - , mediaSyncElement: false - , mediaStopOnUnload: false - , localMediaEnabled: true - , localMediaServerPort: 9555 - , mirroringEnabled: false - , mirroringAppId: MIRRORING_APP_ID - , userAgentWhitelistEnabled: true - , userAgentWhitelist: [ - "https://www.netflix.com/*" - ] -} diff --git a/ext/src/options/defaultOptions.ts b/ext/src/options/defaultOptions.ts new file mode 100644 index 0000000..c75d191 --- /dev/null +++ b/ext/src/options/defaultOptions.ts @@ -0,0 +1,28 @@ +"use strict"; + +export interface Options { + [ key: string ]: any; + mediaEnabled: boolean; + mediaSyncElement: boolean; + mediaStopOnUnload: boolean; + localMediaEnabled: boolean; + localMediaServerPort: number; + mirroringEnabled: boolean; + mirroringAppId: string; + userAgentWhitelistEnabled: boolean; + userAgentWhitelist: string[]; +} + +export default { + mediaEnabled: true + , mediaSyncElement: false + , mediaStopOnUnload: false + , localMediaEnabled: true + , localMediaServerPort: 9555 + , mirroringEnabled: false + , mirroringAppId: MIRRORING_APP_ID + , userAgentWhitelistEnabled: true + , userAgentWhitelist: [ + "https://www.netflix.com/*" + ] +} as Options; diff --git a/ext/src/options/index.jsx b/ext/src/options/index.tsx similarity index 91% rename from ext/src/options/index.jsx rename to ext/src/options/index.tsx index 4910473..9a957db 100644 --- a/ext/src/options/index.jsx +++ b/ext/src/options/index.tsx @@ -1,12 +1,13 @@ +/* tslint:disable:max-line-length */ "use strict"; import React, { Component } from "react"; import ReactDOM from "react-dom"; -import defaultOptions from "./defaultOptions"; +import defaultOptions, { Options } from "./defaultOptions"; -import EditableList from "./EditableList"; import Bridge from "./Bridge"; +import EditableList from "./EditableList"; import getBridgeInfo from "../lib/getBridgeInfo"; @@ -27,7 +28,7 @@ browser.runtime.getPlatformInfo() const MATCH_PATTERN_REGEX = /^(?:(?:(\*|https?|ftp):\/\/((?:\*\.|[^\/\*])+)|(file):\/\/\/?(?:\*\.|[^\/\*])+)(\/.*)|)$/; -function getInputValue (input) { +function getInputValue (input: HTMLInputElement) { switch (input.type) { case "checkbox": return input.checked; @@ -39,8 +40,21 @@ function getInputValue (input) { } } -class App extends Component { - constructor (props) { + +interface OptionsAppState { + hasLoaded: boolean; + options: Options; + bridgeInfo: any; + platform: string; + bridgeLoading: boolean; + isFormValid: boolean; + hasSaved: boolean; +} + +class App extends Component<{}, OptionsAppState> { + private form: HTMLFormElement; + + constructor (props: {}) { super(props); this.state = { @@ -72,105 +86,11 @@ class App extends Component { }); const bridgeInfo = await getBridgeInfo(); - const platform = await browser.runtime.getPlatformInfo(); - - this.setState({ - bridgeInfo - , platform: platform.os - , bridgeLoading: false - }) - } - - /** - * Set stored option values to current state - */ - setStorage () { - return browser.storage.sync.set({ - options: this.state.options - }); - } - - handleReset () { - this.setState({ - options: { ...defaultOptions } - }); - } - - async handleFormSubmit (ev) { - ev.preventDefault(); - - this.form.reportValidity(); - - try { - const { options: oldOptions } - = await browser.storage.sync.get("options"); - await this.setStorage(); - const { options } = await browser.storage.sync.get("options"); - - const alteredOptions = []; - - for (const [ key, val ] of Object.entries(options)) { - const oldVal = oldOptions[key]; - if (oldVal !== val) { - alteredOptions.push(key); - } - } - - this.setState({ - hasSaved: true - }, () => { - window.setTimeout(() => { - this.setState({ - hasSaved: false - }); - }, 1000) - }); - - // Send update message / event - browser.runtime.sendMessage({ - subject: "optionsUpdated" - , data: { alteredOptions } - }); - } catch (err) {} - } - - handleFormChange (ev) { - ev.preventDefault(); - - this.setState({ - isFormValid: this.form.checkValidity() - }); - } - - handleInputChange (ev) { - const { target } = ev; - - this.setState(({ options }) => { - options[target.name] = getInputValue(target); - return { options }; - }); - } - - handleWhitelistChange (whitelist) { - this.setState(({ options }) => { - options.userAgentWhitelist = whitelist; - return { options }; - }); - } - - getWhitelistItemPatternError (info) { - return _("optionsUserAgentWhitelistInvalidMatchPattern", info); - } - - async updateBridgeInfo () { - this.setState({ - bridgeLoading: true - }); - - const bridgeInfo = await getBridgeInfo(); + const { os } = await browser.runtime.getPlatformInfo(); this.setState({ bridgeInfo + , platform: os , bridgeLoading: false }); } @@ -338,6 +258,102 @@ class App extends Component { ); } + + /** + * Set stored option values to current state + */ + private setStorage () { + return browser.storage.sync.set({ + options: this.state.options + }); + } + + private handleReset () { + this.setState({ + options: { ...defaultOptions } + }); + } + + private async handleFormSubmit (ev: React.FormEvent) { + ev.preventDefault(); + + this.form.reportValidity(); + + try { + const { options: oldOptions } + = await browser.storage.sync.get("options"); + await this.setStorage(); + const { options } = await browser.storage.sync.get("options"); + + const alteredOptions = []; + + for (const [ key, val ] of Object.entries(options)) { + const oldVal = oldOptions[key]; + if (oldVal !== val) { + alteredOptions.push(key); + } + } + + this.setState({ + hasSaved: true + }, () => { + window.setTimeout(() => { + this.setState({ + hasSaved: false + }); + }, 1000); + }); + + // Send update message / event + browser.runtime.sendMessage({ + subject: "optionsUpdated" + , data: { alteredOptions } + }); + } catch (err) { + console.error("Failed to save options"); + } + } + + private handleFormChange (ev: React.FormEvent) { + ev.preventDefault(); + + this.setState({ + isFormValid: this.form.checkValidity() + }); + } + + private handleInputChange (ev: React.ChangeEvent) { + const { target } = ev; + + this.setState(({ options }) => { + options[target.name] = getInputValue(target); + return { options }; + }); + } + + private handleWhitelistChange (whitelist: string[]) { + this.setState(({ options }) => { + options.userAgentWhitelist = whitelist; + return { options }; + }); + } + + private getWhitelistItemPatternError (info: string): string { + return _("optionsUserAgentWhitelistInvalidMatchPattern", info); + } + + private async updateBridgeInfo () { + this.setState({ + bridgeLoading: true + }); + + const bridgeInfo = await getBridgeInfo(); + + this.setState({ + bridgeInfo + , bridgeLoading: false + }); + } } diff --git a/ext/webpack.config.js b/ext/webpack.config.js index bad4d09..e2f893e 100755 --- a/ext/webpack.config.js +++ b/ext/webpack.config.js @@ -8,7 +8,7 @@ module.exports = (env) => ({ entry: { "main" : `${env.includePath}/main.ts` , "popup/bundle" : `${env.includePath}/popup/index.jsx` - , "options/bundle" : `${env.includePath}/options/index.jsx` + , "options/bundle" : `${env.includePath}/options/index.tsx` , "updater/bundle" : `${env.includePath}/updater/index.jsx` , "mediaCast" : `${env.includePath}/mediaCast.js` , "mirroringCast" : `${env.includePath}/mirroringCast.js` diff --git a/tslintCommon.json b/tslintCommon.json index c4d25e5..013976d 100644 --- a/tslintCommon.json +++ b/tslintCommon.json @@ -13,6 +13,7 @@ "limit": 80 , "ignore-pattern": "//|.*\";$" }] + , "member-access": [ true, "no-public" ] , "no-console": [ true, "log" ] , "no-namespace": [ true, "allow-declarations" ] , "object-literal-sort-keys": false