-
Notifications
You must be signed in to change notification settings - Fork 186
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Prop Descriptions #52
Open
hipstersmoothie
wants to merge
14
commits into
seek-oss:master
Choose a base branch
from
hipstersmoothie:descriptions
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+193
−12
Open
Changes from 7 commits
Commits
Show all changes
14 commits
Select commit
Hold shift + click to select a range
955c6c4
init
hipstersmoothie cb180f9
required types
hipstersmoothie 3b65d4f
default + type
hipstersmoothie ecac118
add some pizzaz
hipstersmoothie 8d12c3f
lint
hipstersmoothie e7dc3d8
fix it after linting
hipstersmoothie d565727
Merge branch 'master' into descriptions
hipstersmoothie b2e275b
get rid of the copy pasta :tada:
hipstersmoothie c97b223
use lit-html for rendering the tooltip
hipstersmoothie 34b1732
add example
hipstersmoothie 5951248
fix lint + test
hipstersmoothie f5a4186
just use react!
hipstersmoothie d48b2e1
code improvements
hipstersmoothie 013fd6b
Merge branch 'master' into descriptions
markdalgleish File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,306 @@ | ||
/* eslint-disable new-cap */ | ||
|
||
import styles from './CodeMirror-JSX.less'; | ||
|
||
function matches(hint, typed, matchInMiddle) { | ||
if (matchInMiddle) { | ||
return hint.indexOf(typed) >= 0; | ||
} | ||
|
||
return hint.lastIndexOf(typed, 0) === 0; | ||
} | ||
|
||
function elt(tagname, cls) { | ||
const e = document.createElement(tagname); | ||
|
||
if (cls) { | ||
e.className = cls; | ||
} | ||
|
||
for (let i = 2; i < arguments.length; ++i) { | ||
let element = arguments[i]; | ||
|
||
if (typeof element === 'string') { | ||
element = document.createTextNode(element); | ||
} | ||
|
||
e.appendChild(element); | ||
} | ||
|
||
return e; | ||
} | ||
|
||
function makeTooltip(x, y, data) { | ||
const content = [elt('span', null, data.description)]; | ||
|
||
if (data.required) { | ||
content.unshift(elt('span', styles.required, 'ⓘ')); | ||
} | ||
|
||
if (data.default !== null) { | ||
const value = elt('span', null, data.default); | ||
|
||
if (data.type === 'boolean') { | ||
value.style.color = 'rebeccapurple'; | ||
} | ||
|
||
if (data.type === 'string' || data.values.length > 0) { | ||
value.style.color = 'darkred'; | ||
} | ||
|
||
if (data.type === 'number') { | ||
value.style.color = 'steelblue'; | ||
} | ||
|
||
content.push( | ||
elt( | ||
'div', | ||
styles.default, | ||
elt('span', styles.defaultLabel, 'Default:'), | ||
value | ||
) | ||
); | ||
} | ||
|
||
if (data.type !== null) { | ||
content.push( | ||
elt( | ||
'div', | ||
styles.default, | ||
elt('span', styles.defaultLabel, 'Type:'), | ||
elt('span', null, data.type) | ||
) | ||
); | ||
} | ||
|
||
const node = elt('div', styles.tooltip, ...content); | ||
|
||
node.style.left = `${x}px`; | ||
node.style.top = `${y}px`; | ||
|
||
document.body.appendChild(node); | ||
return node; | ||
} | ||
|
||
function remove(node) { | ||
const p = node && node.parentNode; | ||
|
||
if (p) { | ||
p.removeChild(node); | ||
} | ||
} | ||
|
||
export default function getHints(cm, options) { | ||
const CodeMirror = cm.constructor; | ||
|
||
const tags = options && options.schemaInfo; | ||
const matchInMiddle = options && options.matchInMiddle; | ||
let quote = (options && options.quoteChar) || '"'; | ||
|
||
if (!tags) { | ||
return; | ||
} | ||
|
||
const cur = cm.getCursor(), | ||
token = cm.getTokenAt(cur); | ||
|
||
if (token.end > cur.ch) { | ||
token.end = cur.ch; | ||
token.string = token.string.slice(0, cur.ch - token.start); | ||
} | ||
|
||
const inner = CodeMirror.innerMode(cm.getMode(), token.state); | ||
|
||
if (inner.mode.name !== 'xml') { | ||
return; | ||
} | ||
|
||
const result = []; | ||
const tag = /\btag\b/.test(token.type) && !/>$/.test(token.string); | ||
const tagName = tag && /^\w/.test(token.string); | ||
|
||
let tagStart, | ||
tagType, | ||
replaceToken = false, | ||
prefix; | ||
|
||
if (tagName) { | ||
const before = cm | ||
.getLine(cur.line) | ||
.slice(Math.max(0, token.start - 2), token.start); | ||
tagType = | ||
(/<\/$/.test(before) && 'close') || (/<$/.test(before) && 'open') || null; | ||
|
||
if (tagType) { | ||
tagStart = token.start - (tagType === 'close' ? 2 : 1); | ||
} | ||
} else if (tag && token.string === '<') { | ||
tagType = 'open'; | ||
} else if (tag && token.string === '</') { | ||
tagType = 'close'; | ||
} | ||
|
||
if ((!tag && !inner.state.tagName) || tagType) { | ||
if (tagName) { | ||
prefix = token.string; | ||
} | ||
replaceToken = tagType; | ||
const cx = inner.state.context; | ||
const curTag = cx && tags[cx.tagName]; | ||
const childList = cx ? curTag && curTag.children : tags['!top']; | ||
|
||
if (childList && tagType !== 'close') { | ||
for (let i = 0; i < childList.length; ++i) { | ||
if (!prefix || matches(childList[i], prefix, matchInMiddle)) { | ||
result.push(`<${childList[i]}`); | ||
} | ||
} | ||
} else if (tagType !== 'close') { | ||
// Component Identifier names | ||
for (const name in tags) { | ||
if ( | ||
tags.hasOwnProperty(name) && | ||
name !== '!top' && | ||
name !== '!attrs' && | ||
(!prefix || matches(name, prefix, matchInMiddle)) | ||
) { | ||
result.push({ | ||
text: `<${name}`, | ||
description: tags[name].attrs.component_description | ||
}); | ||
} | ||
} | ||
} | ||
if ( | ||
cx && | ||
(!prefix || | ||
(tagType === 'close' && matches(cx.tagName, prefix, matchInMiddle))) | ||
) { | ||
result.push(`</${cx.tagName}>`); | ||
} | ||
} else { | ||
// Attribute completion | ||
const curTag = tags[inner.state.tagName]; | ||
let attrs = curTag && curTag.attrs; | ||
const globalAttrs = tags['!attrs']; | ||
if (!attrs && !globalAttrs) { | ||
return; | ||
} | ||
if (!attrs) { | ||
attrs = globalAttrs; | ||
} else if (globalAttrs) { | ||
// Combine tag-local and global attributes | ||
const set = {}; | ||
for (const nm in globalAttrs) { | ||
if (globalAttrs.hasOwnProperty(nm)) { | ||
set[nm] = globalAttrs[nm]; | ||
} | ||
} | ||
for (const nm in attrs) { | ||
if (attrs.hasOwnProperty(nm)) { | ||
set[nm] = attrs[nm]; | ||
} | ||
} | ||
attrs = set; | ||
} | ||
if (token.type === 'string' || token.string === '=') { | ||
// A value | ||
const before = cm.getRange( | ||
CodeMirror.Pos(cur.line, Math.max(0, cur.ch - 60)), | ||
CodeMirror.Pos( | ||
cur.line, | ||
token.type === 'string' ? token.start : token.end | ||
) | ||
); | ||
const atName = before.match(/([^\s\u00a0=<>\"\']+)=$/); | ||
let atValues; | ||
if ( | ||
!atName || | ||
!attrs.hasOwnProperty(atName[1]) || | ||
!(atValues = Array.isArray(attrs[atName[1]]) | ||
? attrs[atName[1]] | ||
: attrs[atName[1]].values) | ||
) { | ||
return; | ||
} | ||
if (typeof atValues === 'function') { | ||
atValues = atValues.call(this, cm); | ||
} // Functions can be used to supply values for autocomplete widget | ||
if (token.type === 'string') { | ||
prefix = token.string; | ||
let n = 0; | ||
if (/['"]/.test(token.string.charAt(0))) { | ||
quote = token.string.charAt(0); | ||
prefix = token.string.slice(1); | ||
n++; | ||
} | ||
const len = token.string.length; | ||
if (/['"]/.test(token.string.charAt(len - 1))) { | ||
quote = token.string.charAt(len - 1); | ||
prefix = token.string.substr(n, len - 2); | ||
} | ||
if (n) { | ||
// an opening quote | ||
const line = cm.getLine(cur.line); | ||
if (line.length > token.end && line.charAt(token.end) === quote) { | ||
token.end++; | ||
} // include a closing quote | ||
} | ||
replaceToken = true; | ||
} | ||
for (let i = 0; i < atValues.length; ++i) { | ||
if (!prefix || matches(atValues[i], prefix, matchInMiddle)) { | ||
result.push(quote + atValues[i] + quote); | ||
} | ||
} | ||
} else { | ||
// An attribute name | ||
if (token.type === 'attribute') { | ||
prefix = token.string; | ||
replaceToken = true; | ||
} | ||
for (const attr in attrs) { | ||
if ( | ||
attrs.hasOwnProperty(attr) && | ||
attr !== 'component_description' && | ||
(!prefix || matches(attr, prefix, matchInMiddle)) | ||
) { | ||
result.push({ text: attr, ...attrs[attr] }); | ||
} | ||
} | ||
} | ||
} | ||
|
||
const obj = { | ||
list: result, | ||
from: replaceToken | ||
? CodeMirror.Pos( | ||
cur.line, | ||
tagStart === null || typeof tagStart === 'undefined' | ||
? token.start | ||
: tagStart | ||
) | ||
: cur, | ||
to: replaceToken ? CodeMirror.Pos(cur.line, token.end) : cur | ||
}; | ||
|
||
let tooltip = null; | ||
|
||
CodeMirror.on(obj, 'close', () => remove(tooltip)); | ||
CodeMirror.on(obj, 'update', () => remove(tooltip)); | ||
CodeMirror.on(obj, 'select', (data, node) => { | ||
remove(tooltip); | ||
|
||
if (data && data.description) { | ||
tooltip = makeTooltip( | ||
node.parentNode.getBoundingClientRect().right + window.pageXOffset, | ||
node.getBoundingClientRect().top + window.pageYOffset, | ||
data | ||
); | ||
tooltip.className += ' hint-doc'; | ||
} | ||
}); | ||
|
||
// eslint-disable-next-line consistent-return | ||
return obj; | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
.tooltip { | ||
position: absolute; | ||
background: white; | ||
border-radius: 3px; | ||
font-family: monospace; | ||
white-space: pre-wrap; | ||
padding: 4px 8px; | ||
z-index: 10; | ||
box-shadow: 2px 3px 5px rgba(0, 0, 0, 0.2); | ||
border: 1px solid silver; | ||
max-width: 25em; | ||
margin-left: 5px; | ||
} | ||
|
||
.required { | ||
color: red; | ||
padding-right: 5px; | ||
} | ||
|
||
.default { | ||
margin-top: 10px; | ||
} | ||
|
||
.defaultLabel { | ||
margin-right: 8px; | ||
font-weight: 500; | ||
color: rgba(0, 0, 0, 0.7); | ||
} |
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
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this file borrowed from somewhere else? Seems like a copy-and-paste.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It was the addon-xml 😅 I went back for a second look and was able to use that code once it was registered to codemirror and just handle the tooltip stuff myself.
I switched to rendering the tooltip with lit-html. I can remove that and switch back to document methods if you want, but I think the code is a little clearer this way.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually I realized i could just use react and it become much clearer 👍