Skip to content

Commit

Permalink
init commit
Browse files Browse the repository at this point in the history
  • Loading branch information
isTravis committed Mar 5, 2024
0 parents commit fff8c4c
Show file tree
Hide file tree
Showing 17 changed files with 12,124 additions and 0 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
misc
.DS_Store
*.log
node_modules
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# 211

**What's the 2-1-1?**

211s are short, simple descriptions of an idea that are no more than 211 words long, and use only the 2^11 most common english words.

The goal isn't to make it impossible or a big challenge to write. We just want a gut check on how much jargon we're using, and a nudge towards writing more simply.

This doesn't focus on tracking character count because the abbreviations you see on twitter inhibit comprehension more than aid.

**Next Steps**

- Originally the editor was built as simple flat html/js files. This worked fine for the editor, but I then decided to add in 'Posts', and the management of that as flat HTML is brittle. If we wind up using this, we'll want a cleaner way to add simple markdown files that we can build into a post directory, and auto-populate the Post listing on the landing page. The simplest path is probably just to pick a templating framework and add a couple config/layout files.
60 changes: 60 additions & 0 deletions editor/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<script type="text/javascript" src="/editor/words.js"></script>
<script type="text/javascript" src="/editor/script.js" defer></script>
<link rel="icon" type="image/png" href="/favicon.png" />
<link rel="icon" type="image/x-icon" href="/favicon.ico" />
<link rel="stylesheet" href="/style.css" />
<title>211 Editor</title>
<meta
name="description"
content="211s are short, simple statements of an idea that are no more than 211 words long, and use only the 2^11 most common English words."
/>
</head>
<body>
<nav>
<div><a href="/">211</a></div>
<ul>
<li><a href="/">Posts</a></li>
<li><a href="/editor">Editor</a></li>
</ul>
</nav>
<main class="editor">
<div class="description">
211s are short, simple statements of an idea that are no more than 211 words long,
and use only the 2<sup>11</sup> most common English words.
</div>
<div id="editor-wrapper">
<div id="editor">
<textarea id="text" autofocus></textarea>
<div id="mask"></div>
</div>
</div>
<div class="details">
<div class="count">
<div class="detail-title">Word count</div>
<div id="word-count"></div>
</div>
<div class="word-list" id="word-list">
<div class="detail-header">
<div class="detail-title hide-on-all">Words to Change</div>
<div class="detail-title show-on-all">All Words</div>
<div>
<label for="allwords">All words</label>
<input type="checkbox" id="allwords" name="allwords" value="All" />
</div>
</div>
<div id="jargon"></div>
</div>
</div>
</main>
<footer>
<a href="https://github.com/knowledgefutures/211">Code</a>
<span>·</span>
Word data from <a href="https://www.wordfrequency.info/">wordfrequency.info</a>
</footer>
</body>
</html>
29 changes: 29 additions & 0 deletions editor/parse.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { parse } from 'csv-parse/sync';
import fs from 'fs';

const fileBuffer = fs.readFileSync('editor/wordforms.csv');
const records = parse(fileBuffer, {
columns: true,
});

const words = {};
records
// .filter((record) => {
// return Number(record.lemRank) < 2049;
// })
.forEach((record) => {
if (!words[record.word]) {
// The source CSV seems to have some duplicates at higher ranks.
// e.g. "this"
words[record.word] = { rank: Number(record.lemRank), lemma: record.lemma };
}
});

const data = `const words = ${JSON.stringify(words)};`;

fs.writeFile('editor/words.js', data, (err) => {
if (err) {
throw err;
}
console.log('JSON data is saved.');
});
94 changes: 94 additions & 0 deletions editor/script.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
const textareaNode = document.getElementById('text');
const maskNode = document.getElementById('mask');
const jargonNode = document.getElementById('jargon');
const wordCountNode = document.getElementById('word-count');
const allwordsNode = document.getElementById('allwords');
const wordListNode = document.getElementById('word-list');

const parseWords = () => {
const jargonList = document.createElement('ul');
const input = textareaNode.value;
const inputWords = input
.trim()
.toLowerCase()
.replace(/[\r\n]+/g, ' ')
.replace(/[.,\/#!?$%\^&\*;:{}=\_`~()]/g, '')
.split(' ')
.filter((word) => word.length);
const wordCount = inputWords.length;
wordCountNode.innerHTML = wordCount > 211 ? `<span>${wordCount}</span>` : wordCount;
const seenWords = {};
let hasInvalidWords = false;
inputWords
.filter((word) => {
// Make sure it has at least one letter.
// We have to do this for leading hyphens, which
// are included for the sake of hyphenated words.
return word.match(/\b([\w]+)\b/g);
})
.filter((word) => {
if (seenWords[word]) {
return false;
}
seenWords[word] = true;
return true;
})
.forEach((word) => {
const wordObject = words[word];
const wordNode = document.createElement('li');
const textnode = document.createElement('div');
textnode.innerHTML = word;
textnode.className = "text";
const isValid = wordObject && wordObject.rank <= 2048;
if (!isValid) {
hasInvalidWords = true;
}
const countNode = document.createElement('span');
countNode.textContent = wordObject ? wordObject.rank : '5000+';
wordNode.className = isValid ? 'valid' : 'not-valid';
wordNode.appendChild(textnode);
wordNode.appendChild(countNode);
jargonList.appendChild(wordNode);
});
jargonNode.innerHTML = '';
if (hasInvalidWords || allwordsNode.checked) {
jargonNode.appendChild(jargonList);
} else {
jargonNode.innerHTML = "<div class='shadow'>All words are valid!</div>";
}
};
const overlayMask = () => {
const newItems = textareaNode.value.replaceAll(/\b([\w-']+)\b/g, (word) => {
const cleanedWord = word
.toLowerCase()
.replace(/[\r\n]+/g, ' ')
.replace(/[.,\/#!?$%\^&\*;:{}=\_`~()]/g, '');
const wordObject = words[cleanedWord];
const isValid = wordObject && wordObject.rank < 2048;
if (!isValid) {
return `<span>${word}</span>`;
}
return word;
});
maskNode.innerHTML = newItems;
};

const auto_grow = () => {
textareaNode.style.height = '0px';
textareaNode.style.height = textareaNode.scrollHeight + 'px';
};

const handleCheck = () => {
const isChecked = allwordsNode.checked;
wordListNode.className = isChecked ? 'word-list all' : 'word-list';
parseWords();
};

textareaNode.addEventListener('keyup', parseWords);
textareaNode.addEventListener('input', overlayMask);
textareaNode.addEventListener('input', auto_grow);
allwordsNode.addEventListener('input', handleCheck);
auto_grow();
parseWords();
overlayMask();
handleCheck();
Loading

0 comments on commit fff8c4c

Please sign in to comment.