ember-inspector 4.11.0-alpha.2024.3.9 → 4.11.0-alpha.2024.4.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (83) hide show
  1. package/.github/dependabot.yml +1 -0
  2. package/.github/workflows/build.yml +5 -26
  3. package/.github/workflows/plan-release.yml +83 -0
  4. package/.github/workflows/publish.yml +58 -0
  5. package/app/components/component-tree-arg.js +9 -0
  6. package/app/components/component-tree-item.hbs +18 -2
  7. package/app/components/object-inspector/dependent-keys.hbs +9 -5
  8. package/app/components/object-inspector/properties-all.hbs +1 -0
  9. package/app/components/object-inspector/properties-base.js +10 -0
  10. package/app/components/object-inspector/properties-grouped.hbs +1 -0
  11. package/app/components/object-inspector/property.hbs +12 -1
  12. package/app/components/object-inspector/property.ts +4 -2
  13. package/app/components/object-inspector.hbs +16 -2
  14. package/app/components/object-inspector.js +14 -0
  15. package/app/controllers/component-tree.js +54 -3
  16. package/app/routes/component-tree.js +0 -6
  17. package/app/services/adapters/web-extension.js +3 -3
  18. package/app/services/port.js +4 -0
  19. package/app/styles/component_tree.scss +13 -0
  20. package/app/utils/parse-text.ts +1 -0
  21. package/dist/bookmarklet/panes-3-16-0/assets/{chunk.143.ac621af5331b75527946.js → chunk.143.26f04046dc6fc0e116a0.js} +4 -4
  22. package/dist/{firefox/panes-3-16-0/assets/chunk.178.e6b2f8bb19b9f072aa49.js → bookmarklet/panes-3-16-0/assets/chunk.178.38e53a46589969f0228d.js} +3 -3
  23. package/dist/bookmarklet/panes-3-16-0/assets/ember-inspector.css +13 -0
  24. package/dist/bookmarklet/panes-3-16-0/assets/ember-inspector.js +28 -24
  25. package/dist/bookmarklet/panes-3-16-0/assets/svg/code-source.svg +9 -0
  26. package/dist/bookmarklet/panes-3-16-0/assets/vendor.css +33 -0
  27. package/dist/bookmarklet/panes-3-16-0/assets/vendor.js +12 -10
  28. package/dist/bookmarklet/panes-3-16-0/ember_debug.js +453 -559
  29. package/dist/bookmarklet/panes-3-16-0/index.html +2 -2
  30. package/dist/chrome/manifest.json +2 -2
  31. package/dist/{firefox/panes-3-16-0/assets/chunk.143.ac621af5331b75527946.js → chrome/panes-3-16-0/assets/chunk.143.26f04046dc6fc0e116a0.js} +4 -4
  32. package/dist/{bookmarklet/panes-3-16-0/assets/chunk.178.e6b2f8bb19b9f072aa49.js → chrome/panes-3-16-0/assets/chunk.178.38e53a46589969f0228d.js} +3 -3
  33. package/dist/chrome/panes-3-16-0/assets/ember-inspector.css +13 -0
  34. package/dist/chrome/panes-3-16-0/assets/ember-inspector.js +28 -24
  35. package/dist/chrome/panes-3-16-0/assets/svg/code-source.svg +9 -0
  36. package/dist/chrome/panes-3-16-0/assets/vendor.css +33 -0
  37. package/dist/chrome/panes-3-16-0/assets/vendor.js +12 -10
  38. package/dist/chrome/panes-3-16-0/ember_debug.js +453 -559
  39. package/dist/chrome/panes-3-16-0/index.html +2 -2
  40. package/dist/firefox/manifest.json +2 -2
  41. package/dist/{chrome/panes-3-16-0/assets/chunk.143.ac621af5331b75527946.js → firefox/panes-3-16-0/assets/chunk.143.26f04046dc6fc0e116a0.js} +4 -4
  42. package/dist/{websocket/assets/chunk.178.e6b2f8bb19b9f072aa49.js → firefox/panes-3-16-0/assets/chunk.178.38e53a46589969f0228d.js} +3 -3
  43. package/dist/firefox/panes-3-16-0/assets/ember-inspector.css +13 -0
  44. package/dist/firefox/panes-3-16-0/assets/ember-inspector.js +28 -24
  45. package/dist/firefox/panes-3-16-0/assets/svg/code-source.svg +9 -0
  46. package/dist/firefox/panes-3-16-0/assets/vendor.css +33 -0
  47. package/dist/firefox/panes-3-16-0/assets/vendor.js +12 -10
  48. package/dist/firefox/panes-3-16-0/ember_debug.js +453 -559
  49. package/dist/firefox/panes-3-16-0/index.html +2 -2
  50. package/dist/websocket/assets/{chunk.143.ac621af5331b75527946.js → chunk.143.26f04046dc6fc0e116a0.js} +4 -4
  51. package/dist/{chrome/panes-3-16-0/assets/chunk.178.e6b2f8bb19b9f072aa49.js → websocket/assets/chunk.178.38e53a46589969f0228d.js} +3 -3
  52. package/dist/websocket/assets/ember-inspector.css +13 -0
  53. package/dist/websocket/assets/ember-inspector.js +28 -24
  54. package/dist/websocket/assets/svg/code-source.svg +9 -0
  55. package/dist/websocket/assets/vendor.css +33 -0
  56. package/dist/websocket/assets/vendor.js +12 -10
  57. package/dist/websocket/ember_debug.js +453 -559
  58. package/dist/websocket/index.html +2 -2
  59. package/ember-cli-build.js +3 -4
  60. package/ember_debug/adapters/basic.js +4 -4
  61. package/ember_debug/adapters/web-extension.js +9 -5
  62. package/ember_debug/general-debug.js +3 -1
  63. package/ember_debug/libs/capture-render-tree.js +7 -426
  64. package/ember_debug/libs/render-tree.js +210 -31
  65. package/ember_debug/libs/view-inspection.js +28 -0
  66. package/ember_debug/object-inspector.js +92 -109
  67. package/ember_debug/route-debug.js +2 -3
  68. package/ember_debug/utils/ember.js +16 -0
  69. package/ember_debug/utils/get-object-name.js +4 -0
  70. package/ember_debug/utils/name-functions.js +1 -1
  71. package/ember_debug/utils/type-check.js +82 -12
  72. package/ember_debug/utils/version.js +37 -0
  73. package/ember_debug/view-debug.js +1 -1
  74. package/lib/ui/addon/styles/_goto-source.scss +30 -0
  75. package/lib/ui/addon/styles/addon.scss +1 -0
  76. package/lib/ui/addon/styles/toolbar/_index.scss +4 -0
  77. package/package.json +2 -1
  78. package/public/assets/svg/code-source.svg +9 -0
  79. package/skeletons/web-extension/manifest.json +2 -2
  80. package/tests/acceptance/object-inspector-test.js +68 -0
  81. package/tests/ember_debug/object-inspector-test.js +18 -8
  82. package/tests/ember_debug/view-debug-test.js +211 -69
  83. package/tests/index.html +1 -0
