字数限制新规出台,是否配套增加字数统计提示
- 内容介绍
- 文章标签
- 相关推荐
字数限制新规出台,是否可以配套增加字数统计提示,原先 6 字还是很容易肉眼计数的,现在限制 20 字经常遇到:字数不足 → 增加几个字 → 字数不足 的尴尬情况,如果有个字数提示器就方便多了
image730×286 10.2 KB
油猴简单实现了一下,不过还是希望有个官方提示器哈哈
字数统计提示器
// ==UserScript==
// @name Linux.do 字数统计显示
// @namespace https://linux.do/
// @version 1.0
// @description 在 Linux.do 论坛帖子编辑区右下角显示实时字数统计
// @match https://linux.do/*
// @grant none
// ==/UserScript==
(function () {
'use strict';
/**
* 等待某个元素出现
* @param {string} selector
* @param {number} timeout 毫秒
* @returns {Promise<HTMLElement>}
*/
function waitForElement(selector, timeout = 20000) {
return new Promise((resolve) => {
const el = document.querySelector(selector);
if (el) return resolve(el);
const observer = new MutationObserver(() => {
const element = document.querySelector(selector);
if (element) {
observer.disconnect();
resolve(element);
}
});
observer.observe(document.body, { childList: true, subtree: true });
setTimeout(() => {
observer.disconnect();
}, timeout);
});
}
/**
* 创建字数统计显示容器
*/
function createCounter() {
const counter = document.createElement('div');
counter.id = 'post-word-counter';
counter.style.position = 'absolute';
counter.style.right = '8px';
counter.style.bottom = '4px';
counter.style.fontSize = '13px';
counter.style.color = '#888';
counter.style.userSelect = 'none';
counter.style.pointerEvents = 'none';
counter.style.zIndex = '10';
return counter;
}
/**
* 初始化字数统计
*/
async function initCounter() {
const textarea = await waitForElement('.d-editor-input');
if (!textarea) return;
// 防止重复添加
if (document.querySelector('#post-word-counter')) return;
const wrapper = textarea.closest('.d-editor-textarea-wrapper');
if (!wrapper) return;
const counter = createCounter();
wrapper.style.position = 'relative';
wrapper.appendChild(counter);
const updateCount = () => {
const text = textarea.value.trim();
const length = text.length;
counter.textContent = `字数:${length}`;
};
textarea.addEventListener('input', updateCount);
updateCount();
}
/**
* 监听编辑器打开事件(Discourse 动态加载)
*/
function observeComposer() {
const observer = new MutationObserver(() => {
const composer = document.querySelector('.d-editor-input');
if (composer && !document.querySelector('#post-word-counter')) {
initCounter();
}
});
observer.observe(document.body, { childList: true, subtree: true });
}
// 启动监听
observeComposer();
})();
v1.1 增加红绿高亮优化,灵感来自 @torvalds
// ==UserScript==
// @name Linux.do 字数统计 + 剩余提示
// @namespace https://linux.do/
// @version 1.1
// @description 在 Linux.do 编辑器右下角显示实时字数统计,不足20字符警示
// @match https://linux.do/*
// @grant none
// ==/UserScript==
(function () {
'use strict';
// ✅ 等待元素出现工具函数
function waitForElement(selector, timeout = 20000) {
return new Promise((resolve) => {
const el = document.querySelector(selector);
if (el) return resolve(el);
const observer = new MutationObserver(() => {
const element = document.querySelector(selector);
if (element) {
observer.disconnect();
resolve(element);
}
});
observer.observe(document.body, { childList: true, subtree: true });
setTimeout(() => observer.disconnect(), timeout);
});
}
// ✅ 创建计数器元素
function createCounter() {
const counter = document.createElement('div');
counter.id = 'post-word-counter';
counter.style.position = 'absolute';
counter.style.right = '8px';
counter.style.bottom = '8px';
counter.style.fontSize = '13px';
counter.style.color = '#fff';
counter.style.padding = '2px 10px';
counter.style.borderRadius = '12px';
counter.style.userSelect = 'none';
counter.style.pointerEvents = 'none';
counter.style.zIndex = '10';
counter.style.backgroundColor = '#444'; // 默认灰色
counter.style.transition = 'all 0.2s';
return counter;
}
async function initCounter() {
const textarea = await waitForElement('.d-editor-input');
if (!textarea) return;
// 避免重复
if (document.querySelector('#post-word-counter')) return;
const wrapper = textarea.closest('.d-editor-textarea-wrapper');
if (!wrapper) return;
const counter = createCounter();
wrapper.style.position = 'relative';
wrapper.appendChild(counter);
const updateCount = () => {
const text = textarea.value.trim();
const length = text.length;
const minRequired = 20;
const remaining = minRequired - length;
if (length < minRequired) {
counter.textContent = `字数:${length} | 还差 ${remaining} 个字符`;
counter.style.backgroundColor = '#b71c1c'; // 红色
} else {
counter.textContent = `字数:${length}`;
counter.style.backgroundColor = '#2e7d32'; // 绿色
}
};
textarea.addEventListener('input', updateCount);
updateCount();
}
// ✅ 监听编辑器出现(Discourse 动态)
function observeComposer() {
const observer = new MutationObserver(() => {
const composer = document.querySelector('.d-editor-input');
if (composer && !document.querySelector('#post-word-counter')) {
initCounter();
}
});
observer.observe(document.body, { childList: true, subtree: true });
}
observeComposer();
})();
v1.2 修复中文输入法拼音误统计bug
// ==UserScript==
// @name Linux.do 字数统计(中文输入优化)
// @namespace https://linux.do/
// @version 1.2
// @description 在 Linux.do 编辑器右下角显示实时字数统计,支持中文输入法候选状态,不足20字符红色提示
// @match https://linux.do/*
// @grant none
// ==/UserScript==
(function () {
'use strict';
// 等待元素出现
function waitForElement(selector, timeout = 20000) {
return new Promise((resolve) => {
const el = document.querySelector(selector);
if (el) return resolve(el);
const observer = new MutationObserver(() => {
const element = document.querySelector(selector);
if (element) {
observer.disconnect();
resolve(element);
}
});
observer.observe(document.body, { childList: true, subtree: true });
setTimeout(() => observer.disconnect(), timeout);
});
}
// 创建计数器
function createCounter() {
const counter = document.createElement('div');
counter.id = 'post-word-counter';
counter.style.position = 'absolute';
counter.style.right = '8px';
counter.style.bottom = '8px';
counter.style.fontSize = '13px';
counter.style.color = '#fff';
counter.style.padding = '2px 10px';
counter.style.borderRadius = '12px';
counter.style.userSelect = 'none';
counter.style.pointerEvents = 'none';
counter.style.zIndex = '10';
counter.style.backgroundColor = '#444'; // 默认灰色
counter.style.transition = 'all 0.2s';
return counter;
}
async function initCounter() {
const textarea = await waitForElement('.d-editor-input');
if (!textarea) return;
if (document.querySelector('#post-word-counter')) return;
const wrapper = textarea.closest('.d-editor-textarea-wrapper');
if (!wrapper) return;
const counter = createCounter();
wrapper.style.position = 'relative';
wrapper.appendChild(counter);
let isComposing = false; // 是否处于中文输入法拼音阶段
const updateCount = () => {
if (isComposing) return; // 忽略拼音输入过程
const text = textarea.value.trim();
const len = text.length;
const min = 20;
const remaining = min - len;
if (len < min) {
counter.textContent = `字数:${len} | 还差 ${remaining} 个字符`;
counter.style.backgroundColor = '#b71c1c'; // 红色
} else {
counter.textContent = `字数:${len}`;
counter.style.backgroundColor = '#2e7d32'; // 绿色
}
};
textarea.addEventListener('compositionstart', () => {
isComposing = true;
});
textarea.addEventListener('compositionend', () => {
isComposing = false;
updateCount(); // 中文确认后更新
});
textarea.addEventListener('input', updateCount);
updateCount();
}
// 监听 Discourse 编辑器加载
function observeComposer() {
const observer = new MutationObserver(() => {
const composer = document.querySelector('.d-editor-input');
if (composer && !document.querySelector('#post-word-counter')) {
initCounter();
}
});
observer.observe(document.body, { childList: true, subtree: true });
}
observeComposer();
})();
--【壹】--:
今天已经被举报好多次了,看看别人都是怎么弄的
--【贰】--:
image755×415 22.9 KB
--【叁】--:
加了其他md字符吧,比如星号加粗加了很多这种
--【肆】--:
为啥你一个字就可以
我十分疑惑你这个表述方案
--【伍】--: Pierre Zhang:
************可************
这种强行凑字数的方案倒是第一次见,各位佬友各显神通,就是容易陨落
--【陆】--:
我觉得可以啊 不让还得自己去测试 打了多少字数了
--【柒】--:
别看
说别看,你又看了是吧
还可以在折叠块里面放垃圾文字(折叠内容一般没人看),在外面放正常的简短的回复
--【捌】--:
八仙过海各显神通,我是服了你了哈哈哈,太狠了。
--【玖】--:
这样是不行的哦,一举报一个准的呢。。还是要足字数
--【拾】--:
感谢佬的脚本,有个字数统计对于回复来说真的很方便
--【拾壹】--:
小心因为发现始皇留下的特性被始皇请进去喝茶
--【拾贰】--:
为啥要加字数限制,只会添加更多无意义内容,加上数据存储压力
--【拾叁】--:
Linus Torvalds 还是太快了
--【拾肆】--:
泻药,已陨落。(7字)
自从我按下“回复”键的那一刻起,那条评论的最终归宿就确定了。(37字)
--【拾伍】--:
添加不渲染的标记?比如这样?
#可 <div/> <div/> <div/> <div/> <div/> <div/> <div/> <div/> <div/> <div/>
出来就是这样:
可
--【拾陆】--:
这个字数限制让我今天被举报好几次了。难受
--【拾柒】--: Pierre Zhang:
泻药,已陨落。(7 字)
自从我按下 “回复” 键的那一刻起,那条评论的最终归宿就确定了。(37 字)
参考这位佬。
论坛的管理员都是手工审核的,这种过得了AI 过不了人眼,而且只是扫一眼的事
--【拾捌】--:
确实好用
小瑕疵就是 打拼音中途 没按空格之前出现的字母 也算了字数。
--【拾玖】--:
这楼是不是已经被不可名状和谐掉看不见了
字数限制新规出台,是否可以配套增加字数统计提示,原先 6 字还是很容易肉眼计数的,现在限制 20 字经常遇到:字数不足 → 增加几个字 → 字数不足 的尴尬情况,如果有个字数提示器就方便多了
image730×286 10.2 KB
油猴简单实现了一下,不过还是希望有个官方提示器哈哈
字数统计提示器
// ==UserScript==
// @name Linux.do 字数统计显示
// @namespace https://linux.do/
// @version 1.0
// @description 在 Linux.do 论坛帖子编辑区右下角显示实时字数统计
// @match https://linux.do/*
// @grant none
// ==/UserScript==
(function () {
'use strict';
/**
* 等待某个元素出现
* @param {string} selector
* @param {number} timeout 毫秒
* @returns {Promise<HTMLElement>}
*/
function waitForElement(selector, timeout = 20000) {
return new Promise((resolve) => {
const el = document.querySelector(selector);
if (el) return resolve(el);
const observer = new MutationObserver(() => {
const element = document.querySelector(selector);
if (element) {
observer.disconnect();
resolve(element);
}
});
observer.observe(document.body, { childList: true, subtree: true });
setTimeout(() => {
observer.disconnect();
}, timeout);
});
}
/**
* 创建字数统计显示容器
*/
function createCounter() {
const counter = document.createElement('div');
counter.id = 'post-word-counter';
counter.style.position = 'absolute';
counter.style.right = '8px';
counter.style.bottom = '4px';
counter.style.fontSize = '13px';
counter.style.color = '#888';
counter.style.userSelect = 'none';
counter.style.pointerEvents = 'none';
counter.style.zIndex = '10';
return counter;
}
/**
* 初始化字数统计
*/
async function initCounter() {
const textarea = await waitForElement('.d-editor-input');
if (!textarea) return;
// 防止重复添加
if (document.querySelector('#post-word-counter')) return;
const wrapper = textarea.closest('.d-editor-textarea-wrapper');
if (!wrapper) return;
const counter = createCounter();
wrapper.style.position = 'relative';
wrapper.appendChild(counter);
const updateCount = () => {
const text = textarea.value.trim();
const length = text.length;
counter.textContent = `字数:${length}`;
};
textarea.addEventListener('input', updateCount);
updateCount();
}
/**
* 监听编辑器打开事件(Discourse 动态加载)
*/
function observeComposer() {
const observer = new MutationObserver(() => {
const composer = document.querySelector('.d-editor-input');
if (composer && !document.querySelector('#post-word-counter')) {
initCounter();
}
});
observer.observe(document.body, { childList: true, subtree: true });
}
// 启动监听
observeComposer();
})();
v1.1 增加红绿高亮优化,灵感来自 @torvalds
// ==UserScript==
// @name Linux.do 字数统计 + 剩余提示
// @namespace https://linux.do/
// @version 1.1
// @description 在 Linux.do 编辑器右下角显示实时字数统计,不足20字符警示
// @match https://linux.do/*
// @grant none
// ==/UserScript==
(function () {
'use strict';
// ✅ 等待元素出现工具函数
function waitForElement(selector, timeout = 20000) {
return new Promise((resolve) => {
const el = document.querySelector(selector);
if (el) return resolve(el);
const observer = new MutationObserver(() => {
const element = document.querySelector(selector);
if (element) {
observer.disconnect();
resolve(element);
}
});
observer.observe(document.body, { childList: true, subtree: true });
setTimeout(() => observer.disconnect(), timeout);
});
}
// ✅ 创建计数器元素
function createCounter() {
const counter = document.createElement('div');
counter.id = 'post-word-counter';
counter.style.position = 'absolute';
counter.style.right = '8px';
counter.style.bottom = '8px';
counter.style.fontSize = '13px';
counter.style.color = '#fff';
counter.style.padding = '2px 10px';
counter.style.borderRadius = '12px';
counter.style.userSelect = 'none';
counter.style.pointerEvents = 'none';
counter.style.zIndex = '10';
counter.style.backgroundColor = '#444'; // 默认灰色
counter.style.transition = 'all 0.2s';
return counter;
}
async function initCounter() {
const textarea = await waitForElement('.d-editor-input');
if (!textarea) return;
// 避免重复
if (document.querySelector('#post-word-counter')) return;
const wrapper = textarea.closest('.d-editor-textarea-wrapper');
if (!wrapper) return;
const counter = createCounter();
wrapper.style.position = 'relative';
wrapper.appendChild(counter);
const updateCount = () => {
const text = textarea.value.trim();
const length = text.length;
const minRequired = 20;
const remaining = minRequired - length;
if (length < minRequired) {
counter.textContent = `字数:${length} | 还差 ${remaining} 个字符`;
counter.style.backgroundColor = '#b71c1c'; // 红色
} else {
counter.textContent = `字数:${length}`;
counter.style.backgroundColor = '#2e7d32'; // 绿色
}
};
textarea.addEventListener('input', updateCount);
updateCount();
}
// ✅ 监听编辑器出现(Discourse 动态)
function observeComposer() {
const observer = new MutationObserver(() => {
const composer = document.querySelector('.d-editor-input');
if (composer && !document.querySelector('#post-word-counter')) {
initCounter();
}
});
observer.observe(document.body, { childList: true, subtree: true });
}
observeComposer();
})();
v1.2 修复中文输入法拼音误统计bug
// ==UserScript==
// @name Linux.do 字数统计(中文输入优化)
// @namespace https://linux.do/
// @version 1.2
// @description 在 Linux.do 编辑器右下角显示实时字数统计,支持中文输入法候选状态,不足20字符红色提示
// @match https://linux.do/*
// @grant none
// ==/UserScript==
(function () {
'use strict';
// 等待元素出现
function waitForElement(selector, timeout = 20000) {
return new Promise((resolve) => {
const el = document.querySelector(selector);
if (el) return resolve(el);
const observer = new MutationObserver(() => {
const element = document.querySelector(selector);
if (element) {
observer.disconnect();
resolve(element);
}
});
observer.observe(document.body, { childList: true, subtree: true });
setTimeout(() => observer.disconnect(), timeout);
});
}
// 创建计数器
function createCounter() {
const counter = document.createElement('div');
counter.id = 'post-word-counter';
counter.style.position = 'absolute';
counter.style.right = '8px';
counter.style.bottom = '8px';
counter.style.fontSize = '13px';
counter.style.color = '#fff';
counter.style.padding = '2px 10px';
counter.style.borderRadius = '12px';
counter.style.userSelect = 'none';
counter.style.pointerEvents = 'none';
counter.style.zIndex = '10';
counter.style.backgroundColor = '#444'; // 默认灰色
counter.style.transition = 'all 0.2s';
return counter;
}
async function initCounter() {
const textarea = await waitForElement('.d-editor-input');
if (!textarea) return;
if (document.querySelector('#post-word-counter')) return;
const wrapper = textarea.closest('.d-editor-textarea-wrapper');
if (!wrapper) return;
const counter = createCounter();
wrapper.style.position = 'relative';
wrapper.appendChild(counter);
let isComposing = false; // 是否处于中文输入法拼音阶段
const updateCount = () => {
if (isComposing) return; // 忽略拼音输入过程
const text = textarea.value.trim();
const len = text.length;
const min = 20;
const remaining = min - len;
if (len < min) {
counter.textContent = `字数:${len} | 还差 ${remaining} 个字符`;
counter.style.backgroundColor = '#b71c1c'; // 红色
} else {
counter.textContent = `字数:${len}`;
counter.style.backgroundColor = '#2e7d32'; // 绿色
}
};
textarea.addEventListener('compositionstart', () => {
isComposing = true;
});
textarea.addEventListener('compositionend', () => {
isComposing = false;
updateCount(); // 中文确认后更新
});
textarea.addEventListener('input', updateCount);
updateCount();
}
// 监听 Discourse 编辑器加载
function observeComposer() {
const observer = new MutationObserver(() => {
const composer = document.querySelector('.d-editor-input');
if (composer && !document.querySelector('#post-word-counter')) {
initCounter();
}
});
observer.observe(document.body, { childList: true, subtree: true });
}
observeComposer();
})();
--【壹】--:
今天已经被举报好多次了,看看别人都是怎么弄的
--【贰】--:
image755×415 22.9 KB
--【叁】--:
加了其他md字符吧,比如星号加粗加了很多这种
--【肆】--:
为啥你一个字就可以
我十分疑惑你这个表述方案
--【伍】--: Pierre Zhang:
************可************
这种强行凑字数的方案倒是第一次见,各位佬友各显神通,就是容易陨落
--【陆】--:
我觉得可以啊 不让还得自己去测试 打了多少字数了
--【柒】--:
别看
说别看,你又看了是吧
还可以在折叠块里面放垃圾文字(折叠内容一般没人看),在外面放正常的简短的回复
--【捌】--:
八仙过海各显神通,我是服了你了哈哈哈,太狠了。
--【玖】--:
这样是不行的哦,一举报一个准的呢。。还是要足字数
--【拾】--:
感谢佬的脚本,有个字数统计对于回复来说真的很方便
--【拾壹】--:
小心因为发现始皇留下的特性被始皇请进去喝茶
--【拾贰】--:
为啥要加字数限制,只会添加更多无意义内容,加上数据存储压力
--【拾叁】--:
Linus Torvalds 还是太快了
--【拾肆】--:
泻药,已陨落。(7字)
自从我按下“回复”键的那一刻起,那条评论的最终归宿就确定了。(37字)
--【拾伍】--:
添加不渲染的标记?比如这样?
#可 <div/> <div/> <div/> <div/> <div/> <div/> <div/> <div/> <div/> <div/>
出来就是这样:
可
--【拾陆】--:
这个字数限制让我今天被举报好几次了。难受
--【拾柒】--: Pierre Zhang:
泻药,已陨落。(7 字)
自从我按下 “回复” 键的那一刻起,那条评论的最终归宿就确定了。(37 字)
参考这位佬。
论坛的管理员都是手工审核的,这种过得了AI 过不了人眼,而且只是扫一眼的事
--【拾捌】--:
确实好用
小瑕疵就是 打拼音中途 没按空格之前出现的字母 也算了字数。
--【拾玖】--:
这楼是不是已经被不可名状和谐掉看不见了

