* feat: 🎸 Add code-editor component (#1207)

* feat: 🎸 Add code-editor component

Added code editor component which was taken from HCP, tweaked styles and
imports to use boundary assets

✅ Closes: ICU-5167
This commit is contained in:
Zhihe Li authored and GitHub committed 2022-07-29 17:18:07 -04:00
1 parent 40184006cd
commit b722fa361b
22 files changed
+637 -37

No files matched your search

@@ -0,0 +1,6 @@
<div
data-test-code-editor-field-editor
...attributes
class='{{@classNames}} rose-codemirror-container'
{{code-mirror value=@value onInput=@onInput options=@options}}
></div>
@@ -0,0 +1,8 @@
<div data-test-code-editor>
{{yield
(hash
fieldEditor=(component 'rose/code-editor/field-editor' value=@codeValue)
toolbar=(component 'rose/code-editor/toolbar' copyText=@codeValue)
)
}}
</div>
@@ -0,0 +1,90 @@
import { Meta, Story, Preview } from '@storybook/addon-docs/blocks';
import { hbs } from 'ember-cli-htmlbars';
<Meta title="Rose|Code Editor" component="CodeEditor" />
# Code Editor
`CodeEditor` is a component that yields two presentational components which together provide an IDE-like UX.
CodeEditor::fieldEditor is where the provided code is displayed with syntax highlighting.
CodeEditor::toolbar is intended to go on top of the fieldEditor and provides a 'Copy code' button as well as other optional user-provided actions.
```html
<CodeEditor @codeValue="{{this.codeIWantToSee}}" as |c|>
<c.toolbar />
<c.fieldEditor />
</CodeEditor>
```
<!-- mdx seems to not be able to handle template literals -->
export const codeValue =
'hcp_boundary_cluster_id = "<cluster-id>"\n\n' +
'listener "tcp" {\n' +
' address = "0.0.0.0:9202"\n' +
' purpose = "proxy"\n' +
'}\n\n' +
'worker {\n' +
' public_addr = "107.22.128.152"\n' +
' auth_storage_path = "/home/ubuntu/boundary/worker1"\n' +
' tags {\n' +
' type = ["dev-worker", "ubuntu"]\n' +
' }\n' +
'}';
<Preview>
<Story name="Readonly">
{{
template: hbs`
<Rose::CodeEditor @codeValue={{codeValue}} as |c|>
<c.toolbar />
<c.fieldEditor @options={{options}} />
</Rose::CodeEditor>`,
context: {
codeValue: codeValue,
options: {
mode: 'hcl',
readOnly: true,
},
},
}}
</Story>
</Preview>
<Preview>
<Story name="CodeEditorShell">
{{
template: hbs`
<Rose::CodeEditor @codeValue={{codeValue}} as |c|>
<c.toolbar />
<c.fieldEditor @classNames='rose-autosize' @options={{options}} />
</Rose::CodeEditor>`,
context: {
codeValue: 'mkdir /home/ubuntu/boundary/',
options: {
mode: 'shell',
readOnly: true,
},
},
}}
</Story>
</Preview>
<Preview>
<Story name="CodeEditorShellEditable">
{{
template: hbs`
<Rose::CodeEditor @codeValue={{codeValue}} as |c|>
<c.toolbar />
<c.fieldEditor @classNames='autosize' @options={{options}} />
</Rose::CodeEditor>`,
context: {
codeValue: 'mkdir /home/ubuntu/boundary/',
options: {
mode: 'shell',
readOnly: false,
},
},
}}
</Story>
</Preview>
@@ -0,0 +1,29 @@
<div class='rose-code-editor-toolbar' data-test-code-editor-toolbar>
<div data-test-code-editor-toolbar-action class='code-editor-toolbar__action'>
{{yield to='action'}}
</div>
<div class='rose-code-editor-toolbar__right-aligned'>
{{#if (has-block 'menu')}}
<div
data-test-code-editor-toolbar-menu
class='rose-code-editor-toolbar__menu'
>
{{yield to='menu'}}
</div>
<div
class='rose-code-editor-toolbar__menu-divider'
data-test-code-editor-toolbar-menu-divider
></div>
{{/if}}
<CopyButton
@clipboardText={{@copyText}}
@success={{this.copied}}
class='rose-code-editor-toolbar__copy-button'
data-test-code-editor-toolbar-copy-button
>
<Rose::Icon @name={{this.copyIconType}} @size='medium' />
Copy code
</CopyButton>
</div>
</div>
@@ -0,0 +1,25 @@
import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';
import { action } from '@ember/object';
import { later } from '@ember/runloop';
export const COPY_ICON_TYPE = 'flight-icons/svg/clipboard-copy-16';
export const COPIED_ICON_TYPE = 'flight-icons/svg/clipboard-checked-16';
export default class RoseCodeEditorToolbarComponent extends Component {
@tracked copyIconType = COPY_ICON_TYPE;
@action
copied() {
let { onCopy } = this.args;
let originalIconType = this.copyIconType;
this.copyIconType = COPIED_ICON_TYPE;
if (onCopy) {
onCopy();
}
later(() => (this.copyIconType = originalIconType), 1000);
}
}
@@ -10,14 +10,16 @@ import { text, boolean, select } from '@storybook/addon-knobs';
Proxies the built-in `LinkTo` component, applying a class `rose-nav-link`.
```html
<Rose::Nav::Link @route='index'>Text</nav.link>
<Rose::Nav::Link @route="index">Text</Rose::Nav::Link>
```
<Preview>
<Story name="Basic Nav Link">{{
template: hbs`
<Rose::Nav::Link @route='index'>Text</nav.link>
<Story name="Basic Nav Link">
{{
template: hbs`
<Rose::Nav::Link @route='index'>Text</Rose::Nav::Link>
`,
context: {},
}}</Story>
context: {},
}}
</Story>
</Preview>
@@ -0,0 +1,88 @@
import Modifier from 'ember-modifier';
import codemirror from 'codemirror';
import '../utilities/register-codemirror-hcl';
import 'codemirror/mode/go/go';
import 'codemirror/mode/javascript/javascript';
import 'codemirror/mode/shell/shell';
import 'codemirror/addon/edit/matchbrackets';
import 'codemirror/addon/edit/closebrackets';
import 'codemirror/addon/selection/active-line';
// Here we define default options for the editor.
// These should follow the codemirror configuration types
//
const _PRESET_DEFAULTS = {
theme: 'monokai',
lineNumbers: true,
cursorBlinkRate: 500,
matchBrackets: true,
autoCloseBrackets: true,
styleActiveLine: true,
mode: 'hcl',
};
/**
*
* `CodeMirror` implements a modifier that creates a CodeMirror instance on the provided element.
*
* The supported modes for the editor are currently: hcl, shell, go, javascript
* The supported themes are: monokai
*
* Sample usage:
* ```
* <div
* {{code-mirror value=@value onInput=@onInput options=@options}}
* />
* ```
*
* @class CodeMirror
*
*/
export default class CodeMirrorModifier extends Modifier {
_editor;
didInstall() {
this._setup();
}
didUpdateArguments() {
if (this._editor?.getValue() !== this.args.named.value) {
this._editor?.setValue(this.args.named.value);
}
}
/**
* Called when editor contents change.
* @method CodeMirror#_onChange
* See documentation for the CodeMirror editor events, specifically 'change' event here https://codemirror.net/doc/manual.html#events.
*/
_onChange(editor) {
const { onInput } = this.args.named;
const newVal = editor.getValue();
onInput && onInput(newVal);
}
/**
* Initializes the editor with default configuration merged with consumer-provided configuration.
* Also registers a 'change' event on the editor.
* @method CodeMirror#_setup
*/
_setup() {
if (!this.element) {
throw new Error('CodeMirror modifier has no element');
}
const editor = codemirror(this.element, {
..._PRESET_DEFAULTS,
...(this.args.named.options || {}),
value: this.args.named.value,
});
editor.on('change', (editor) => {
this._onChange(editor);
});
this._editor = editor;
}
}
@@ -1,7 +1,7 @@
import { modifier } from 'ember-modifier';
/**
* Used to detect clicks occuring _inside_ the modified element.
* Used to detect clicks occurring _inside_ the modified element.
* This is useful especially for dropdowns to toggle content visibility
* when the user clicks an item.
*/
@@ -1,7 +1,7 @@
import { modifier } from 'ember-modifier';
/**
* Used to detect clicks occuring _outside_ of the modified element.
* Used to detect clicks occurring _outside_ of the modified element.
* This is useful especially for dropdowns to toggle content visibility
* when the user clicks away.
*/
@@ -19,3 +19,4 @@
@import 'link-button';
@import 'badge';
@import 'toolbar';
@import 'code-editor';
@@ -0,0 +1,80 @@
@use '../../variables/sizing';
// Codemirror overrides
.rose-codemirror-container {
width: 100%;
}
.CodeMirror {
max-width: 100%;
display: flex;
flex: 1;
font-family: ui-monospace, 'Menlo', monospace;
}
.rose-autosize {
.CodeMirror {
height: auto;
}
}
.CodeMirror-scroll {
width: 100%;
}
.CodeMirror-sizer {
border-right-width: 0px !important;
}
// Toolbar
.rose-code-editor-toolbar {
display: flex;
justify-content: space-between;
align-items: center;
background-color: var(--ui-gray-subtler-6);
border-top: 1px solid var(--ui-gray-subtler-3);
border-bottom: 1px solid var(--ui-gray-subtler-3);
height: 2.75rem;
&__action {
margin-left: sizing.rems(s);
}
&__right-aligned {
display: flex;
height: 100%;
align-items: center;
}
&__menu {
margin-right: sizing.rems(s);
.pds-dropdownTrigger {
box-shadow: none;
&__layoutWrapper {
padding-left: sizing.rems(s);
padding-right: sizing.rems(s);
}
}
&-divider {
border-right: 1px solid var(--ui-gray-subtler-3);
height: sizing.rems(xl);
}
}
&__copy-button {
border: none;
background-color: inherit;
cursor: pointer;
color: var(--ui-gray-starker-2);
margin-right: sizing.rems(xs);
margin-left: sizing.rems(s);
height: sizing.rems(xl);
&-icon {
margin-right: sizing.rems(xs);
}
}
}
@@ -0,0 +1,38 @@
import codemirror from 'codemirror';
import 'codemirror/addon/mode/simple';
// This utility defines 'hcl' mode for a codemirror editor and enables correct syntax highlighting.
// Importing this file in the codemirror modifier will allow 'hcl' to be selected as a mode:
// import 'cloud-ui-core/utils/register-codemirror-hcl'
codemirror.defineSimpleMode('hcl', {
start: [
{ regex: /"(?:[^\\]|\\.)*?(?:"|$)/, token: 'string' }, // strings
{ regex: /(\w+)(\s+)(=)/, token: ['keyword', 'null', 'null'] }, // assignment of variables
{
regex: /(build|deploy|release|hook|registry|type|runner|url)( )({)/,
token: ['keyword', 'null', 'null'],
}, // top level keywords
{ regex: /(variable)\b/, token: 'keyword' }, // input variable keyword
{ regex: /true|false|null|undefined/, token: 'atom' }, // bool keywords
{
regex: /0x[a-f\d]+|[-+]?(?:\.\d+|\d+\.?\d*)(?:e[-+]?\d+)?/i,
token: 'number',
}, // numbers
{ regex: /(#|\/\/)(\s*\S*)/, token: 'comment' }, // single line comments
{ regex: /(path)(.)/, token: ['variable-2', 'null'] }, // path variables
{ regex: /(workspace)(.)(\S*)/, token: ['string', 'null', 'string'] }, // workspace variables
{ regex: /\/\*/, token: 'comment', next: 'comment' }, // multi-line comment
{ regex: /[-+/*=<>!]+/, token: 'operator' }, // operators
{ regex: /[{[(]/, indent: true }, // for auto indent
{ regex: /[}\])]/, dedent: true },
],
// The multi-line comment state.
comment: [
{ regex: /.*?\*\//, token: 'comment', next: 'start' },
{ regex: /.*/, token: 'comment' },
],
meta: {
dontIndentStates: ['comment'],
lineComment: '#',
},
});
@@ -0,0 +1 @@
export { default } from 'rose/components/rose/code-editor';
@@ -0,0 +1 @@
export { default } from 'rose/components/rose/code-editor/field-editor';
@@ -0,0 +1 @@
export { default } from 'rose/components/rose/code-editor/toolbar';
+1
View File
@@ -0,0 +1 @@
export { default } from 'rose/modifiers/code-mirror';
+3
View File
@@ -7,6 +7,9 @@ module.exports = function (defaults) {
// Add options here
});
app.import('node_modules/codemirror/lib/codemirror.css');
app.import('node_modules/codemirror/theme/monokai.css');
/*
This build file specifies the options for the dummy test app of this
addon, located in `/tests/dummy`
+3 -1
View File
@@ -31,8 +31,10 @@
"doc:toc": "doctoc README.md"
},
"dependencies": {
"codemirror": "5.65.7",
"ember-auto-import": "^2.4.2",
"ember-cli-babel": "^7.26.8",
"ember-cli-clipboard": "^0.16.0",
"ember-cli-htmlbars": "^5.7.1",
"ember-composable-helpers": "^5.0.0",
"ember-focus-trap": "^0.7.0",
@@ -112,6 +114,6 @@
"lint-staged": {
"*.js": "eslint --fix",
"*.hbs": "ember-template-lint --fix",
"*.{js,scss}": "prettier --write"
"*.{js,scss,mdx}": "prettier --write"
}
}
@@ -0,0 +1,27 @@
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import { render } from '@ember/test-helpers';
import { hbs } from 'ember-cli-htmlbars';
module('Integration | Component | rose/code-editor', function (hooks) {
setupRenderingTest(hooks);
test('it renders', async function (assert) {
const codeValue = 'export HCP_CLIENT_ID = {place your client_id here}';
this.set('codeValue', codeValue);
await render(hbs`
<Rose::CodeEditor
@codeValue={{this.codeValue}}
as |c|
>
<c.toolbar />
<c.fieldEditor />
</Rose::CodeEditor>
`);
assert.dom('[data-test-code-editor]').isVisible();
assert.dom('[data-test-code-editor-toolbar]').isVisible();
assert.dom('[data-test-code-editor-field-editor]').isVisible();
assert.dom('[data-test-code-editor-field-editor]').includesText(codeValue);
});
});
@@ -0,0 +1,69 @@
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import { typeIn, render, waitUntil } from '@ember/test-helpers';
import { hbs } from 'ember-cli-htmlbars';
module(
'Integration | Component | rose/code-editor/field-editor',
function (hooks) {
setupRenderingTest(hooks);
const editorSelector = '[data-test-code-editor-field-editor]';
test('it renders', async function (assert) {
const codeValue = `export HCP_CLIENT_ID = {place your client_id here}`;
this.set('codeValue', codeValue);
await render(hbs`
<Rose::CodeEditor::FieldEditor @value={{this.codeValue}} />
`);
assert.dom(editorSelector).isVisible();
assert.dom(editorSelector).includesText(codeValue);
const myNewCode = 'NEW CODE';
await typeIn(`${editorSelector} textarea`, myNewCode);
assert.dom(editorSelector).includesText(myNewCode);
});
test('it renders readonly', async function (assert) {
const codeValue = `export HCP_CLIENT_ID = {place your client_id here}`;
this.set('codeValue', codeValue);
this.set('options', {
readOnly: true,
});
await render(hbs`
<Rose::CodeEditor::FieldEditor @value={{this.codeValue}} @options={{this.options}} />
`);
assert.dom(editorSelector).isVisible();
assert.dom(editorSelector).includesText(codeValue);
const myNewCode = 'NEW CODE';
waitUntil(async () => {
try {
// This should fail if the textarea is readonly
await typeIn(`${editorSelector} textarea`, myNewCode);
} catch {
return true;
}
});
assert.dom(editorSelector).doesNotIncludeText(myNewCode);
});
test('it calls onInput on change', async function (assert) {
const codeValue = `export HCP_CLIENT_ID = {place your client_id here}`;
const onInput = () => {
this.set('called', true);
};
this.set('codeValue', codeValue);
this.set('onInput', onInput);
await render(hbs`
<Rose::CodeEditor::FieldEditor @value={{this.codeValue}} @onInput={{this.onInput}} />
`);
assert.dom(editorSelector).isVisible();
assert.dom(editorSelector).includesText(codeValue);
const myNewCode = 'NEW CODE';
await typeIn(`${editorSelector} textarea`, myNewCode);
assert.dom(editorSelector).includesText(myNewCode);
assert.true(this.called);
});
}
);
@@ -0,0 +1,55 @@
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import { click, render } from '@ember/test-helpers';
import { hbs } from 'ember-cli-htmlbars';
module('Integration | Component | rose/code-editor/toolbar', function (hooks) {
setupRenderingTest(hooks);
const toolbarSelector = '[data-test-code-editor-toolbar]';
const copyButtonSelector = '[data-test-code-editor-toolbar-copy-button]';
const menuDividerSelector = '[data-test-code-editor-toolbar-menu-divider]';
hooks.beforeEach(function () {
const copyText = 'copyText';
this.set('copyText', copyText);
});
test('it renders', async function (assert) {
await render(hbs`
<Rose::CodeEditor::Toolbar @copyText={{this.copyText}} />
`);
assert.dom(toolbarSelector).isVisible();
assert.dom(copyButtonSelector).isVisible();
assert.dom(menuDividerSelector).doesNotExist();
});
test('it displays action', async function (assert) {
await render(hbs`
<Rose::CodeEditor::Toolbar @onCopy={{this.copyText}}>
<:action>
<div data-test-my-action>Hello</div>
</:action>
</Rose::CodeEditor::Toolbar>
`);
assert.dom(toolbarSelector).isVisible();
assert.dom(copyButtonSelector).isVisible();
assert.dom(menuDividerSelector).doesNotExist();
assert.dom('[data-test-my-action]').isVisible();
});
test('it calls onCopy callback', async function (assert) {
const onCopy = () => {
this.set('called', true);
};
this.set('onCopy', onCopy);
await render(hbs`
<Rose::CodeEditor::Toolbar @copyText={{this.copyText}} @onCopy={{this.onCopy}} />
`);
assert.dom(toolbarSelector).isVisible();
assert.dom(copyButtonSelector).isVisible();
assert.dom(menuDividerSelector).doesNotExist();
await click(copyButtonSelector);
assert.true(this.called);
});
});
+101 -28
View File
@@ -3869,7 +3869,7 @@
ember-cli-babel "^7.22.1"
ember-compatibility-helpers "^1.1.1"
"@ember/render-modifiers@^2.0.4":
"@ember/render-modifiers@^1.0.2 || ^2.0.0", "@ember/render-modifiers@^2.0.4":
version "2.0.4"
resolved "https://registry.yarnpkg.com/@ember/render-modifiers/-/render-modifiers-2.0.4.tgz#0ac7af647cb736076dbfcd54ca71e090cd329d71"
integrity sha512-Zh/fo5VUmVzYHkHVvzWVjJ1RjFUxA2jH0zCp2+DQa80Bf3DUXauiEByxU22UkN4LFT55DBFttC0xCQSJG3WTsg==
@@ -9420,13 +9420,13 @@ browserify-zlib@^0.2.0:
pako "~1.0.5"
browserslist@4.14.2, browserslist@^4.0.0, browserslist@^4.12.0, browserslist@^4.14.5, browserslist@^4.16.5, browserslist@^4.16.6, browserslist@^4.16.7, browserslist@^4.17.3, browserslist@^4.17.5, browserslist@^4.19.1, browserslist@^4.20.2, browserslist@^4.21.0:
version "4.21.1"
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.1.tgz#c9b9b0a54c7607e8dc3e01a0d311727188011a00"
integrity sha512-Nq8MFCSrnJXSc88yliwlzQe3qNe3VntIjhsArW9IJOEPSHNx23FalwApUVbzAWABLhYJJ7y8AynWI/XM8OdfjQ==
version "4.21.2"
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.2.tgz#59a400757465535954946a400b841ed37e2b4ecf"
integrity sha512-MonuOgAtUB46uP5CezYbRaYKBNt2LxP0yX+Pmj4LkcDFGkn9Cbpi83d9sCjwQDErXsIJSzY5oKGDbgOlF/LPAA==
dependencies:
caniuse-lite "^1.0.30001359"
electron-to-chromium "^1.4.172"
node-releases "^2.0.5"
caniuse-lite "^1.0.30001366"
electron-to-chromium "^1.4.188"
node-releases "^2.0.6"
update-browserslist-db "^1.0.4"
bser@2.1.1:
@@ -9758,10 +9758,10 @@ caniuse-api@^3.0.0:
lodash.memoize "^4.1.2"
lodash.uniq "^4.5.0"
caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001157, caniuse-lite@^1.0.30001359:
version "1.0.30001364"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001364.tgz#1e118f0e933ed2b79f8d461796b8ce45398014a0"
integrity sha512-9O0xzV3wVyX0SlegIQ6knz+okhBB5pE0PC40MNdwcipjwpxoUEHL24uJ+gG42cgklPjfO5ZjZPme9FTSN3QT2Q==
caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001157, caniuse-lite@^1.0.30001366:
version "1.0.30001367"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001367.tgz#2b97fe472e8fa29c78c5970615d7cd2ee414108a"
integrity sha512-XDgbeOHfifWV3GEES2B8rtsrADx4Jf+juKX2SICJcaUhjYBO3bR96kvEIHa15VU6ohtOhBZuPGGYGbXMRn0NCw==
capture-exit@^2.0.0:
version "2.0.0"
@@ -10155,6 +10155,15 @@ cli-width@^3.0.0:
resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-3.0.0.tgz#a2f48437a2caa9a22436e794bf071ec9e61cedf6"
integrity sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==
clipboard@^2.0.6:
version "2.0.11"
resolved "https://registry.yarnpkg.com/clipboard/-/clipboard-2.0.11.tgz#62180360b97dd668b6b3a84ec226975762a70be5"
integrity sha512-C+0bbOqkezLIsmWSvlsXS0Q0bmkugu7jcfMIACB+RDEntIzQIkdr148we28AfSloQLRdZlYL/QYyrq05j/3Faw==
dependencies:
good-listener "^1.2.2"
select "^1.1.2"
tiny-emitter "^2.0.0"
clipboard@^2.0.8:
version "2.0.8"
resolved "https://registry.yarnpkg.com/clipboard/-/clipboard-2.0.8.tgz#ffc6c103dd2967a83005f3f61976aa4655a4cdba"
@@ -10251,6 +10260,11 @@ code-point-at@^1.0.0:
resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=
codemirror@5.65.7:
version "5.65.7"
resolved "https://registry.yarnpkg.com/codemirror/-/codemirror-5.65.7.tgz#29af41ce5f4c2b8f1c1e16f4e645ff392823716a"
integrity sha512-zb67cXzgugIQmb6tfD4G11ILjYoMfTjwcjn+cWsa4GewlI2adhR/h3kolkoCQTm1msD/1BuqVTKuO09ELsS++A==
collapse-white-space@^1.0.2:
version "1.0.6"
resolved "https://registry.yarnpkg.com/collapse-white-space/-/collapse-white-space-1.0.6.tgz#e63629c0016665792060dbbeb79c42239d2c5287"
@@ -11757,10 +11771,10 @@ electron-rebuild@^3.2.6:
tar "^6.0.5"
yargs "^17.0.1"
electron-to-chromium@^1.4.172:
version "1.4.182"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.182.tgz#5d59214ebfe90b36f23e81cd226a42732cd8c677"
integrity sha512-OpEjTADzGoXABjqobGhpy0D2YsTncAax7IkER68ycc4adaq0dqEG9//9aenKPy7BGA90bqQdLac0dPp6uMkcSg==
electron-to-chromium@^1.4.188:
version "1.4.195"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.195.tgz#139b2d95a42a3f17df217589723a1deac71d1473"
integrity sha512-vefjEh0sk871xNmR5whJf9TEngX+KTKS3hOHpjoMpauKkwlGwtMz1H8IaIjAT/GNnX0TbGwAdmVoXCAzXf+PPg==
element-resize-detector@^1.2.2:
version "1.2.3"
@@ -11836,6 +11850,41 @@ ember-auto-import@^1.10.1, ember-auto-import@^1.11.2, ember-auto-import@^1.2.15,
walk-sync "^0.3.3"
webpack "^4.43.0"
ember-auto-import@^1.11.3:
version "1.12.2"
resolved "https://registry.yarnpkg.com/ember-auto-import/-/ember-auto-import-1.12.2.tgz#cc7298ee5c0654b0249267de68fb27a2861c3579"
integrity sha512-gLqML2k77AuUiXxWNon1FSzuG1DV7PEPpCLCU5aJvf6fdL6rmFfElsZRh+8ELEB/qP9dT+LHjNEunVzd2dYc8A==
dependencies:
"@babel/core" "^7.1.6"
"@babel/preset-env" "^7.10.2"
"@babel/traverse" "^7.1.6"
"@babel/types" "^7.1.6"
"@embroider/shared-internals" "^1.0.0"
babel-core "^6.26.3"
babel-loader "^8.0.6"
babel-plugin-syntax-dynamic-import "^6.18.0"
babylon "^6.18.0"
broccoli-debug "^0.6.4"
broccoli-node-api "^1.7.0"
broccoli-plugin "^4.0.0"
broccoli-source "^3.0.0"
debug "^3.1.0"
ember-cli-babel "^7.0.0"
enhanced-resolve "^4.0.0"
fs-extra "^6.0.1"
fs-tree-diff "^2.0.0"
handlebars "^4.3.1"
js-string-escape "^1.0.1"
lodash "^4.17.19"
mkdirp "^0.5.1"
resolve-package-path "^3.1.0"
rimraf "^2.6.2"
semver "^7.3.4"
symlink-or-copy "^1.2.0"
typescript-memoize "^1.0.0-alpha.3"
walk-sync "^0.3.3"
webpack "^4.43.0"
ember-auto-import@^2.4.2:
version "2.4.2"
resolved "https://registry.yarnpkg.com/ember-auto-import/-/ember-auto-import-2.4.2.tgz#d4d3bc6885a11cf124f606f5c37169bdf76e37ae"
@@ -11961,6 +12010,17 @@ ember-cli-babel@^6.16.0, ember-cli-babel@^6.6.0, ember-cli-babel@^6.8.1, ember-c
rimraf "^3.0.1"
semver "^5.5.0"
ember-cli-clipboard@^0.16.0:
version "0.16.0"
resolved "https://registry.yarnpkg.com/ember-cli-clipboard/-/ember-cli-clipboard-0.16.0.tgz#f4878cbbfbc56e0bc6d2a65ccf5a334c47b0f614"
integrity sha512-l9iDVjcJLkbgpdbJe+bN29q2ibZmEpEV6bXstIG9q4HPvaqbXw0PbSFhaNeQWpJKNkd5dFKSNdgEfli6heJSFw==
dependencies:
"@ember/render-modifiers" "^1.0.2 || ^2.0.0"
clipboard "^2.0.6"
ember-auto-import "^1.11.3"
ember-cli-babel "^7.26.6"
ember-cli-htmlbars "^5.7.1"
ember-cli-code-coverage@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/ember-cli-code-coverage/-/ember-cli-code-coverage-1.0.3.tgz#9a6e5e6350d70761eba749d68ebe2e0d9aa3492f"
@@ -16417,6 +16477,11 @@ ip@1.1.5, ip@^1.1.5:
resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a"
integrity sha512-rBtCAQAJm8A110nbwn6YdveUnuZH3WrC36IwkRXxDnq53JvXA2NVQvB7IHyKomxK1MJ4VDNw3UtFDdXQ+AvLYA==
ip@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/ip/-/ip-2.0.0.tgz#4cf4ab182fee2314c75ede1276f8c80b479936da"
integrity sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==
ipaddr.js@1.9.1:
version "1.9.1"
resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3"
@@ -20115,10 +20180,10 @@ node-notifier@^10.0.0, node-notifier@^8.0.1:
uuid "^8.3.0"
which "^2.0.2"
node-releases@^2.0.5:
version "2.0.5"
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.5.tgz#280ed5bc3eba0d96ce44897d8aee478bfb3d9666"
integrity sha512-U9h1NLROZTq9uE1SNffn6WuPDg8icmi3ns4rEl/oTfIle4iLjTliCzgTsbaIFMq/Xn078/lfY/BL0GWZ+psK4Q==
node-releases@^2.0.6:
version "2.0.6"
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.6.tgz#8a7088c63a55e493845683ebf3c828d8c51c5503"
integrity sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==
node-uuid@~1.4.7:
version "1.4.8"
@@ -21425,12 +21490,12 @@ playwright@^1.15.0:
yazl "^2.5.1"
plist@^3.0.0, plist@^3.0.1, plist@^3.0.4, plist@^3.0.5:
version "3.0.5"
resolved "https://registry.yarnpkg.com/plist/-/plist-3.0.5.tgz#2cbeb52d10e3cdccccf0c11a63a85d830970a987"
integrity sha512-83vX4eYdQp3vP9SxuYgEM/G/pJQqLUz/V/xzPrzruLs7fz7jxGQ1msZ/mg1nwZxUSuOp4sb+/bEIbRrbzZRxDA==
version "3.0.6"
resolved "https://registry.yarnpkg.com/plist/-/plist-3.0.6.tgz#7cfb68a856a7834bca6dbfe3218eb9c7740145d3"
integrity sha512-WiIVYyrp8TD4w8yCvyeIr+lkmrGRd5u0VbRnU+tP/aRLxP/YadJUYOMZJ/6hIa3oUyVCsycXvtNRgd5XBJIbiA==
dependencies:
base64-js "^1.5.1"
xmlbuilder "^9.0.7"
xmlbuilder "^15.1.1"
pluralize@^1.2.1:
version "1.2.1"
@@ -23986,7 +24051,15 @@ socks-proxy-agent@^6.0.0:
debug "^4.3.3"
socks "^2.6.2"
socks@^2.3.3, socks@^2.6.2:
socks@^2.3.3:
version "2.7.0"
resolved "https://registry.yarnpkg.com/socks/-/socks-2.7.0.tgz#f9225acdb841e874dca25f870e9130990f3913d0"
integrity sha512-scnOe9y4VuiNUULJN72GrM26BNOjVsfPXI+j+98PkyEfsIXroa5ofyjT+FzGvn/xHs73U2JtoBYAVx9Hl4quSA==
dependencies:
ip "^2.0.0"
smart-buffer "^4.2.0"
socks@^2.6.2:
version "2.6.2"
resolved "https://registry.yarnpkg.com/socks/-/socks-2.6.2.tgz#ec042d7960073d40d94268ff3bb727dc685f111a"
integrity sha512-zDZhHhZRY9PxRruRMR7kMhnf3I8hDs4S3f9RecfnGxvcBHQcKcIH/oUcEWffsfl1XxdYlA7nnlGbbTvPz9D8gA==
@@ -26711,10 +26784,10 @@ xml-name-validator@^3.0.0:
resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a"
integrity sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==
xmlbuilder@^9.0.7:
version "9.0.7"
resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-9.0.7.tgz#132ee63d2ec5565c557e20f4c22df9aca686b10d"
integrity sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=
xmlbuilder@^15.1.1:
version "15.1.1"
resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-15.1.1.tgz#9dcdce49eea66d8d10b42cae94a79c3c8d0c2ec5"
integrity sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==
xmlchars@^2.2.0:
version "2.2.0"