@@ -7,6 +7,7 @@ updates:
7
7
  open-pull-requests-limit: 10
8
8
  labels:
9
9
  - dependencies
10
+ - internal
10
11
  ignore:
11
12
  - dependency-name: ember-cli
12
13
  versions:
@@ -252,7 +252,7 @@ jobs:
252
252
  needs:
253
253
  - test
254
254
  - ember-try
255
- - build
255
+ - build
256
256
  runs-on: ubuntu-latest
257
257
  steps:
258
258
  - name: Set up node
@@ -272,8 +272,8 @@ jobs:
272
272
  echo "REFRESH_TOKEN=${{ secrets.GOOGLE_NIGHTLY_REFRESH_TOKEN }}" >> $GITHUB_ENV
273
273
  else
274
274
  echo "EXTENSION_ID=bmdblncegkenkacieihfhpjfppoconhi" >> $GITHUB_ENV
275
- echo "CLIENT_ID=${{ secrets.GOOGLE_STABLE_CLIENT_ID }}" >> $GITHUB_ENV
276
- echo "REFRESH_TOKEN=${{ secrets.GOOGLE_STABLE_REFRESH_TOKEN }}" >> $GITHUB_ENV
275
+ echo "CLIENT_ID=${{ secrets.GOOGLE_NIGHTLY_CLIENT_ID }}" >> $GITHUB_ENV
276
+ echo "REFRESH_TOKEN=${{ secrets.GOOGLE_NIGHTLY_REFRESH_TOKEN }}" >> $GITHUB_ENV
277
277
  fi
