Public
Edited
Dec 20, 2022
1 fork
Importers
1 star
Insert cell
Insert cell
Insert cell
adventOfCodeHeader(2022)
Insert cell
Insert cell
viewof input = renderInput(`asdf\n123 456\n1\n2\n3\n4\n5\n6\n7\n8\n9\n10`)
Insert cell
renderInput = (s, {label = 'input'} = {}) => {
const {classNames} = useScope()

const lines = s.trim().split(/(?<=\n)/)

const renderToken = (token, classNames = '') => htl.html.fragment`<span class="${classNames}">${token}</span>`

const renderLine = (line) => {
const tokens = line.split(/(\s+)/)

const spans = tokens.map(token => {
if (!token.trim()) {
if (token === '\n') {
return renderToken(token.replace(/\s/g, '↵'), classNames.whitespace)
} else {
return renderToken(token.replace(/\s/g, '•'), classNames.whitespace)
}
} else {
return renderToken(token)
}
})

return htl.html.fragment`<code class="${classNames.line}">${spans}</code>`
}
const element = htl.html`
<style>
.${classNames.pre} {
counter-reset: line;
display: flex;
flex-direction: column;
border: 1px solid #333340;
background-color: #10101a;
color: #cccccc;
overflow: hidden;
}

.${classNames.pre} .${classNames.scroll} {
padding: 0.5em;
display: flex;
flex-direction: column;
max-height: 12em;
overflow: auto;
}

.${classNames.pre} .${classNames.header} {
color: white;
width: calc(100% + 1em);
margin: 0 -0.5em;
border-bottom: 1px solid #cccccc;
}

.${classNames.pre} h5 {
color: white;
padding: 0.5em 1em;
}

.${classNames.pre} .${classNames.line} {
counter-increment: line;
}

.${classNames.pre} .${classNames.line}:before {
display: inline-block;
content: '';
width: 3em;
user-select: none;
opacity: 0.33;
}

.${classNames.pre} .${classNames.line}:before {
content: counter(line);
}

.${classNames.pre} .${classNames.whitespace} {
opacity: 0.33;
}
</style>
<pre class="${classNames.pre}">
<div class="${classNames.header}"><h5>${label} (${s.length} characters, ${lines.length} lines)</h5></div>
<div class="${classNames.scroll}">
${lines.map(line => renderLine(line))}
</div>
</pre>`
element.value = s
return element
}
Insert cell
useScope = () => {
const hash = crypto.randomUUID()
const scoped = classNames => typeof classNames === 'string'
? classNames.split(/\s+/).map(name => `${name}-${hash}`).join(' ')
: R.map(scoped, classNames)

const classNames = new Proxy({}, {
get (target, prop, receiver) {
return scoped(prop)
}
})

return {hash, scoped, classNames}
}
Insert cell
R = import('ramda')
Insert cell
fp = (await import('https://cdn.skypack.dev/lodash/fp')).default
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more