diff --git a/addons/rose/addon/components/rose/code-editor/field-editor/index.hbs b/addons/rose/addon/components/rose/code-editor/field-editor/index.hbs
new file mode 100644
index 000000000..82ed4cbae
--- /dev/null
+++ b/addons/rose/addon/components/rose/code-editor/field-editor/index.hbs
@@ -0,0 +1,6 @@
+
\ No newline at end of file
diff --git a/addons/rose/addon/components/rose/code-editor/index.hbs b/addons/rose/addon/components/rose/code-editor/index.hbs
new file mode 100644
index 000000000..1357f73dc
--- /dev/null
+++ b/addons/rose/addon/components/rose/code-editor/index.hbs
@@ -0,0 +1,8 @@
+
+ {{yield
+ (hash
+ fieldEditor=(component 'rose/code-editor/field-editor' value=@codeValue)
+ toolbar=(component 'rose/code-editor/toolbar' copyText=@codeValue)
+ )
+ }}
+
\ No newline at end of file
diff --git a/addons/rose/addon/components/rose/code-editor/index.stories.mdx b/addons/rose/addon/components/rose/code-editor/index.stories.mdx
new file mode 100644
index 000000000..05aacff99
--- /dev/null
+++ b/addons/rose/addon/components/rose/code-editor/index.stories.mdx
@@ -0,0 +1,90 @@
+import { Meta, Story, Preview } from '@storybook/addon-docs/blocks';
+import { hbs } from 'ember-cli-htmlbars';
+
+
+
+# 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
+
+
+
+
+```
+
+
+
+export const codeValue =
+ 'hcp_boundary_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' +
+ '}';
+
+
+
+ {{
+ template: hbs`
+
+
+
+ `,
+ context: {
+ codeValue: codeValue,
+ options: {
+ mode: 'hcl',
+ readOnly: true,
+ },
+ },
+ }}
+
+
+
+
+
+ {{
+ template: hbs`
+
+
+
+ `,
+ context: {
+ codeValue: 'mkdir /home/ubuntu/boundary/',
+ options: {
+ mode: 'shell',
+ readOnly: true,
+ },
+ },
+ }}
+
+
+
+
+
+ {{
+ template: hbs`
+
+
+
+ `,
+ context: {
+ codeValue: 'mkdir /home/ubuntu/boundary/',
+ options: {
+ mode: 'shell',
+ readOnly: false,
+ },
+ },
+ }}
+
+
diff --git a/addons/rose/addon/components/rose/code-editor/toolbar/index.hbs b/addons/rose/addon/components/rose/code-editor/toolbar/index.hbs
new file mode 100644
index 000000000..0d9b1928a
--- /dev/null
+++ b/addons/rose/addon/components/rose/code-editor/toolbar/index.hbs
@@ -0,0 +1,29 @@
+
\ No newline at end of file
diff --git a/addons/rose/addon/components/rose/code-editor/toolbar/index.js b/addons/rose/addon/components/rose/code-editor/toolbar/index.js
new file mode 100644
index 000000000..9ec546b66
--- /dev/null
+++ b/addons/rose/addon/components/rose/code-editor/toolbar/index.js
@@ -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);
+ }
+}
diff --git a/addons/rose/addon/components/rose/nav/link/index.stories.mdx b/addons/rose/addon/components/rose/nav/link/index.stories.mdx
index 198f434f4..655582cea 100644
--- a/addons/rose/addon/components/rose/nav/link/index.stories.mdx
+++ b/addons/rose/addon/components/rose/nav/link/index.stories.mdx
@@ -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
-Text
+Text
```
- {{
- template: hbs`
- Text
+
+ {{
+ template: hbs`
+ Text
`,
- context: {},
- }}
+ context: {},
+ }}
+
diff --git a/addons/rose/addon/modifiers/code-mirror.js b/addons/rose/addon/modifiers/code-mirror.js
new file mode 100644
index 000000000..6efa1a419
--- /dev/null
+++ b/addons/rose/addon/modifiers/code-mirror.js
@@ -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:
+ * ```
+ *
+ * ```
+ *
+ * @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;
+ }
+}
diff --git a/addons/rose/addon/modifiers/on-click-inside.js b/addons/rose/addon/modifiers/on-click-inside.js
index ec64ff5f7..6364121cd 100644
--- a/addons/rose/addon/modifiers/on-click-inside.js
+++ b/addons/rose/addon/modifiers/on-click-inside.js
@@ -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.
*/
diff --git a/addons/rose/addon/modifiers/on-click-outside.js b/addons/rose/addon/modifiers/on-click-outside.js
index be434a234..bab96ddaa 100644
--- a/addons/rose/addon/modifiers/on-click-outside.js
+++ b/addons/rose/addon/modifiers/on-click-outside.js
@@ -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.
*/
diff --git a/addons/rose/addon/styles/rose/components/_index.scss b/addons/rose/addon/styles/rose/components/_index.scss
index f8161a2c6..eaa43f53b 100644
--- a/addons/rose/addon/styles/rose/components/_index.scss
+++ b/addons/rose/addon/styles/rose/components/_index.scss
@@ -19,3 +19,4 @@
@import 'link-button';
@import 'badge';
@import 'toolbar';
+@import 'code-editor';
diff --git a/addons/rose/addon/styles/rose/components/code-editor/_index.scss b/addons/rose/addon/styles/rose/components/code-editor/_index.scss
new file mode 100644
index 000000000..962da8eff
--- /dev/null
+++ b/addons/rose/addon/styles/rose/components/code-editor/_index.scss
@@ -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);
+ }
+ }
+}
diff --git a/addons/rose/addon/utilities/register-codemirror-hcl.js b/addons/rose/addon/utilities/register-codemirror-hcl.js
new file mode 100644
index 000000000..f39180d72
--- /dev/null
+++ b/addons/rose/addon/utilities/register-codemirror-hcl.js
@@ -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: '#',
+ },
+});
diff --git a/addons/rose/app/components/rose/code-editor.js b/addons/rose/app/components/rose/code-editor.js
new file mode 100644
index 000000000..385898fb5
--- /dev/null
+++ b/addons/rose/app/components/rose/code-editor.js
@@ -0,0 +1 @@
+export { default } from 'rose/components/rose/code-editor';
diff --git a/addons/rose/app/components/rose/code-editor/field-editor.js b/addons/rose/app/components/rose/code-editor/field-editor.js
new file mode 100644
index 000000000..2fac9081d
--- /dev/null
+++ b/addons/rose/app/components/rose/code-editor/field-editor.js
@@ -0,0 +1 @@
+export { default } from 'rose/components/rose/code-editor/field-editor';
diff --git a/addons/rose/app/components/rose/code-editor/toolbar.js b/addons/rose/app/components/rose/code-editor/toolbar.js
new file mode 100644
index 000000000..b59e5c3c9
--- /dev/null
+++ b/addons/rose/app/components/rose/code-editor/toolbar.js
@@ -0,0 +1 @@
+export { default } from 'rose/components/rose/code-editor/toolbar';
diff --git a/addons/rose/app/modifiers/code-mirror.js b/addons/rose/app/modifiers/code-mirror.js
new file mode 100644
index 000000000..2251c72ee
--- /dev/null
+++ b/addons/rose/app/modifiers/code-mirror.js
@@ -0,0 +1 @@
+export { default } from 'rose/modifiers/code-mirror';
diff --git a/addons/rose/ember-cli-build.js b/addons/rose/ember-cli-build.js
index ba0649dc9..6d7b0d444 100644
--- a/addons/rose/ember-cli-build.js
+++ b/addons/rose/ember-cli-build.js
@@ -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`
diff --git a/addons/rose/package.json b/addons/rose/package.json
index 6cf3a5f59..5f0371cd2 100644
--- a/addons/rose/package.json
+++ b/addons/rose/package.json
@@ -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"
}
}
diff --git a/addons/rose/tests/integration/components/rose/code-editor-test.js b/addons/rose/tests/integration/components/rose/code-editor-test.js
new file mode 100644
index 000000000..e14d2c85c
--- /dev/null
+++ b/addons/rose/tests/integration/components/rose/code-editor-test.js
@@ -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`
+
+
+
+
+ `);
+ 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);
+ });
+});
diff --git a/addons/rose/tests/integration/components/rose/code-editor/field-editor-test.js b/addons/rose/tests/integration/components/rose/code-editor/field-editor-test.js
new file mode 100644
index 000000000..fb37c59b4
--- /dev/null
+++ b/addons/rose/tests/integration/components/rose/code-editor/field-editor-test.js
@@ -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`
+
+ `);
+ 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`
+
+ `);
+ 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`
+
+ `);
+ 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);
+ });
+ }
+);
diff --git a/addons/rose/tests/integration/components/rose/code-editor/toolbar-test.js b/addons/rose/tests/integration/components/rose/code-editor/toolbar-test.js
new file mode 100644
index 000000000..78608e9f8
--- /dev/null
+++ b/addons/rose/tests/integration/components/rose/code-editor/toolbar-test.js
@@ -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`
+
+ `);
+ assert.dom(toolbarSelector).isVisible();
+ assert.dom(copyButtonSelector).isVisible();
+ assert.dom(menuDividerSelector).doesNotExist();
+ });
+
+ test('it displays action', async function (assert) {
+ await render(hbs`
+
+ <:action>
+ Hello
+
+
+ `);
+ 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`
+
+ `);
+ assert.dom(toolbarSelector).isVisible();
+ assert.dom(copyButtonSelector).isVisible();
+ assert.dom(menuDividerSelector).doesNotExist();
+
+ await click(copyButtonSelector);
+ assert.true(this.called);
+ });
+});
diff --git a/yarn.lock b/yarn.lock
index 3e68500ea..9c7c673bb 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -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"