278
278
  - name: Upload to Chrome Web Store
279
279
  if: >-
@@ -286,7 +286,7 @@ jobs:
286
286
  needs:
287
287
  - test
288
288
  - ember-try
289
- - build
289
+ - build
290
290
  runs-on: ubuntu-latest
291
291
  steps:
292
292
  - name: Set up nod
@@ -314,7 +314,7 @@ jobs:
314
314
  needs:
315
315
  - test
316
316
  - ember-try
317
- - build
317
+ - build
318
318
  runs-on: ubuntu-latest
319
319
  steps:
320
320
  - name: Set up node
@@ -336,25 +336,4 @@ jobs:
336
336
  npm whoami
337
337
  if [[ "$GITHUB_EVENT_NAME" == "schedule" ]]; then
338
338
  npm publish --tag alpha
339
- else
340
- npm publish
341
339
  fi
342
-
343
- publish-github:
344
- name: Publish GitHub release
345
- needs:
346
- - test
347
- - ember-try
348
- - build
349
- if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')
350
- runs-on: ubuntu-latest
351
- steps:
352
- - name: Create release
353
- uses: actions/create-release@v1
354
- env:
355
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
356
- with:
357
- tag_name: ${{ github.ref }}
358
- release_name: ${{ github.ref }}
359
- draft: false
360
- prerelease: false
@@ -0,0 +1,83 @@
1
+ name: Release Plan Review
2
+ on:
3
+ push:
4
+ branches:
5
+ - main
6
+ - master
7
+ pull_request:
8
+ types:
9
+ - labeled
10
+
11
+ concurrency:
12
+ group: plan-release # only the latest one of these should ever be running
13
+ cancel-in-progress: true
14
+
15
+ jobs:
16
+ check-plan:
17
+ name: "Check Release Plan"
18
+ runs-on: ubuntu-latest
19
+ outputs:
20
+ command: ${{ steps.check-release.outputs.command }}
21
+
22
+ steps:
23
+ - uses: actions/checkout@v4
24
+ with:
25
+ fetch-depth: 0
26
+ ref: 'main'
27
+ # This will only cause the `check-plan` job to have a "command" of `release`
28
+ # when the .release-plan.json file was changed on the last commit.
29
+ - id: check-release
30
+ run: if git diff --name-only HEAD HEAD~1 | grep -w -q ".release-plan.json"; then echo "command=release"; fi >> $GITHUB_OUTPUT
31
+
32
+ prepare_release_notes:
33
+ name: Prepare Release Notes
34
+ runs-on: ubuntu-latest
35
+ timeout-minutes: 5
36
+ needs: check-plan
37
+ outputs:
38
+ explanation: ${{ steps.explanation.outputs.text }}
39
+ # only run on push event if plan wasn't updated (don't create a release plan when we're releasing)
40
+ # only run on labeled event if the PR has already been merged
41
+ if: (github.event_name == 'push' && needs.check-plan.outputs.command != 'release') || (github.event_name == 'pull_request' && github.event.pull_request.merged == true)
42
+
43
+ steps:
44
+ - uses: actions/checkout@v4
45
+ # We need to download lots of history so that
46
+ # lerna-changelog can discover what's changed since the last release
47
+ with:
48
+ fetch-depth: 0
49
+ - uses: actions/setup-node@v4
50
+ with:
51
+ node-version: 18
52
+
53
+ - uses: pnpm/action-setup@v2
54
+ with:
55
+ version: 8
56
+ - run: pnpm install --frozen-lockfile
57
+
58
+ - name: "Generate Explanation and Prep Changelogs"
59
+ id: explanation
60
+ run: |
61
+ set -x
62
+
63
+ pnpm release-plan prepare --singlePackage=ember-inspector
64
+
65
+ echo 'text<<EOF' >> $GITHUB_OUTPUT
66
+ jq .description .release-plan.json -r >> $GITHUB_OUTPUT
67
+ echo 'EOF' >> $GITHUB_OUTPUT
68
+ env:
69
+ GITHUB_AUTH: ${{ secrets.GITHUB_TOKEN }}
70
+
71
+ - uses: peter-evans/create-pull-request@v5
72
+ with:
73
+ commit-message: "Prepare Release using 'release-plan'"
74
+ author: "github-actions[bot] <github-actions-bot@users.noreply.github.com>"
75
+ labels: "internal"
76
+ branch: release-preview
77
+ title: Prepare Release
78
+ body: |
79
+ This PR is a preview of the release that [release-plan](https://github.com/embroider-build/release-plan) has prepared. To release you should just merge this PR 👍
80
+
81
+ -----------------------------------------
82
+
83
+ ${{ steps.explanation.outputs.text }}
@@ -0,0 +1,58 @@
1
+ # For every push to the master branch, this checks if the release-plan was
2
+ # updated and if it was it will publish stable npm packages based on the
3
+ # release plan
4
+
5
+ name: Publish Stable
6
+
7
+ on:
8
+ workflow_dispatch:
9
+ push:
10
+ branches:
11
+ - main
12
+ - master
13
+
14
+ concurrency:
15
+ group: publish-${{ github.head_ref || github.ref }}
16
+ cancel-in-progress: true
17
+
18
+ jobs:
19
+ check-plan:
20
+ name: "Check Release Plan"
21
+ runs-on: ubuntu-latest
22
+ outputs:
23
+ command: ${{ steps.check-release.outputs.command }}
24
+
25
+ steps:
26
+ - uses: actions/checkout@v4
27
+ with:
28
+ fetch-depth: 0
29
+ ref: 'main'
30
+ # This will only cause the `check-plan` job to have a result of `success`
31
+ # when the .release-plan.json file was changed on the last commit. This
32
+ # plus the fact that this action only runs on main will be enough of a guard
33
+ - id: check-release
34
+ run: if git diff --name-only HEAD HEAD~1 | grep -w -q ".release-plan.json"; then echo "command=release"; fi >> $GITHUB_OUTPUT
35
+
36
+ publish:
37
+ name: "NPM Publish"
38
+ runs-on: ubuntu-latest
39
+ needs: check-plan
40
+ if: needs.check-plan.outputs.command == 'release'
41
+
42
+ steps:
43
+ - uses: actions/checkout@v4
44
+ - uses: actions/setup-node@v4
45
+ with:
46
+ node-version: 18
47
+ # This creates an .npmrc that reads the NODE_AUTH_TOKEN environment variable
48
+ registry-url: 'https://registry.npmjs.org'
49
+
50
+ - uses: pnpm/action-setup@v2
51
+ with:
52
+ version: 8
53
+ - run: pnpm install --frozen-lockfile
54
+ - name: npm publish
55
+ run: pnpm release-plan publish --singlePackage=ember-inspector
56
+ env:
57
+ GITHUB_AUTH: ${{ secrets.GITHUB_TOKEN }}
58
+ NODE_AUTH_TOKEN: ${{ secrets.NPM_AUTH_TOKEN }}
@@ -12,6 +12,15 @@ export default class ComponentTreeArg extends Component {
12
12
 
13
13
  get displayValue() {
14
14
  if (this.isObject) {
15
+ if (this.args.value.inspect) {
16
+ if (this.args.value.type === 'function') {
17
+ return this.args.value.inspect
18
+ .replace(/"/g, '\\"')
19
+ .replace('bound ', '')
20
+ .replace('{ ... }', '');
21
+ }
22
+ return truncate(this.args.value.inspect.replace(/"/g, '\\"'));
23
+ }
15
24
  return '...';
16
25
  } else if (typeof this.args.value === 'string') {
17
26
  // Escape any interior quotes – we will add the surrounding quotes in the template
@@ -23,8 +23,10 @@
23
23
 
24
24
  <code
25
25
  class="component-tree-item__tag flex whitespace-no-wrap
26
+ {{if @item.isClosingTag 'component-tree-item__closing'}}
27
+ {{if @item.hasModifiers 'component-tree-item__has_modifier'}}
26
28
  {{if
27
- @item.isComponent
29
+ (or @item.isComponent @item.isModifier @item.isHtmlTag)
28
30
  (if
29
31
  @item.isCurlyInvocation
30
32
  "component-tree-item-classic__bracket"
@@ -37,7 +39,7 @@
37
39
  }}"
38
40
  >
39
41
  {{!-- template-lint-disable no-unbalanced-curlies --}}
40
- {{#if @item.isComponent}}
42
+ {{#if (or @item.isComponent @item.isModifier)}}
41
43
  {{#if @item.isCurlyInvocation}}
42
44
  <span class="component-name">
43
45
  {{@item.name}}
@@ -83,6 +85,20 @@
83
85
  \{{mount "{{@item.name}}"}}
84
86
  {{else if @item.isRouteTemplate}}
85
87
  {{@item.name}} route
88
+ {{else if @item.isHtmlTag}}
89
+ <span class="component-name">
90
+ {{@item.name}}
91
+ </span>
92
+ {{#each-in @item.args.named as |name value|}}
93
+ <div class="arg-token flex ml-2">
94
+ <span class="key-token">
95
+ {{name}}
96
+ </span>
97
+ ={{if (is-string value) "\""}}
98
+ <ComponentTreeArg @value={{value}} />
99
+ {{if (is-string value) "\""}}
100
+ </div>
101
+ {{/each-in}}
86
102
  {{/if}}
87
103
  </code>
88
104
  </div>
@@ -1,14 +1,17 @@
1
1
  <li class="mixin__property-dependency-list relative">
2
2
  {{svg-jar "dependent-key-connection" width="20px" height="10px"}}
3
3
  <ul class="m-0 p-0 list-none">
4
- {{#each @keys as |depKey|}}
5
- <li class="mixin__property-dependency-item relative text-base12 text-sm">
6
- {{#if (match depKey "•")}}
4
+ {{#each @keys as |dep|}}
5
+ <li
6
+ class="mixin__property-dependency-item relative text-base12 text-sm {{if dep.changed 'text-spec01'}}"
7
+ title={{if dep.changed 'this property changed'}}
8
+ >
9
+ {{#if dep.child}}
7
10
  <span
8
11
  class="mixin__property-dependency-name subkey"
9
12
  data-label="object-property-name"
10
13
  >
11
- {{depKey}}
14
+ • -- {{dep.child}}
12
15
  </span>
13
16
  {{else}}
14
17
  {{svg-jar
@@ -20,9 +23,10 @@
20
23
  class="mixin__property-dependency-name"
21
24
  data-label="object-property-name"
22
25
  >
23
- {{depKey}}
26
+ {{dep.name}}
24
27
  </span>
25
28
  {{/if}}
29
+ {{#if dep.changed}}🔸{{/if}}
26
30
  </li>
27
31
  {{/each}}
28
32
  </ul>
@@ -11,6 +11,7 @@
11
11
  @model={{prop}}
12
12
  @saveProperty={{this.saveProperty}}
13
13
  @sendToConsole={{fn this.sendToConsole prop}}
14
+ @gotoSource={{fn this.gotoSource prop}}
14
15
  />
15
16
  {{/each}}
16
17
  </ObjectInspector::SortProperties>
@@ -15,6 +15,16 @@ export default class PropertiesBase extends Component {
15
15
  this.port.send('objectInspector:sendToConsole', data);
16
16
  }
17
17
 
18
+ @action gotoSource({ name }) {
19
+ const data = {
20
+ objectId: this.args.model.objectId,
21
+ };
22
+ if (name !== '...') {
23
+ data.property = name;
24
+ }
25
+ this.port.send('objectInspector:gotoSource', data);
26
+ }
27
+
18
28
  @action digDeeper({ name }) {
19
29
  this.port.send('objectInspector:digDeeper', {
20
30
  objectId: this.args.model.objectId,
@@ -33,6 +33,7 @@
33
33
  @digDeeper={{fn this.digDeeper prop}}
34
34
  @saveProperty={{this.saveProperty}}
35
35
  @sendToConsole={{fn this.sendToConsole prop}}
36
+ @gotoSource={{fn this.gotoSource prop}}
36
37
  />
37
38
  {{else}}
38
39
  <li class="mixin__property flex relative flex-row items-center truncate">No Properties</li>
@@ -119,12 +119,23 @@
119
119
  <button
120
120
  data-test-send-to-console-btn
121
121
  class="mixin__send-btn flex-shrink-0 send-to-console"
122
- title="Send to console"
122
+ title="Send To Console"
123
123
  type="button"
124
124
  {{on "click" @sendToConsole}}
125
125
  >
126
126
  {{svg-jar "send-with-text" width="20px" height="10px"}}
127
127
  </button>
128
+ {{#if this.isFunction}}
129
+ <button
130
+ data-test-goto-source-btn
131
+ class="mixin__send-btn flex-shrink-0 goto-source"
132
+ title="Goto Source"
133
+ type="button"
134
+ {{on "click" @gotoSource}}
135
+ >
136
+ {{svg-jar "code-source" width="20px" height="10px"}}
137
+ </button>
138
+ {{/if}}
128
139
  </li>
129
140
 
130
141
  {{#if this.showDependentKeys}}
@@ -8,6 +8,8 @@ import parseText from 'ember-inspector/utils/parse-text';
8
8
  interface ObjectInspectorPropertyArgs {
9
9
  model: any;
10
10
  digDeeper: () => unknown;
11
+ gotoSource: () => void;
12
+ sendToConsole: () => void;
11
13
  saveProperty: (
12
14
  property: unknown,
13
15
  value: unknown,
@@ -119,8 +121,8 @@ export default class ObjectInspectorProperty extends Component<ObjectInspectorPr
119
121
  }
120
122
 
121
123
  get cannotEdit() {
122
- if (this.args.model.name === '...' || !this.isCalculated) return true;
123
- return this.isFunction || this.isOverridden || this.readOnly;
124
+ if (this.args.model.name === '...' || !this.isCalculated || this.readOnly) return true;
125
+ return this.args.model?.value?.type !== 'type-string' && this.args.model?.value?.type !== 'type-number';
124
126
  }
125
127
 
126
128
  @action
@@ -21,11 +21,25 @@
21
21
  type="button"
22
22
  {{on
23
23
  "click"
24
- (fn this.sendObjectToConsole (get @model (sub @model.length 1)))
24
+ (fn this.sendObjectToConsole this.current)
25
25
  }}
26
26
  >
27
27
  {{svg-jar "send-with-text" width="20px" height="10px"}}
28
28
  </button>
29
+ {{#if this.isClass}}
30
+ <button
31
+ data-test-goto-class-source-btn
32
+ class="goto-source"
33
+ title="Goto Source"
34
+ type="button"
35
+ {{on
36
+ "click"
37
+ (fn this.gotoSource this.current)
38
+ }}
39
+ >
40
+ {{svg-jar "code-source" width="20px" height="10px"}}
41
+ </button>
42
+ {{/if}}
29
43
  </div>
30
44
 
31
45
  {{#if this.trail}}
@@ -103,4 +117,4 @@
103
117
  No object selected
104
118
  </Ui::EmptyMessage>
105
119
  </div>
106
- {{/if}}
120
+ {{/if}}
@@ -14,6 +14,13 @@ export default class ObjectInspector extends Component {
14
14
  this.searchInputId = 'custom-filter-input';
15
15
  }
16
16
 
17
+ get isClass() {
18
+ return this.current.mixins.length > 1;
19
+ }
20
+
21
+ get current() {
22
+ return this.args.model[this.args.model.length - 1];
23
+ }
17
24
  get trail() {
18
25
  let nested = this.args.model.slice(1);
19
26
  if (nested.length === 0) {
@@ -55,6 +62,13 @@ export default class ObjectInspector extends Component {
55
62
  });
56
63
  }
57
64
 
65
+ @action gotoSource(obj) {
66
+ let objectId = obj.objectId;
67
+ this.port.send('objectInspector:gotoSource', {
68
+ objectId,
69
+ });
70
+ }
71
+
58
72
  @action popStack() {
59
73
  if (this.isNested) {
60
74
  this.args.popMixinDetails();
@@ -48,6 +48,21 @@ export default class ComponentTreeController extends Controller {
48
48
 
49
49
  renderItems.push(item);
50
50
 
51
+ if (
52
+ item.isHtmlTag &&
53
+ renderNode.children.some((c) => c.type === 'modifier')
54
+ ) {
55
+ const idx = renderNode.children.findLastIndex(
56
+ (c) => c.type === 'modifier'
57
+ );
58
+ renderNode.children.splice(idx + 1, 0, {
59
+ type: 'placeholder-closing-tag',
60
+ id: renderNode.id + '-closing-tag',
61
+ name: '',
62
+ children: [],
63
+ });
64
+ }
65
+
51
66
  renderNode.children.forEach((node) => flatten(item, node));
52
67
  }
53
68
  };
@@ -301,7 +316,32 @@ class RenderItem {
301
316
  }
302
317
 
303
318
  get isComponent() {
304
- return this.renderNode.type === 'component';
319
+ return (
320
+ this.renderNode.type === 'component' ||
321
+ this.renderNode.type === 'remote-element'
322
+ );
323
+ }
324
+
325
+ get isModifier() {
326
+ return this.renderNode.type === 'modifier';
327
+ }
328
+
329
+ get hasModifiers() {
330
+ return this.childItems.some((item) => item.isModifier);
331
+ }
332
+
333
+ get isLastModifier() {
334
+ return (
335
+ this.parentItem.childItems.findLast((item) => item.isModifier) === this
336
+ );
337
+ }
338
+
339
+ get isHtmlTag() {
340
+ return this.renderNode.type === 'html-element';
341
+ }
342
+
343
+ get isClosingTag() {
344
+ return this.renderNode.type === 'placeholder-closing-tag';
305
345
  }
306
346
 
307
347
  get name() {
@@ -313,12 +353,15 @@ class RenderItem {
313
353
  }
314
354
 
315
355
  get isCurlyInvocation() {
356
+ if (this.isModifier) {
357
+ return true;
358
+ }
316
359
  return this.renderNode.args && this.renderNode.args.positional;
317
360
  }
318
361
 
319
362
  get hasInstance() {
320
363
  let { instance } = this.renderNode;
321
- return typeof instance === 'object' && instance !== null;
364
+ return typeof instance === 'object' && instance;
322
365
  }
323
366
 
324
367
  get instance() {
@@ -330,7 +373,7 @@ class RenderItem {
330
373
  }
331
374
 
332
375
  get hasBounds() {
333
- return this.renderNode.bounds !== null;
376
+ return this.renderNode.bounds;
334
377
  }
335
378
 
336
379
  get isRoot() {
@@ -400,6 +443,7 @@ class RenderItem {
400
443
  }
401
444
 
402
445
  @action showPreview() {
446
+ if (this.isClosingTag) return;
403
447
  this.controller.previewing = this.id;
404
448
  }
405
449
 
@@ -410,6 +454,7 @@ class RenderItem {
410
454
  }
411
455
 
412
456
  @action toggleInspection() {
457
+ if (this.isClosingTag) return;
413
458
  if (this.isPinned) {
414
459
  this.controller.pinned = undefined;
415
460
  } else {
@@ -439,6 +484,12 @@ class RenderItem {
439
484
  this.send('view:inspectElement', { id: this.id });
440
485
  }
441
486
 
487
+ @action inspectValue(event) {
488
+ event.stopPropagation();
489
+
490
+ this.send('view:inspectValue', { id: this.id });
491
+ }
492
+
442
493
  show() {
443
494
  let item = this.parentItem;
444
495
 
@@ -31,7 +31,6 @@ export default class ComponentTreeRoute extends TabRoute {
31
31
  this.port.on('view:cancelSelection', this, this.cancelSelection);
32
32
  this.port.on('view:startInspecting', this, this.startInspecting);
33
33
  this.port.on('view:stopInspecting', this, this.stopInspecting);
34
- this.port.on('view:inspectDOMNode', this, this.inspectDOMNode);
35
34
  }
36
35
 
37
36
  deactivate() {
@@ -41,7 +40,6 @@ export default class ComponentTreeRoute extends TabRoute {
41
40
  this.port.off('view:cancelSelection', this, this.cancelSelection);
42
41
  this.port.off('view:startInspecting', this, this.startInspecting);
43
42
  this.port.off('view:stopInspecting', this, this.stopInspecting);
44
- this.port.off('view:inspectDOMNode', this, this.inspectDOMNode);
45
43
  }
46
44
 
47
45
  setRenderTree({ tree }) {
@@ -59,8 +57,4 @@ export default class ComponentTreeRoute extends TabRoute {
59
57
  stopInspecting() {
60
58
  this.controller.isInspecting = false;
61
59
  }
62
-
63
- inspectDOMNode({ name }) {
64
- this.port.adapter.inspectDOMNode(name);
65
- }
66
60
  }
@@ -107,12 +107,12 @@ export default class WebExtension extends BasicAdapter {
107
107
  }
108
108
 
109
109
  /**
110
- * Open the devtools "Elements" tab and select a specific DOM node.
110
+ * Open the devtools "Elements" or "Sources" tab and select a specific DOM node or function.
111
111
  *
112
- * @method inspectDOMNode
112
+ * @method inspectJSValue
113
113
  * @param {String} name
114
114
  */
115
- inspectDOMNode(name) {
115
+ inspectJSValue(name) {
116
116
  chrome.devtools.inspectedWindow.eval(`
117
117
  inspect(window[${JSON.stringify(name)}]);
118
118
  delete window[${JSON.stringify(name)}];
@@ -49,6 +49,10 @@ export default class PortService extends Service.extend(Evented) {
49
49
  this.trigger(message.type, message, applicationId);
50
50
  }
51
51
  });
52
+
53
+ this.on('view:inspectJSValue', this, ({ name }) =>
54
+ this.adapter.inspectJSValue(name)
55
+ );
52
56
  }
53
57
 
54
58
  selectApplication(applicationId) {
@@ -141,6 +141,19 @@
141
141
  color: var(--base09);
142
142
  }
143
143
 
144
+ .component-tree-item__has_modifier:after {
145
+ content: '' !important;
146
+ }
147
+
148
+ .component-tree-item__closing:before {
149
+ content: '>';
150
+ margin-left: -13px;
151
+ }
152
+
153
+ .component-tree-item__self-closing:before {
154
+ content: '/>';
155
+ }
156
+
144
157
  .component-tree-item__bracket:before {
145
158
  content: '<';
146
159
  }
@@ -18,3 +18,4 @@ export default function parseText(value: string): string {
18
18
  }
19
19
  return parsedValue;
20
20
  }
21
+