我带着一丝调侃,创建了这个脚本,将一段文本拆分成推文风暴,以提高“可读性”。 这有点像 Mercury Reader 的反面。 如果你没有明白这种讽刺,那么这就是对那些选择在 Twitter 上发布长篇内容而不是,你知道,可读段落的人的一种委婉的批评。
查看 CodePen 上 Chris Coyier (@chriscoyier) 的作品 将文本转换为推文风暴。
看看它的工作原理可能会很有趣。
首先,我们需要将文本拆分成句子数组。
我们不会对文本在页面上的位置进行任何复杂的分析,尽管可能存在某种算法来做到这一点。 我们假设我们拥有以下内容
<main id="text">
Many sentences in here. So many sentences. Probably dozens of them.
</main>
让我们获取这段文本,去掉所有 HTML 代码,就像这样
let content = document.querySelector("#text").textContent;
现在我们需要将其拆分成句子。 这可能像在句点处分割一样简单,比如 content.split(". ")
,但这样做没有任何智能。 例如,像“你要去哪里,安德森先生?”这样的句子会在“先生”的末尾而不是“?”的末尾断开,这可不是什么好兆头。
这是在 Stack Overflow 上找到的解决方法!
这个答案相当不错。 我们将执行
let contentArray = content.replace(/([.?!])\s*(?=[A-Z])/g, "$1|").split("|");
我并没有试图深入研究它的工作原理,但乍一看,它似乎处理了一些常见的句子结尾标点符号,以及那些“安德森先生”的情况。
我们需要一些推文模板。
有两个:一个是开始主题的,另一个是回复推文。 我们应该创建一个模板,因为我们需要根据需要多次循环使用回复推文,而这似乎是最佳方法。
我选择了 Handlebars,说实话,因为它是我想到的第一个。 我可能可以使用更简单的 Mustache,但无论如何这只是一个演示。 我还可以/应该使用 模板文字模板。
为了创建模板,我做的第一件事是用模拟数据在 HTML 和 CSS 中创建一个推文,就像我从头开始开发一个组件一样。
<div class="tweet">
<div class="user">
<img src="/fake-user.svg" alt="" class="user-avatar">
<div class="user-fullname">Jimmy Fiddlecakes</div>
<div class="user-username">@everythingmatters</div>
</div>
<div class="tweet-text">
Blah blah blah important words. 1/80
</div>
<time class="tweet-time">
5:48 PM - 15 Sep 2017
</time>
yadda yadda yadda
我编写了自己的 HTML 和 CSS,但使用 DevTools 观察了真实的 Twitter 设计,并尽可能多地窃取十六进制代码、字体大小等,以使其看起来真实。
为了将这些 HTML 推文块转换为真正的模板,我按照 Handlebars 的方式将它们包装在脚本标签中
现在我可以
// Turn the template into a function I can call to compile it:
let mainTweetSource = document.querySelector("#main-tweet-template").innerText;
let mainTweetTemplate = Handlebars.compile(mainTweetSource);
// Compile it whenever:
let mainTweetHtml = mainTweetTemplate(data);
那里的 data
是有用的部分。 这是模板的意义所在。
这种模板中的“数据”是什么? 以下是内容

我们可以用对象来表示,就像 Handlebars 想要的那样
let mainTweetData = {
"avatar": "200/[email protected]",
"user-fullname": "Jimmy Fiddlecakes",
"user-username": "@everythingmatters",
"tweet-text": "", // from our array!
"tweet-time": "5:48 PM - 15 Sep 2017",
"comments": contentArray.length + 1,
"retweets": Math.floor(Math.random() * 100),
"loves": Math.floor(Math.random() * 200),
"tweet-number": 1,
"tweet-total": contentArray.length
};
现在我们遍历句子并组合模板。
// .shift() off the first sentence and compile the main tweet template first
let mainTweetHtml = mainTweetTemplate(mainTweetData);
let allSubtweetsHTML = "";
// Loop over the rest of the sentences
contentArray.forEach(function(sentence, i) {
let subtweet_data = {
// gather up the data fresh each time, randomzing numbers and
// most importantly plopping in the new sentence:
"tweet-text": sentence,
...
};
let subTweetHtml = subTweetTemplate(subtweetData);
allSubtweetsHTML += subTweetHtml;
}
// Now dump out all this HTML somewhere onto the page:
document.querySelector("#content").innerHTML = `
<div class="all-tweets-container">
${mainTweetHtml}
${allSubtweets}
</div>
`;
这样就可以了!
我相信有很多方法可以改进它,所以请随时复制 CodePen 并开始尝试。 最终的目标是将其制作成一个浏览器扩展。
我更喜欢速读:https://codepen.io/fauxserious/pen/EgWQNq
您好,
一个小问题,为什么在时间轴中我们总是需要显示用户名?
正则表达式分割过于复杂,并且遗漏了一个重要部分。 所有推文都限制在 140 个(现在是 280 个)字符以内。 因此,只需获取字符串的长度,将其除以 140 或 280,然后多次切片。 如果您希望它偏向于,可以添加一些关于空格和单词的检查,但这仍然不需要复杂的正则表达式。
更棒的是! 这样一来,推文就不会在完整的句子处结束,阅读起来更困难! ;)
您可以结合这两种方法来获取完整的句子,但您无法保证完整的句子始终在推文的长度内。 推文风暴中的大多数推文都没有按句子分割,它们通常在最后一个可能的词后分割。
因此,您实际上需要切片,并将字符从最后一个空格移动到下一条推文的开头。
显然,JS 技巧是这篇文章的真正目的,但对于那些只是想快速完成这项工作的人来说,我最近发现了 Chirr App,它是一个在线工具,可以很好地完成这项工作,还可以选择使用省略号 (…) 来指示您希望手动分割句子。
您使用的正则表达式实际上并没有解决“安德森先生”的情况。 它基本上假设标点符号后面的任何大写字母都是新句子的开头,而“安德森先生”符合这一标准,但显然不是两个句子。 自己试试,将这段代码粘贴到浏览器的控制台中,您会发现有 3 个推文块,而不是 2 个。
我也正要发布同样的内容。 事实上,如果没有创建一个详尽的缩略语列表(“先生”、“女士”、“博士”、“小姐”、“圣”等)来排除在分割算法之外,就无法轻松处理“安德森先生”这种情况。
此外,正如其他评论者所指出的,一个句子可能超过 Twitter 的 140 个(或 280 个)字符限制。 作为概念验证,这里介绍的方法还可以,但绝对不能用于生产环境。