diff --git a/components/http/http-raw-body.vue b/components/http/http-raw-body.vue
index c2d009743..0df3ed5ef 100644
--- a/components/http/http-raw-body.vue
+++ b/components/http/http-raw-body.vue
@@ -29,18 +29,20 @@
-
+
diff --git a/components/lenses/renderers/JSONLensRenderer.vue b/components/lenses/renderers/JSONLensRenderer.vue
index 8273d3c42..18c0fcb9f 100644
--- a/components/lenses/renderers/JSONLensRenderer.vue
+++ b/components/lenses/renderers/JSONLensRenderer.vue
@@ -43,6 +43,7 @@
+
+
+
+ {{ p }}
+
+
chevron_right
+
+
+ {{ sib.key ? sib.key.value : i }}
+
+
+
+
@@ -16,6 +34,61 @@
@apply transition-none;
}
}
+
+.outline {
+ @apply flex;
+ @apply flex-no-wrap;
+ @apply w-full;
+ @apply overflow-auto;
+ @apply font-mono;
+ @apply shadow-lg;
+ @apply px-4;
+
+ .block {
+ @apply inline-flex;
+ @apply items-center;
+ @apply flex-grow-0;
+ @apply flex-shrink-0;
+ @apply text-fgLightColor;
+ @apply text-sm;
+
+ &:hover {
+ @apply text-fgColor;
+ @apply cursor-pointer;
+ }
+
+ .label {
+ @apply p-2;
+ @apply transition;
+ @apply ease-in-out;
+ @apply duration-150;
+ }
+
+ .siblings {
+ @apply absolute;
+ @apply z-50;
+ @apply top-9;
+ @apply bg-bgColor;
+ @apply max-h-60;
+ @apply overflow-auto;
+ @apply shadow-lg;
+ @apply text-fgLightColor;
+ @apply overscroll-none;
+
+ border-radius: 0 0 8px 8px;
+ }
+
+ .sib {
+ @apply px-4;
+ @apply py-1;
+
+ &:hover {
+ @apply text-fgColor;
+ @apply bg-bgLightColor;
+ }
+ }
+ }
+}
diff --git a/helpers/outline.js b/helpers/outline.js
new file mode 100644
index 000000000..3ea2ef91e
--- /dev/null
+++ b/helpers/outline.js
@@ -0,0 +1,126 @@
+import jsonParse from "./jsonParse"
+
+export default () => {
+ let jsonAST = {}
+ let path = []
+
+ const init = (jsonStr) => {
+ jsonAST = jsonParse(jsonStr)
+ linkParents(jsonAST)
+ }
+
+ const setNewText = (jsonStr) => {
+ init(jsonStr)
+ path = []
+ }
+
+ const linkParents = (node) => {
+ if (node.kind == "Object") {
+ if (node.members) {
+ node.members.forEach((m) => {
+ m.parent = node
+ linkParents(m)
+ })
+ }
+ } else if (node.kind == "Array") {
+ if (node.values) {
+ node.values.forEach((v) => {
+ v.parent = node
+ linkParents(v)
+ })
+ }
+ } else if (node.kind == "Member") {
+ if (node.value) {
+ node.value.parent = node
+ linkParents(node.value)
+ }
+ }
+ }
+
+ const genPath = (index) => {
+ let output = {}
+ path = []
+ let current = jsonAST
+ if (current.kind == "Object") {
+ path.push({ label: "{}", obj: "root" })
+ } else if (current.kind == "Array") {
+ path.push({ label: "[]", obj: "root" })
+ }
+ let over = false
+
+ try {
+ while (!over) {
+ if (current.kind == "Object") {
+ let i = 0
+ let found = false
+ while (i < current.members.length) {
+ let m = current.members[i]
+ if (m.start <= index && m.end >= index) {
+ path.push({ label: m.key.value, obj: m })
+ current = current.members[i]
+ found = true
+ break
+ }
+ i++
+ }
+ if (!found) over = true
+ } else if (current.kind == "Array") {
+ if (current.values) {
+ let i = 0
+ let found = false
+ while (i < current.values.length) {
+ let m = current.values[i]
+ if (m.start <= index && m.end >= index) {
+ path.push({ label: `[${i.toString()}]`, obj: m })
+ current = current.values[i]
+ found = true
+ break
+ }
+ i++
+ }
+ if (!found) over = true
+ } else over = true
+ } else if (current.kind == "Member") {
+ if (current.value) {
+ if (current.value.start <= index && current.value.end >= index) {
+ current = current.value
+ } else over = true
+ } else over = true
+ } else if (
+ current.kind == "String" ||
+ current.kind == "Number" ||
+ current.kind == "Boolean" ||
+ current.kind == "Null"
+ ) {
+ if (current.start <= index && current.end >= index) {
+ path.push({ label: `${current.value}`, obj: current })
+ }
+ over = true
+ }
+ }
+ output = { success: true, res: path.map((p) => p.label) }
+ } catch (e) {
+ output = { success: false, res: e }
+ }
+ return output
+ }
+
+ const getSiblings = (index) => {
+ let parent = path[index].obj.parent
+ if (!parent) return []
+ else {
+ if (parent.kind == "Object") {
+ return parent.members
+ } else if (parent.kind == "Array") {
+ return parent.values
+ } else return []
+ }
+ }
+
+ return {
+ init,
+ genPath,
+ getSiblings,
+ setNewText,
+ }
+}