例如:
但我输入的文字符合自己设定的正则表达式的规则,则自动给当前块加上相关属性
例如当我笔记中存在成都时,自动给当前块加上“地点”:“成都”的属性
例如:
但我输入的文字符合自己设定的正则表达式的规则,则自动给当前块加上相关属性
例如当我笔记中存在成都时,自动给当前块加上“地点”:“成都”的属性
监听编辑器输入事件,仅供参考
(()=>{
// 编辑器输入事件
onEditorInput((editor) => {
// 获取光标所在元素
const currEl = getCursorElement();
console.log('当前元素', currEl);
// 获取当前块
const currBlock = currEl.closest('[data-type]');
console.log('当前块', currBlock);
});
// 编辑器输入事件
function onEditorInput(callback) {
whenElementExist(isMobile()?'body':'.layout__center').then(async element => {
// 等待笔记列表加载完毕
await sleep(40);
// 监听编辑器加载事件
observeDomChange(element, async (mutation) => {
if (mutation.target.classList?.contains("protyle-wysiwyg")) {
console.log(mutation.target);
const editor = mutation.target;
if(editor && editor.closest){
// 等待编辑器加载完毕
const protyle = editor.closest(".protyle");
if(protyle.dataset.loading !== 'finished'){
await whenElementExist(()=>editor?.closest(".protyle") === 'finished');
}
if(!editor.getAttribute('custom-listened')){
editor.setAttribute('custom-listened', true);
//console.log('listen editor');
editor.addEventListener('input', ()=>{
//console.log('editor inputed');
callback(editor);
})
}
}
}
});
});
}
// 获取光标所在元素
function getCursorElement() {
const selection = window.getSelection();
if (selection.rangeCount > 0) {
const range = selection.getRangeAt(0);
// 获取选择范围的起始位置所在的节点
const startContainer = range.startContainer;
// 如果起始位置是文本节点,返回其父元素节点
const cursorElement = startContainer.nodeType === Node.TEXT_NODE
? startContainer.parentElement
: startContainer;
return cursorElement;
}
return null;
}
// 观察元素被添加
function observeDomChange(selector, callback) {
// 定义一个回调函数,当DOM发生变化时调用
const onChange = function(mutationsList, observer) {
for (const mutation of mutationsList) {
if (mutation.type === 'childList') {
callback(mutation);
}
}
};
// 创建一个观察器实例,并传入回调函数
const observer = new MutationObserver(onChange);
// 配置观察选项:指定需要观察哪些变动
const config = { attributes: false, childList: true, subtree: true };
// 获取目标节点
const targetNode = typeof selector === 'string' ? document.querySelector(selector) : selector;
// 如果目标节点存在,则开始观察
if (targetNode) {
observer.observe(targetNode, config);
}
// 返回一个函数,用于停止观察
return () => {
observer.disconnect();
};
}
// 是否手机端
function isMobile() {
return !!document.getElementById("sidebar");
}
// 延迟执行
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
// 等待元素渲染完成后执行
function whenElementExist(selector) {
return new Promise(resolve => {
const checkForElement = () => {
let element = null;
if (typeof selector === 'function') {
element = selector();
} else {
element = document.querySelector(selector);
}
if (element) {
resolve(element);
} else {
requestAnimationFrame(checkForElement);
}
};
checkForElement();
});
}
})();
监听编辑器输入事件,仅供参考
(()=>{
// 编辑器输入事件
onEditorInput((editor) => {
// 获取光标所在元素
const currEl = getCursorElement();
console.log('当前元素', currEl);
// 获取当前块
const currBlock = currEl.closest('[data-type]');
console.log('当前块', currBlock);
});
// 编辑器输入事件
function onEditorInput(callback) {
whenElementExist(isMobile()?'body':'.layout__center').then(async element => {
// 等待笔记列表加载完毕
await sleep(40);
// 监听编辑器加载事件
observeDomChange(element, async (mutation) => {
if (mutation.target.classList?.contains("protyle-wysiwyg")) {
console.log(mutation.target);
const editor = mutation.target;
if(editor && editor.closest){
// 等待编辑器加载完毕
const protyle = editor.closest(".protyle");
if(protyle.dataset.loading !== 'finished'){
await whenElementExist(()=>editor?.closest(".protyle") === 'finished');
}
if(!editor.getAttribute('custom-listened')){
editor.setAttribute('custom-listened', true);
//console.log('listen editor');
editor.addEventListener('input', ()=>{
//console.log('editor inputed');
callback(editor);
})
}
}
}
});
});
}
// 获取光标所在元素
function getCursorElement() {
const selection = window.getSelection();
if (selection.rangeCount > 0) {
const range = selection.getRangeAt(0);
// 获取选择范围的起始位置所在的节点
const startContainer = range.startContainer;
// 如果起始位置是文本节点,返回其父元素节点
const cursorElement = startContainer.nodeType === Node.TEXT_NODE
? startContainer.parentElement
: startContainer;
return cursorElement;
}
return null;
}
// 观察元素被添加
function observeDomChange(selector, callback) {
// 定义一个回调函数,当DOM发生变化时调用
const onChange = function(mutationsList, observer) {
for (const mutation of mutationsList) {
if (mutation.type === 'childList') {
callback(mutation);
}
}
};
// 创建一个观察器实例,并传入回调函数
const observer = new MutationObserver(onChange);
// 配置观察选项:指定需要观察哪些变动
const config = { attributes: false, childList: true, subtree: true };
// 获取目标节点
const targetNode = typeof selector === 'string' ? document.querySelector(selector) : selector;
// 如果目标节点存在,则开始观察
if (targetNode) {
observer.observe(targetNode, config);
}
// 返回一个函数,用于停止观察
return () => {
observer.disconnect();
};
}
// 是否手机端
function isMobile() {
return !!document.getElementById("sidebar");
}
// 延迟执行
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
// 等待元素渲染完成后执行
function whenElementExist(selector) {
return new Promise(resolve => {
const checkForElement = () => {
let element = null;
if (typeof selector === 'function') {
element = selector();
} else {
element = document.querySelector(selector);
}
if (element) {
resolve(element);
} else {
requestAnimationFrame(checkForElement);
}
};
checkForElement();
});
}
})();
Postman 是一款简单好用的 HTTP API 调试工具。
又拍云是国内领先的 CDN 服务提供商,国家工信部认证通过的“可信云”,乌云众测平台认证的“安全云”,为移动时代的创业者提供新一代的 CDN 加速服务。
Git 是 Linux Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件。
Facebook 是一个联系朋友的社交工具。大家可以通过它和朋友、同事、同学以及周围的人保持互动交流,分享无限上传的图片,发布链接和视频,更可以增进对朋友的了解。
应用程序编程接口(Application Programming Interface)是一些预先定义的函数,目的是提供应用程序与开发人员基于某软件或硬件得以访问一组例程的能力,而又无需访问源码,或理解内部工作机制的细节。
单点登录(Single Sign On)是目前比较流行的企业业务整合的解决方案之一。SSO 的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。
WiFiDog 是一套开源的无线热点认证管理工具,主要功能包括:位置相关的内容递送;用户认证和授权;集中式网络监控。
OAuth 协议为用户资源的授权提供了一个安全的、开放而又简易的标准。与以往的授权方式不同之处是 oAuth 的授权不会使第三方触及到用户的帐号信息(如用户名与密码),即第三方无需使用用户的用户名与密码就可以申请获得该用户资源的授权,因此 oAuth 是安全的。oAuth 是 Open Authorization 的简写。
Go 语言是 Google 推出的一种全新的编程语言,可以在不损失应用程序性能的情况下降低代码的复杂性。谷歌首席软件工程师罗布派克(Rob Pike)说:我们之所以开发 Go,是因为过去 10 多年间软件开发的难度令人沮丧。Go 是谷歌 2009 发布的第二款编程语言。
希望你我能在旅途中找到人生的下一站。
星期六到星期天晚,实行五天工作制后,指每周的最后两天。再过几年可能就是三天了。
心是产生任何想法的源泉,心本体会陷入到对自己本体不能理解的状态中,因为心能产生任何想法,不能分出对错,不能分出自己。
房星网,我们不和没有钱的程序员谈理想,我们要让程序员又有理想又有钱。我们有雄厚的房地产行业线下资源,遍布昆明全城的 100 家门店、四千地产经纪人是我们坚实的后盾。
V2EX 是创意工作者们的社区。这里目前汇聚了超过 400,000 名主要来自互联网行业、游戏行业和媒体行业的创意工作者。V2EX 希望能够成为创意工作者们的生活和事业的一部分。
SSL(Secure Sockets Layer 安全套接层),及其继任者传输层安全(Transport Layer Security,TLS)是为网络通信提供安全及数据完整性的一种安全协议。TLS 与 SSL 在传输层对网络连接进行加密。
C 语言是一门通用计算机编程语言,应用广泛。C 语言的设计目标是提供一种能以简易的方式编译、处理低级存储器、产生少量的机器码以及不需要任何运行环境支持便能运行的编程语言。
Latke 是一款以 JSON 为主的 Java Web 框架。
Kafka 是一种高吞吐量的分布式发布订阅消息系统,它可以处理消费者规模的网站中的所有动作流数据。 这种动作(网页浏览,搜索和其他用户的行动)是现代系统中许多功能的基础。 这些数据通常是由于吞吐量的要求而通过处理日志和日志聚合来解决。
Cloud Foundry 是 VMware 推出的业界第一个开源 PaaS 云平台,它支持多种框架、语言、运行时环境、云平台及应用服务,使开发人员能够在几秒钟内进行应用程序的部署和扩展,无需担心任何基础架构的问题。
ngrok 是一个反向代理,通过在公共的端点和本地运行的 Web 服务器之间建立一个安全的通道。
你比 99% 的人都优秀么?
Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。
Lute 是一款结构化的 Markdown 引擎,支持 Go 和 JavaScript。
TextBundle 文件格式旨在应用程序之间交换 Markdown 或 Fountain 之类的纯文本文件时,提供更无缝的用户体验。