Last active
August 13, 2020 21:57
-
-
Save krukid/3a3ac1887a8534fc4d7be9455f0281ab to your computer and use it in GitHub Desktop.
mint-object-explorer
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Component from '@glimmer/component'; | |
import { tracked } from '@glimmer/tracking'; | |
function matchString(source, pattern, specifier) { | |
const match = pattern.match(/^(?:(\w+)=)?(")?([^"]+)\2$/); | |
if (match) { | |
const [, prefix, quote, text] = match; | |
const isPresent = text.trim(); | |
const isRelevant = prefix === undefined || prefix === specifier; | |
const isWildcard = text === '*'; | |
const isExact = quote !== undefined; | |
return isRelevant && isPresent && ( | |
isWildcard || ( | |
isExact | |
? source === text | |
: source.includes(text) | |
) | |
); | |
} | |
return false; | |
} | |
function matchNodeKey(node, filter) { | |
return matchString(node.key, filter, 'key'); | |
} | |
function matchNodeValue(node, filter) { | |
return matchString(String(node.value), filter, 'value'); | |
} | |
function nodeify(key, object) { | |
const type = Object.prototype.toString.apply(object).slice(8, -1); | |
return { | |
key, | |
type, | |
value: object, | |
isObject: type === 'Object', | |
isArray: type === 'Array', | |
isContainer: ['Object', 'Array'].includes(type), | |
}; | |
} | |
function recursivelyNodeify(key, object, filter, strict) { | |
const node = nodeify(key, object); | |
// determine match by key | |
node.matchKey = matchNodeKey(node, filter); | |
// nodeify container children | |
if (node.isObject) { | |
node.children = Object.entries(object).map(([childKey, childObject]) => recursivelyNodeify(childKey, childObject, filter, strict)); | |
} | |
else if (node.isArray) { | |
node.children = object.map((childObject, childKey) => recursivelyNodeify(String(childKey), childObject, filter, strict)); | |
} | |
// filter container children if strict | |
if (node.isContainer && strict) { | |
node.children = node.children.filter(childNode => node.matchKey || childNode.matchKey || childNode.matchValue); | |
} | |
// determine match by value | |
if (node.isContainer) { | |
node.matchValue = node.children.findIndex(childNode => childNode.matchKey || childNode.matchValue) >= 0; | |
} | |
else { | |
node.matchValue = matchNodeValue(node, filter); | |
} | |
return node; | |
} | |
export default class extends Component { | |
@tracked | |
filter = ''; | |
@tracked | |
isStrictFilter = false; | |
get tree() { | |
const tree = recursivelyNodeify('root', this.args.object, this.filter, this.isStrictFilter); | |
console.debug(tree); | |
return tree; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Component from '@glimmer/component'; | |
import { tracked } from '@glimmer/tracking'; | |
import { action } from '@ember/object'; | |
export default class extends Component { | |
json = ''; | |
@tracked | |
error = true; | |
@action | |
change(event) { | |
let object; | |
try { | |
object = JSON.parse(event.target.value); | |
this.error = null; | |
} | |
catch (e) { | |
console.debug(e); | |
this.error = e; | |
} | |
this.args.onParsed(object); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Component from '@glimmer/component'; | |
import { tracked } from '@glimmer/tracking'; | |
import { action } from '@ember/object'; | |
export default class extends Component { | |
@tracked | |
isPreferExpanded = false; | |
get isExpanded() { | |
return this.isPreferExpanded || !this.args.node.isContainer || this.args.node.matchValue || this.args.node.matchKey; | |
} | |
get isHighlighted() { | |
return this.args.node.matchValue || this.args.node.matchKey; | |
} | |
get keyClassName() { | |
return this.isPreferExpanded && this.args.node.isContainer | |
? 'mint-object__key--expanded' | |
: 'mint-object__key--elastic'; | |
} | |
get valueClassName() { | |
switch (this.args.node.type) { | |
case 'Number': return 'mint-object__value--number'; | |
case 'String': return 'mint-object__value--string'; | |
case 'Boolean': return 'mint-object__value--boolean'; | |
case 'Object': return 'mint-object__value--object'; | |
} | |
} | |
get rootClassName() { | |
return [ | |
this.isExpanded | |
? 'mint-object--expanded' | |
: 'mint-object--collapsed', | |
this.isHighlighted | |
? 'mint-object--pronounced' | |
: 'mint-object--dimmed' | |
].join(' '); | |
} | |
get value() { | |
return String(this.args.node.value); | |
} | |
@action | |
expand() { | |
this.isPreferExpanded = !this.isPreferExpanded; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Controller from '@ember/controller'; | |
import { tracked } from '@glimmer/tracking'; | |
import { action } from '@ember/object'; | |
const DEMO_OBJECT = { | |
a: { | |
b: 'foo', | |
c: 1, | |
d: {}, | |
e: { | |
w: 'qux wii', | |
}, | |
}, | |
i: -5.1, | |
b: false, | |
s: 'bar', | |
}; | |
export default class ApplicationController extends Controller { | |
appName = 'mint-object-explorer'; | |
@tracked | |
customObject; | |
get object() { | |
return this.customObject === undefined | |
? DEMO_OBJECT | |
: this.customObject; | |
} | |
@action | |
objectParsed(object) { | |
this.customObject = object; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
potentially useful features/ tweaks: | |
1. persistent node toggle across searches | |
2. node toggles expand AND highlight (alt color?) | |
3. opacity darken bg for nested containers | |
4. search expressions (key="foo" value=2 AND value=5) | |
// key is exactly "foo" OR value contains both 2 and 5 | |
// eg: `a.foo.b=352` matches a.foo (by key) and a.foo.b (by value) | |
5. extended expressions (key>5 [numeric] value<="qwe" [lexicographic]) | |
// consider /, /= OR ->, => for lex >, >= | |
// \, \= OR <-, <= for lex <, <= | |
// key<=qwe value>5 | |
6. prefixed list display instead of tree (filter leaf nodes) | |
// a.b.c: 5 | |
// x.y: qwd | |
7. key path matching | |
// key=a > value=b > key="c" === match nodes with key containing "a" that have children with value containing "b", if those children have key "c" | |
// path=a.b.c === key=a > key=b > key=c | |
// path="a.b.c" === key="a" > key="b" > key="c" | |
?. css-like expressions VS search-like expressions? |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
body { | |
margin: 12px 16px; | |
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; | |
font-size: 12pt; | |
} | |
.mint-object { | |
} | |
.mint-object--dimmed { | |
color: silver; | |
} | |
.mint-object--pronounced { | |
color: black; | |
} | |
.mint-object__key { | |
font-weight: 700; | |
} | |
.mint-object__key--elastic { | |
} | |
.mint-object__key--expanded { | |
color: darkmagenta; | |
} | |
.mint-object__key[role=button]:hover { | |
text-decoration: underline; | |
color: magenta; | |
} | |
.mint-object__value { | |
padding-left: 15px; | |
} | |
.mint-object__value--object { | |
border-left: dashed 1px silver; | |
} | |
.mint-object--pronounced > .mint-object__value--string { | |
color: orange; | |
} | |
.mint-object--pronounced > .mint-object__value--boolean { | |
color: black; | |
} | |
.mint-object--pronounced > .mint-object__value--number { | |
color: blue; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"version": "0.17.1", | |
"EmberENV": { | |
"FEATURES": {}, | |
"_TEMPLATE_ONLY_GLIMMER_COMPONENTS": false, | |
"_APPLICATION_TEMPLATE_WRAPPER": true, | |
"_JQUERY_INTEGRATION": true | |
}, | |
"options": { | |
"use_pods": false, | |
"enable-testing": false | |
}, | |
"dependencies": { | |
"jquery": "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.js", | |
"ember": "3.18.1", | |
"ember-template-compiler": "3.18.1", | |
"ember-testing": "3.18.1" | |
}, | |
"addons": { | |
"@glimmer/component": "1.0.0" | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
https://ember-twiddle.com/3a3ac1887a8534fc4d7be9455f0281ab