Skip to content

Instantly share code, notes, and snippets.

@bendyorke
Last active April 10, 2020 12:14
Show Gist options
  • Save bendyorke/b4df862c3b55c79ffd48d7facfaf22e6 to your computer and use it in GitHub Desktop.
Save bendyorke/b4df862c3b55c79ffd48d7facfaf22e6 to your computer and use it in GitHub Desktop.
Sourcegraph Library Discussion
- find the column and line number related to where the cursor is
- find the token underneath the cursor using some sort language parsing
- leverage the syntax highlighting to determine tokens (individual HTML Elements)
- this would help with the onTokenEnter and onTokenLeave priciples
- make API call to get the hover contents back from the api
- so long as the cursor stays over the current token, show a loading indicator
- it can't jusst on cursor move, onTokenEnter
- onTokenLeave stop the request/ignore the request
- once you get the content back, replace the loading indicator with the content
- you could cache the content in case the user hovers back over the same token in a given session
- need some sort of token identifier
- still make an API request to show updates, but could optimistically show potentially stale data
# API
- createHoverableElement(token: HTMLElement) {
- add an onMouseEnter to start fetching data
- add an onMouseLeave to destroy the data
!- create and register an internal ID / convert the HTML element into a specific selector
!- used for the client side 'caching'
}
- convertTokensToHoverableElements(root: HTMLElement, filter: (HTMLElemetn) => boolean) {
- inspect a block of HTML and turn all poential tokens into hoverable elements
- find all tokens, convert to hoverableElements
}
- createRow(row: HTMLElement, {
rowIdentifier: 'data-row'
})
- createFile({
rowIdentifier/rowMarkup: 'data-row',
tokenidentifier: 'data-token',
})
## Example 1
createFile()
## Example 2
$('.gh-row').each(() => createRow())
$('.gh-arg, .gh-var, .gh-etc').each(() => createHoverableElement())
## Options
- require the library author to include markup indicating different rows
- call `createRow` on an HTMLElement and internally add the markup required for a row
- create an internal reference to a specific HTMLEmenet and compare with JS as you walk up a tre

General Flow

  • Identify file, tokens, and rows:
    • File:
      • HTMLElement with which to count rows relative to
    • Rows:
      • Count row relative to File and store as configurable html property
      • Set data attribute to save row number for quick reference and access
        • i.e. "data-row=1"
    • Tokens:
      • Bind event handlers to individual token elements:
        • onTokenEnter for when the cursor enters a token's HTMLElement
        • onTokenLeave for when the cursor leaves a token's HTMLElement
      • Count col start relative to Row and store as configurable html property
        • can use .innerText to count character positions
        • i.e. "data-col=0"
  • onTokenEnter:
    • Set off timer to debounce requests:
      • Don't want to fire off a bunch of api calls as the users moves the cursour around the screen
    • Calculate row and col:
      • get colStart and colEnd from token data-col attribute
        • colEnd can be calculated from colStart and innerText length
      • get row from closest parental row's data-row attribute
    • if col & row are found
      • Render a tooltip element:
        • Relative to the token element itself
      • Show tooltip loadings state:
        • If there is no existing data for the token, show just a loading indicator
        • If there is existing data for the token, show the previous data and a loading indicator
      • Request tooltip content from API
        • On success, save tooltip content to element scope in memory
        • On success, render tooltip content
        • On failure, show error message in tooltip

API

interface AdditionalMarkupDescriptors {
  fileTag?: string
  rowTag?: string
  tokenTag?: string
}

autocreateFiles({
  fileTag = 'file',
  rowTag = 'row',
  tokenTag = 'token',
} = AdditionalMarkupDescriptors): void

createFile(file: HTMLElement, {
  fileTag = 'file',
  rowTag = 'row',
  tokenTag = 'token',
} = AdditionalMarkupDescriptors): void

createRow(row: HTMLElement, {
  rowTag = 'row',
} = AdditionalMarkupDescriptors): void

createToken(row: HTMLElement, {
  tokenTag = 'token',
} = AdditionalMarkupDescriptors): void

Examples

Simplest example, using standard data markings:

<div data-file>
  <div data-row="1">
    <span data-col-start="1">console</span>
    <span data-col-start="8">.</span>
    <span data-col-start="9">log</span>
    <span data-col-start="12">(</span>
    <span data-col-start="13">"Hello World"</span>
    <span data-col-start="26">)</span>
  </div>
</div>
import {createFile} from 'hoverable-tooltips'

autocreateFiles({})

Custom example, using existing un-marked code with custom attributes

<file>
  <row>
    <module>console</module>
    <accessor>.</accessor>
    <attribute>log</attribute>
    <invoke>(</invoke>
    <string>"Hello World"</string>
    <invoke>)</invoke>
  </row>
</file>
import {createFile, createRow, createToken} from 'hoverable-tooltips'

const files = document.querySelectorAll('file')
files.forEach((file) => createFile(file, { fileTag: 'my-file' })

const rows = document.querySelectorAll('row')
rows.forEach((row) => createRow(row, { rowTag: 'my-row' })

const tokens = document.querySelectorAll('module, accessor, attribute, invoke, string')
tokens.forEach((token) => createToken(token, { tokenTag: 'my-token' })
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment