Skip to content

Instantly share code, notes, and snippets.

@MattiasMartens
Last active May 8, 2023 01:52
Show Gist options
  • Save MattiasMartens/4bc8c9ca515a566fa1afd05355bfb239 to your computer and use it in GitHub Desktop.
Save MattiasMartens/4bc8c9ca515a566fa1afd05355bfb239 to your computer and use it in GitHub Desktop.
Bluesky Threader
<!DOCTYPE html>
<html>
<head>
<title>Tweet Threader</title>
<link
href="data:image/png;base64,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"
rel="icon"
type="image/x-icon"
/>
<style>
.col1,
.col2 {
display: inline-block;
width: 30em;
vertical-align: top;
}
.row {
margin: auto;
width: fit-content;
}
textarea {
width: 28em;
box-sizing: border-box;
padding: 0.5em;
margin-left: 1em;
}
#char-count {
display: inline-block;
float: right;
margin-right: 1em;
}
/** circle */
#char-count .quiet-remaining:before {
content: "•";
font-size: large;
color: #1da1f2;
cursor: pointer;
}
#char-count .quiet-remaining.near-edge:before {
color: red;
}
.tweet-block--content,
textarea,
.tweet-block--index,
.toast,
#char-count,
p {
font-family: "Lucida Console", Monaco, monospace;
font-size: 1em;
}
h1 {
font-family: "system-ui", -apple-system, BlinkMacSystemFont, "Segoe UI",
Roboto, "Helvetica Neue", Arial, sans-serif;
color: #1da1f2;
text-align: center;
margin-bottom: 0;
}
.subtitle {
text-align: center;
font-family: "system-ui", -apple-system, BlinkMacSystemFont, "Segoe UI",
Roboto, "Helvetica Neue", Arial, sans-serif;
}
h2 {
font-family: "system-ui", -apple-system, BlinkMacSystemFont, "Segoe UI",
Roboto, "Helvetica Neue", Arial, sans-serif;
color: #125580;
}
.tweet-block {
border: 1px solid #ccc;
position: relative;
margin-bottom: 1em;
background-color: #f7fcff;
width: 30em;
}
.tweet-block:hover {
background-color: #e8f5fe;
}
.tweet-block--index {
position: absolute;
top: 10px;
left: 10px;
color: #1da1f2;
}
.tweet-block--content {
width: 26em;
margin-left: 2em;
margin-top: 2.5em;
margin-bottom: 1.5em;
padding: 0.25em;
display: inline-block;
cursor: pointer;
cursor: copy;
transition: background-color 250ms;
word-wrap: break-word;
}
.tweet-block--content p {
margin-top: 1em;
}
.tweet-block--content:hover {
background-color: #9fd2f2;
}
.toast {
background-color: #1da1f2;
color: white;
padding: 1em;
position: fixed;
bottom: 1em;
right: 1em;
z-index: 1;
opacity: 0;
transition: opacity 250ms;
}
code {
background-color: #f7fcff;
padding: 0.25em;
margin: 0;
border-radius: 0.25em;
/** red code color */
color: #e83e8c;
/** light grey border */
border: 1px solid #d1d5da;
margin-left: -0.25em;
margin-right: -0.25em;
}
</style>
</head>
<body>
<h1>Tweet Threader</h1>
<div class="subtitle">
By
<a href="https://twitter.com/mattiasinspace" _target="blank"
>@MattiasInSpace</a
>
</div>
<div class="row">
<div class="col1">
<h2>Enter text you want to make into a thread</h2>
<p>
Text will break into tweets every 280 characters. To add an explicit
tweet break, add the pipe character <code>|</code> on its own line.
</p>
<textarea id="input-text"></textarea>
<span id="char-count"></span>
</div>
<div class="col2">
<div id="output">
<h2>Rendered into tweet blocks</h2>
<div id="output-text"></div>
</div>
</div>
</div>
<script>
window.toggleAlwaysShowRemaining = function () {
const newAlwaysShowRemaining = !localStorage.getItem(
"alwaysShowRemaining"
);
const remainingElement = document.querySelector(".remaining");
if (remainingElement) {
if (newAlwaysShowRemaining) {
remainingElement.style.display = "initial";
} else if (!remainingElement.classList.contains("always-show")) {
remainingElement.style.display = "none";
}
}
newAlwaysShowRemaining ? localStorage.setItem("alwaysShowRemaining", 'true') : localStorage.removeItem("alwaysShowRemaining");
};
function truncateTextWithEllipsis(text, maxLength) {
if (text.length <= maxLength) {
return text;
}
return text.slice(0, maxLength - 1) + "…";
}
function showToast(message) {
// Create the toast element
const toast = document.createElement("div");
toast.classList.add("toast");
toast.innerHTML = message;
// Insert the toast element into the DOM
document.body.appendChild(toast);
// Show the toast
setTimeout(function () {
toast.style.opacity = 1;
}, 0);
// Show the toast for 3 seconds
setTimeout(function () {
toast.style.opacity = 0;
setTimeout(function () {
toast.remove();
}, 250);
}, 3000);
}
function escapeHTML(html) {
return html.replace(/[&<>"]/g, function (char) {
switch (char) {
case "&":
return "&amp;";
case "<":
return "&lt;";
case ">":
return "&gt;";
case '"':
return "&quot;";
}
});
}
const rerenderInput = function () {
// Break input text into Tweets
/** @type string */ const text = inputText.value;
const delimited = text.split("\n|\n");
// Use newlines as paragraph breaks
const brokenLengthwise = delimited
.map((chunk) => {
const broken = chunk.match(/.{1,280}/gs);
if (!broken) {
return [];
}
return [...broken].map((chunk) =>
chunk
.split("\n")
.map((innerChunk) => `${escapeHTML(innerChunk)}<br>`)
.join("")
);
})
.flat();
const outputHTML = outputText.innerHTML;
const marker = '<span style="color: red;">|</span>';
outputText.innerHTML = brokenLengthwise
.map(
(tweet, index, { length }) =>
`<div class="tweet-block"><div class="tweet-block--index">${
index + 1
}/${length}</div><div class="tweet-block--content" title="Click to copy">${tweet}</div></div>`
)
.join("");
// Save previous input to local storage
localStorage.setItem("inputText", inputText.value);
// Update height of textarea input
inputText.style.height = "1px";
inputText.style.height = 25 + inputText.scrollHeight + "px";
// Update char count
const charCount = document.getElementById("char-count");
charCount.innerHTML = "";
const lastTweet = document.querySelector(
".tweet-block:last-child .tweet-block--content"
);
if (lastTweet) {
const innerTextLength = lastTweet.innerText.length - 1;
const remaining = 280 - innerTextLength;
const showRemaining = remaining <= 20;
const showRemainingMerged = showRemaining || !!localStorage.getItem("alwaysShowRemaining");
const nearEdge = remaining <= 10;
const charText = `${innerTextLength}/280 (remaining: ${remaining})`;
const quietRemainingHtml = `<span class="quiet-remaining ${
nearEdge ? "near-edge" : ""
}" title="${charText}" onclick="window.toggleAlwaysShowRemaining()"></span>`;
const color = nearEdge ? "red" : "#125580";
const remainingHtml = `<span class="remaining ${showRemaining ? 'always-show' : ''}" style="color: ${color}; margin-left: 0.5em; display: ${
showRemainingMerged ? "initial" : "none"
}">${charText}</span>`;
charCount.innerHTML = quietRemainingHtml + remainingHtml;
}
};
const inputText = document.getElementById("input-text");
const outputText = document.getElementById("output-text");
inputText.addEventListener("input", rerenderInput);
// Load previous input from local storage
const previousInput = localStorage.getItem("inputText");
if (previousInput) {
inputText.value = previousInput;
rerenderInput();
}
// Add click-to-copy for tweet blocks
const col2 = document.querySelector(".col2");
col2.addEventListener("click", (event) => {
const target = event.target;
const content = target.closest(".tweet-block--content");
if (!!target) {
const range = document.createRange();
range.selectNode(target);
window.getSelection().removeAllRanges();
window.getSelection().addRange(range);
document.execCommand("copy");
window.getSelection().removeAllRanges();
showToast(
`Copied to clipboard: ${truncateTextWithEllipsis(
content.innerText,
32
)}`
);
}
});
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment