Public
Edited
May 18
Fork of River Snow
Insert cell
Insert cell
<div class="set">has anyone said this before?

given that
the words
spill out of me, as
my states change
(and <i>as</i> my state’s change
as this, my flowing
if decaying
(<i>as</i> decaying
my continuum of
aging
multiplicities —

given all that
the answer must be: no

these words are not
my tokens
(not anyone’s tokens
of any
thing or idea
not a mere
(a mere, islanded
recombination: no

each one
each element
(which one?
which element, exactly?
and at what level of
what?
linguistic structure?

each one
recognizes,
reconfigures
all of what I once said
(once, then,
in my past

which leans down
(falling into
the present of what
I say now
at the horizon of
what I
mean to say

and never will
again

<em>[ After a line by Lao Yang: ]</em>

waiting
for stillness

to lean
down
over
us

*

waiting
for stillness
to
befall

*

waiting

stillness

falling</div>
Insert cell
parasConfig = ({ draft1: [] }) // , draft2: [], draft3: [], draft4: []
// Edit and construct this literal with properties that match
// the cell names of paragraphs.
// Other configuration is done in the config StrictObj:
Insert cell
config = {
let obj = {
paraNames: Object.keys(parasConfig),
paraCells: [draft1], // , draft2, draft3, draft4
spannedCells: [spanned1] // , spanned2, spanned3, spanned4
};
return new StrictObj(obj);
}
Insert cell
paras = {
let pArray = Array.from(Object.values(parasConfig));
pArray = pArray.map((a) => a.map((i) => i.id));
return pArray;
}
Insert cell
spels = mapParaSpels(config.get("spannedCells"), config.get("paraNames"))
Insert cell
spanString = Array.from(spels.values())
.map((spel) => spel.html)
.join("")
Insert cell
<div class="set">media echo chambers are filled with a deep cinnabar of
outrage and the algorithm fashions a crown upon the most
outrageous and controversial figures — the image of the
city blanketed in snow became a powerful symbol that
fashions its robe of silence around controversial issues</div>
Insert cell
<div class="set">supporters shouted <cite>stars</cite> <cite>stars</cite> in unison drowning out any
dissenting voices the pursuit of profit has eclipsed our
immortal words — others are effectively silenced,
disregarding the nuances of human hearing and critical
thinking our planet ends but critics argue</div>
Insert cell
<div class="set">shift instead toward addressing the root causes
chase fleeting ambitions tilting at quintain clouds of
uncertainty — this rise has seen discourse sweep wings
across the ideological landscape through online communities
where misinformation and all of us must <cite>fly</cite></div>
Insert cell
mapParaSpels = (spannedCells, paraNames) => {
let spels = new Map();
for (const [idx, spannedCell] of spannedCells.entries()) {
parasConfig[paraNames[idx]] = [];
let spelArray = getSpelArray(spannedCell, spels.size);
spelArray.forEach((spel) => {
spels.set(spel.id, {
string: spel.string,
leftvw: spel.leftvw,
topvw: spel.topvw,
html: spel.html
});
// array of spells added to paraName property of parasConfig
parasConfig[paraNames[idx]].push(spel);
});
}
return spels;
}
Insert cell
getSpelArray = (spannedElem, size = 0) => {
// builds the spels array of spel objects and returns styled spans for display
let spelArray = [];
let verseSpans = Array.from(spannedElem.children);
verseSpans.forEach((span, idx) => {
let spel = {};
spel.id = span.innerText + "_" + (idx + size);
spel.string = span.innerText;
spel.leftvw = pxToVw(span.offsetLeft);
spel.topvw = pxToVw(span.offsetTop);
spel.html = `<span id="${spel.id}" class="spel" style="left:${spel.leftvw}vw;top:${spel.topvw}vw">${span.innerHTML}</span>`;
spelArray.push(spel);
});
return spelArray;
}
Insert cell
addSpansTo = (draftElem) => {
let newText = ``; // this will hold html for the new draftSpanned cell
let text = draftElem.innerHTML; // get existing innerHTML from from the pre element of verse cell
let spelStart = text.search(/\S/); // find the first spel by finding first nonwhitespace
while (spelStart != -1) {
newText += text.substr(0, spelStart); // grab everything up to that point
text = text.substr(spelStart); // put the rest in text
let spelEnd = text.search(/\s/); // find where whitespace starts again
if (spelEnd == -1) spelEnd = text.length; // text ends with nonwhitespace
// wrap the spel we've found in span tags
newText += `<span>` + text.substr(0, spelEnd) + `</span>`; // add this to newText
text = text.substr(spelEnd); // put the rest in text
spelStart = text.search(/\S/); // find the next nonwhitespace (if any)
}
return `<div class="set">${newText}</div>`; // wrap in pre tags of same class
}
Insert cell
Insert cell
scores = {
let scores = [];
let spelIdx = 0;
let paraCells = config.get("paraCells");
for (let pIdx = 0; pIdx < paraCells.length; pIdx++) {
let score = [];
let paraElem = paraCells[pIdx];
let paraSpels = parasConfig[config.get("paraNames")[pIdx]];
let pauses = [],
pausesIdx = 0;
let textToProcess = paraElem.innerText,
s = textToProcess.search(/\S/);
while (s != -1) {
let spaces = textToProcess.substr(0, s);
textToProcess = textToProcess.substr(s);
let l = textToProcess.search(/\s/);
if (l == -1) l = textToProcess.length;
let word = textToProcess.substr(0, l);
pauses.push(timeToRead(word, pausesIdx++, spaces, pauses));
textToProcess = textToProcess.substr(l);
s = textToProcess.search(/\S/);
}
pauses.forEach((p, idx) => score.push({ id: paraSpels[idx].id, pause: p }));
scores.push(score);
}
return scores;
}
Insert cell
timeToRead = (word, idx, spaces, pauses, factor = 1) => {
let hundreths = 30;
let vowelsOrPunc = word.match(/[aeiouy,:;\.\?]/gi);
if (vowelsOrPunc) hundreths += (vowelsOrPunc.length * 15) / factor;
if (idx - 1 > -1) {
let crs = spaces.match(/[\n\r]/gi);
if (crs) pauses[idx - 1] += (crs.length * 150) / factor;
else pauses[idx - 1] += (spaces.length * 7.5) / factor;
}
return hundreths;
}
Insert cell
Insert cell
<h4>CSS</h4>
<style>

/* @font-face {
font-family: 'Source Serif 4';
src: local('Source Serif 4')
}
*/
.set {
white-space: pre;
position: relative;
font-family: "Source Serif 4", "Source Serif Pro", serif;
font-size: 2.5vw;
font-variant-ligatures: no-common-ligatures;
font-optical-sizing: auto;
font-style: normal;
font-variation-settings:
"wght" 500,
"wdth" 100,
"YTLC" 500;
line-height: 1.5;
color: black;
}

.spel {
position: absolute;
opacity: 0;
transition: all 1.5s ease-in-out; /* vendorless fallback */
-o-transition: all 1.5s ease-in-out; /* opera */
-ms-transition: all 1.5s ease-in-out; /* IE 10 */
-moz-transition: all 1.5s ease-in-out; /* Firefox */
-webkit-transition: all 1.5s ease-in-out; /*safari and chrome */
}

.spel.visible {
opacity: 1;
}

#display {
position: relative;
background-color: floralwhite;
color: darkslategray;
cursor: none;
overflow: hidden;
width: 60vw; /* This value should be calculated manually for notebooks that display */
height: 50vw; /* This value should be calculated manually for notebooks that display */
}

</style>
Insert cell
Insert cell
Insert cell
vWidth = Math.max(
document.documentElement.clientWidth || 0,
window.innerWidth || 0
)
Insert cell
Insert cell
randInt = (maxPlusOne) => (maxPlusOne * Math.random()) | 0
Insert cell
Insert cell
Insert cell
spanned1 = html`${await addSpansTo(draft1)}`
Insert cell
spanned2 = html`${await addSpansTo(draft2)}`
Insert cell
spanned3 = html`${await addSpansTo(draft3)}`
Insert cell
spanned4 = html`${await addSpansTo(draft4)}`
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