精华内容
下载资源
问答
  • 介绍prosemirror是一个用于在Web端构建富文本编辑器工具包,理想内容编辑器可以生成结构化,语义上有意义的文档,但这样做方式很容易让用户理解。ProseMirror试图弥合Markdown文本编辑和经典WYSIWYG(所见即所得...

    介绍

    prosemirror是一个用于在Web端构建富文本编辑器的工具包,理想的内容编辑器可以生成结构化,语义上有意义的文档,但这样做的方式很容易让用户理解。ProseMirror试图弥合Markdown文本编辑和经典WYSIWYG(所见即所得)编辑器之间的差距。它通过实现WYSIWYG风格的编辑界面来实现这一点,该界面比纯HTML更受约束和结构化。你可以自定义编辑器创建的文档的形状和结构,并根据应用程序的需要进行定制。所以还是值得尝试下的!


    70b4ac2a4daf5b082e3d45dadc26542f.gif

    Github

    https://github.com/prosemirror

    相关特性

    • 协同编辑

    ProseMirror具有内置的,可靠的支持,用于协作编辑,其中多个人实时处理同一文档。

    • 可扩展的模式文档模式

    允许使用自定义结构编辑文档,而无需从头开始编写自己的编辑器。

    • 模块化

    模块化架构确保您只加载所需的代码,并可根据需要替换系统的各个部分。

    • 可插拔插件系统

    允许您轻松启用其他功能,并以方便的格式打包您自己的扩展。

    • 功能实用

    强大且不可变的体系结构使ProseMirror可以轻松集成到现代Web应用程序中,并可以自信地实现复杂的行为。

    • Unopinionated

    核心库很小且通用,提供了可以构建非常不同类型的编辑器的基础。

    实例Demo

    • 基本示例
    import {EditorState} from "prosemirror-state"import {EditorView} from "prosemirror-view"import {Schema, DOMParser} from "prosemirror-model"import {schema} from "prosemirror-schema-basic"import {addListNodes} from "prosemirror-schema-list"import {exampleSetup} from "prosemirror-example-setup"// Mix the nodes from prosemirror-schema-list into the basic schema to// create a schema with list support.const mySchema = new Schema({ nodes: addListNodes(schema.spec.nodes, "paragraph block*
    展开全文
  • 1 引言「可视化搭建系统」——从设计到架构,探索前端的领域和意义 这篇文章主要分析了现阶段可视化搭建的几种表现形式和实现原理,并重点介绍了基于富文本的可视化搭建思路,让人耳目一新。基于富文本的可视化搭建...

    1 引言

    「可视化搭建系统」——从设计到架构,探索前端的领域和意义 这篇文章主要分析了现阶段可视化搭建的几种表现形式和实现原理,并重点介绍了基于富文本的可视化搭建思路,让人耳目一新。

    基于富文本的可视化搭建看似很新颖,但其实早就被广泛使用了,任何一个富文本编辑器几乎都有插入表格功能,这就是一个典型插入自定义组件的场景。

    使用过 语雀 的同学应该知道,这个产品的富文本编辑器可以插入各种各样自定义区块,是 “最像搭建” 的富文本编辑器。

    那么积木式搭建和富文本搭建存在哪些差异,除了富文本更倾向于记录静态内容外,还有哪些差异,两者是否可以结合?本文将围绕这两点进行讨论。

    2 精读

    还是先顺着原文谈谈对可视化搭建的理解:

    可视化搭建是通过可视化方式代替开发。前端代码开发主要围绕的是 html + js + css,那么无论是 markdown 语法,还是创建另一套模版语言亦或 JSON 构成的 DSL,都是用一种 dsl + 组件 + css 的方式代替 html + js + css,可视化搭建则更进一步,用 ui 代替了 dsl + 组件,即精简为 ui 操作 + css

    可以看到,这种转换的推演过程存在一定瑕疵,因为每次转换都有部分损耗:

    用 dsl + 组件 代替 html + js。

    如果 dsl 拓展得足够好,理论上可以达到 html 的水平,尤其在垂直业务场景是不需要那么多特殊 html 标签的。

    但用组件代替 js 就有点奇怪了,首先并不是所有 js 逻辑都沉淀在组件里,一定有组件间的联动逻辑是无法通过一个组件 js 完成的,另一方面如果将 js 逻辑寄托在组件代码里,本质上是没有提效的,用源码开发项目与开发搭建平台的组件都是 pro code,更极端一点来说,无论是组件间联动还是整个应用都可以用一个组件来写,那搭建平台就无事可做了,这个组件也成了整个应用,game over。

    为了弥补这块缺憾,低代码能力的呼声越来越高,而低代码能力的核心在于设计是否合理,比如暴露哪些 API 可以覆盖大部分需求?写多少代码合适,如何以最小 API 透出最大弥补组件间缺失的 js 能力?目前来看,以状态数据驱动的低代码是相对优雅的。

    用 ui 操作 代替 dsl + 组件。

    UI 操作并不是标准的,相比直接操作模版或者 JSON DSL,UI 化后就仁者见仁智者见智了,但 UI 化带来的效率提升是巨大的,因为所见即所得是生产力的源泉,从直观的 UI 布局来看,就比维护代码更轻松。但 UI 化也存在两个问题,一个是可能有人觉得不如 markdown 效率高,另一个是功能有丢失。

    对于第一点 UI 操作效率不如 markdown 高,可能很多程序员都崇尚用 markdown 维护文档而不是富文本,原因是觉得程序员维护代码的效率反而比所见即所得高,但那可能是错觉,原因是还没有遇到好用的富文本编辑器,体验过语雀富文本编辑器后,相信大部分程序员都不会再想回头写 markdown。当然语雀富文本战胜 markdown 的原因有很多,我觉得主要两点是吸收并兼容了 markdown 操作习惯,与支持了更多仅 UI 能做到的拓展能力,对 markdown 形成降维打击。

    第二点功能丢失很好理解,markdown 有一套标准语法和解析器可以验证,但 UI 操作并没有标准化,也没有独立验证系统,如果无法回退到源码模式,UI 没有实现的功能就做不到。

    回到富文本搭建上,其实富文本搭建和普通网页构建并没有本质区别。html 是超文本标记语言,富文本是跨平台文档格式,从逻辑上这两个格式是可以互转的,只要富文本规则作出足够多的拓展,就可以大致覆盖 html 的能力。

    但富文本搭建有着显著的特征,就是光标。

    积木式搭建和富文本搭建的区别

    富文本以文本为中心,因此编辑文字的光标会常驻,编辑的核心逻辑是排版文字,并考虑如何在文字周围添加一些自定义区块。

    有了光标后,圈选也非常重要,因为大家编辑文字时有一种很自然的想法是,任何文字圈选后复制,可以粘贴到任何地方,那么所有插入到富文本中的自定义组件也要支持被圈选,被复制。

    实际上富文本内插入自定义区块也可以转换为积木式搭建方案解决,比如下面的场景:

    文本 A
    图表 B
    文本 C

    我们在文本 A 与 文本 C 之间插入图表 B,也可以理解为拖拽了三个组件:文本组件 A + 图表组件 B + 文本组件 C,然后分别编辑这三个组件,微调样式后可以达到与富文本一样的编辑效果,甚至加上自由布局后,在布局能力上会超越富文本。

    虽然功能层面上富文本略有输给积木式搭建,但富文本在编辑体验上是胜出的,对于文字较多的场景,我们还是会选择富文本方式编辑而不是积木式搭建拖拽 N 个文本组件。

    所以微软 OneNote 也吸取了这个经验,毕竟笔记本主要还是记录文字,因此还是采用富文本的编辑模式,但创造性的加入了一个个独立区块,点击任何区域都会创造一个区块,整个文档可以由一个区块构成,也可以是多个区块组合而成,这样对于连贯性的文字场景可以采用一个富文本区块,对于自定义区块较多,比如大部分是图片和表格的,还可以回到积木式搭建的体验。由于 OneNote 采用绝对定位模拟流式布局的思路,当区块重叠时还可以自动挤压底部区块,因此多区块模式下编辑体验还是相对顺畅的。

    可以看出来这是一种结合的尝试,从前端角度来看,富文本本质上是对一个 div 进行 contenteditable 申明,那么一个应用可以整体是 contenteditable 的,也可以局部几个区块是,这种代码层面的自由度体现在搭建上就是积木式搭建可以与富文本搭建自由结合。

    积木式搭建与富文本搭建如何结合

    对于积木式搭建来说,富文本只是其中一个组件,在不考虑有富文本组件时是完全没有富文本能力的。比如一个搭建平台只提供了几个图表和基础控件,你是不可能在其基础上使用富文本能力的,甚至连写静态文本都做不到。

    所以富文本只是搭建中一个组件,就像 contenteditable 也只能依附于一个标签,整个网页还是由标签组成的。但对于一个提供了富文本组件的积木式搭建系统来说,文字与控件混排又是一个痛点,毕竟要以一个个区块组件的方式去拖拽文本节点,成本比富文本模式大得多。

    所以理想情况是富文本与整个搭建系统使用同一套 DSL 描述结构,富文本只是在布局上有所简化,简化为简单的平铺模式即可,但因为 DSL 描述打通,富文本也可以描述使用搭建提供的任意组件嵌套在内,所以只要用户愿意,可以将富文本组件拉到最大,整个页面都基于富文本模式去搭建,这就变成了富文本搭建,也可以将富文本缩小,将普通控件以积木方式拖拽到画布中,走积木式搭建路线。

    用代码方式描述积木式搭建:

    <bar-chart />
    <div>
      <p>header</p>
      <line-chart />
      <p>footer</p>
    </div>
    

    上述模式需要拖拽 bar-chartdivpline-chartp 共 5 个组件。富文本模式则类似下面的结构:

    <bar-chart />
    <div contenteditable>
      <p>header</p>
      <line-chart />
      <p>footer</p>
    </div>
    

    只要拖拽 bar-chartdiv 两个组件即可,div 内部的文字通过光标输入,line-chart 通过富文本某个按钮或者键盘快捷键添加。

    可以看到虽然操作方式不同,但本质上描述协议并没有本质区别,我们理论上可以将任何容器标签切换为富文本模式。

    3 总结

    富文本是一种重要的交互模式,可以基于富文本模式做搭建,也可以在搭建系统中嵌入富文本组件,甚至还可以追求搭建与富文本的结合。

    富文本组件既可以是搭建系统中一个组件,又可以在内部承载搭建系统的所有组件,做到这一步才算是真正发挥出富文本的潜力。

    讨论地址是:精读《可视化搭建思考 - 富文本搭建》· Issue #262 · dt-fe/weekly

    如果你想参与讨论,请 点击这里,每周都有新的主题,周末或周一发布。前端精读 - 帮你筛选靠谱的内容。

    关注 前端精读微信公众号

    7e49b4378180029bce5cf0cac0035519.png
    版权声明:自由转载-非商用-非衍生-保持署名(创意共享 3.0 许可证
    展开全文
  • 富文本传参时候,总是莫名其妙丢失变成 ‘<p style=’ ,究竟是为什么呢 欢迎使用Markdown编辑器 你好! 这是你第一次使用 Markdown编辑器 所展示欢迎页。如果你想学习如何使用Markdown编辑器, 可以仔细阅读这...

    本次使用的富文本插件是百度的ueditor。

    经过一天的折腾,才明白当你原样将富文本的内容通过ajax的当成json传递出去的时候,
    因为引号的关系会导致截取,本来<p style="color:red;"> 因为是字符串所以传递的时候默认在最前面和最尾端加了",
    导致后台接收到的字符串变成<p style= ,一开始傻兮兮的用replace正则匹配将富文本里的" 都变成' ,但实际上你不能保证所有情况都被你匹配到,最后使用base64加密,后台解密的方法,终于成功。

    jquery.base64.js

    /*
     *  base64.js
     *
     *  Licensed under the BSD 3-Clause License.
     *    http://opensource.org/licenses/BSD-3-Clause
     *
     *  References:
     *    http://en.wikipedia.org/wiki/Base64
     */
    ;(function (global, factory) {
        typeof exports === 'object' && typeof module !== 'undefined'
            ? module.exports = factory(global)
            : typeof define === 'function' && define.amd
            ? define(factory) : factory(global)
    }((
        typeof self !== 'undefined' ? self
            : typeof window !== 'undefined' ? window
            : typeof global !== 'undefined' ? global
                : this
    ), function(global) {
        'use strict';
        // existing version for noConflict()
        global = global || {};
        var _Base64 = global.Base64;
        var version = "2.5.1";
        // if node.js and NOT React Native, we use Buffer
        var buffer;
        if (typeof module !== 'undefined' && module.exports) {
            try {
                buffer = eval("require('buffer').Buffer");
            } catch (err) {
                buffer = undefined;
            }
        }
        // constants
        var b64chars
            = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
        var b64tab = function(bin) {
            var t = {};
            for (var i = 0, l = bin.length; i < l; i++) t[bin.charAt(i)] = i;
            return t;
        }(b64chars);
        var fromCharCode = String.fromCharCode;
        // encoder stuff
        var cb_utob = function(c) {
            if (c.length < 2) {
                var cc = c.charCodeAt(0);
                return cc < 0x80 ? c
                    : cc < 0x800 ? (fromCharCode(0xc0 | (cc >>> 6))
                        + fromCharCode(0x80 | (cc & 0x3f)))
                        : (fromCharCode(0xe0 | ((cc >>> 12) & 0x0f))
                            + fromCharCode(0x80 | ((cc >>>  6) & 0x3f))
                            + fromCharCode(0x80 | ( cc         & 0x3f)));
            } else {
                var cc = 0x10000
                    + (c.charCodeAt(0) - 0xD800) * 0x400
                    + (c.charCodeAt(1) - 0xDC00);
                return (fromCharCode(0xf0 | ((cc >>> 18) & 0x07))
                    + fromCharCode(0x80 | ((cc >>> 12) & 0x3f))
                    + fromCharCode(0x80 | ((cc >>>  6) & 0x3f))
                    + fromCharCode(0x80 | ( cc         & 0x3f)));
            }
        };
        var re_utob = /[\uD800-\uDBFF][\uDC00-\uDFFFF]|[^\x00-\x7F]/g;
        var utob = function(u) {
            return u.replace(re_utob, cb_utob);
        };
        var cb_encode = function(ccc) {
            var padlen = [0, 2, 1][ccc.length % 3],
                ord = ccc.charCodeAt(0) << 16
                    | ((ccc.length > 1 ? ccc.charCodeAt(1) : 0) << 8)
                    | ((ccc.length > 2 ? ccc.charCodeAt(2) : 0)),
                chars = [
                    b64chars.charAt( ord >>> 18),
                    b64chars.charAt((ord >>> 12) & 63),
                    padlen >= 2 ? '=' : b64chars.charAt((ord >>> 6) & 63),
                    padlen >= 1 ? '=' : b64chars.charAt(ord & 63)
                ];
            return chars.join('');
        };
        var btoa = global.btoa ? function(b) {
            return global.btoa(b);
        } : function(b) {
            return b.replace(/[\s\S]{1,3}/g, cb_encode);
        };
        var _encode = buffer ?
            buffer.from && Uint8Array && buffer.from !== Uint8Array.from
                ? function (u) {
                    return (u.constructor === buffer.constructor ? u : buffer.from(u))
                        .toString('base64')
                }
                :  function (u) {
                    return (u.constructor === buffer.constructor ? u : new  buffer(u))
                        .toString('base64')
                }
            : function (u) { return btoa(utob(u)) }
        ;
        var encode = function(u, urisafe) {
            return !urisafe
                ? _encode(String(u))
                : _encode(String(u)).replace(/[+\/]/g, function(m0) {
                    return m0 == '+' ? '-' : '_';
                }).replace(/=/g, '');
        };
        var encodeURI = function(u) { return encode(u, true) };
        // decoder stuff
        var re_btou = new RegExp([
            '[\xC0-\xDF][\x80-\xBF]',
            '[\xE0-\xEF][\x80-\xBF]{2}',
            '[\xF0-\xF7][\x80-\xBF]{3}'
        ].join('|'), 'g');
        var cb_btou = function(cccc) {
            switch(cccc.length) {
                case 4:
                    var cp = ((0x07 & cccc.charCodeAt(0)) << 18)
                        |    ((0x3f & cccc.charCodeAt(1)) << 12)
                        |    ((0x3f & cccc.charCodeAt(2)) <<  6)
                        |     (0x3f & cccc.charCodeAt(3)),
                        offset = cp - 0x10000;
                    return (fromCharCode((offset  >>> 10) + 0xD800)
                        + fromCharCode((offset & 0x3FF) + 0xDC00));
                case 3:
                    return fromCharCode(
                        ((0x0f & cccc.charCodeAt(0)) << 12)
                        | ((0x3f & cccc.charCodeAt(1)) << 6)
                        |  (0x3f & cccc.charCodeAt(2))
                    );
                default:
                    return  fromCharCode(
                        ((0x1f & cccc.charCodeAt(0)) << 6)
                        |  (0x3f & cccc.charCodeAt(1))
                    );
            }
        };
        var btou = function(b) {
            return b.replace(re_btou, cb_btou);
        };
        var cb_decode = function(cccc) {
            var len = cccc.length,
                padlen = len % 4,
                n = (len > 0 ? b64tab[cccc.charAt(0)] << 18 : 0)
                    | (len > 1 ? b64tab[cccc.charAt(1)] << 12 : 0)
                    | (len > 2 ? b64tab[cccc.charAt(2)] <<  6 : 0)
                    | (len > 3 ? b64tab[cccc.charAt(3)]       : 0),
                chars = [
                    fromCharCode( n >>> 16),
                    fromCharCode((n >>>  8) & 0xff),
                    fromCharCode( n         & 0xff)
                ];
            chars.length -= [0, 0, 2, 1][padlen];
            return chars.join('');
        };
        var _atob = global.atob ? function(a) {
            return global.atob(a);
        } : function(a){
            return a.replace(/\S{1,4}/g, cb_decode);
        };
        var atob = function(a) {
            return _atob(String(a).replace(/[^A-Za-z0-9\+\/]/g, ''));
        };
        var _decode = buffer ?
            buffer.from && Uint8Array && buffer.from !== Uint8Array.from
                ? function(a) {
                    return (a.constructor === buffer.constructor
                        ? a : buffer.from(a, 'base64')).toString();
                }
                : function(a) {
                    return (a.constructor === buffer.constructor
                        ? a : new buffer(a, 'base64')).toString();
                }
            : function(a) { return btou(_atob(a)) };
        var decode = function(a){
            return _decode(
                String(a).replace(/[-_]/g, function(m0) { return m0 == '-' ? '+' : '/' })
                    .replace(/[^A-Za-z0-9\+\/]/g, '')
            );
        };
        var noConflict = function() {
            var Base64 = global.Base64;
            global.Base64 = _Base64;
            return Base64;
        };
        // export Base64
        global.Base64 = {
            VERSION: version,
            atob: atob,
            btoa: btoa,
            fromBase64: decode,
            toBase64: encode,
            utob: utob,
            encode: encode,
            encodeURI: encodeURI,
            btou: btou,
            decode: decode,
            noConflict: noConflict,
            __buffer__: buffer
        };
        // if ES5 is available, make Base64.extendString() available
        if (typeof Object.defineProperty === 'function') {
            var noEnum = function(v){
                return {value:v,enumerable:false,writable:true,configurable:true};
            };
            global.Base64.extendString = function () {
                Object.defineProperty(
                    String.prototype, 'fromBase64', noEnum(function () {
                        return decode(this)
                    }));
                Object.defineProperty(
                    String.prototype, 'toBase64', noEnum(function (urisafe) {
                        return encode(this, urisafe)
                    }));
                Object.defineProperty(
                    String.prototype, 'toBase64URI', noEnum(function () {
                        return encode(this, true)
                    }));
            };
        }
        //
        // export Base64 to the namespace
        //
        if (global['Meteor']) { // Meteor.js
            Base64 = global.Base64;
        }
        // module.exports and AMD are mutually exclusive.
        // module.exports has precedence.
        if (typeof module !== 'undefined' && module.exports) {
            module.exports.Base64 = global.Base64;
        }
        else if (typeof define === 'function' && define.amd) {
            // AMD. Register as an anonymous module.
            define([], function(){ return global.Base64 });
        }
        // that's it!
        return {Base64: global.Base64}
    }));
    

    后台解码不需要引入jar包,jdk1.8自带:

      public String decodeBase64(String str){
            if(StringUtils.isEmpty(str)){
                return null;
            }
            byte[] bytes = Base64.getDecoder().decode(str);
            try {
                return new String(bytes, "UTF-8");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            return null;
        }
    

    在自己的逻辑代码里判断富文本内容是否为空,

    @PostMapping("/add")
        public Response addInfomation(ShareInfo shareInfo, @RequestParam("file") MultipartFile[] file) throws IOException {
    
            if(!file[0].isEmpty()){
                FileUtils.saveFile(file[0],filePath+file[0].getOriginalFilename());
                shareInfo.setFilename(file[0].getOriginalFilename());
            }else if(shareInfo!=null&&shareInfo.getId()!=null){
                ShareInfo resShare=shareInfoService.getById(shareInfo.getId());
                if(resShare!=null&&StringUtils.isNotEmpty(resShare.getFilename())){
                    shareInfo.setFilename(resShare.getFilename());
                }
            }
            //判断是否为空,如果有值 BASE64解码
            if(StringUtils.isNotEmpty(shareInfo.getChineseContent())){
                shareInfo.setChineseContent(decodeBase64(shareInfo.getChineseContent()));
            }
            if(StringUtils.isNotEmpty(shareInfo.getEnglishContent())){
                shareInfo.setEnglishContent(decodeBase64(shareInfo.getEnglishContent()));
            }
            if(shareInfo.getId()==0){
                shareInfo.setCreateTime(new Date());
                shareInfo.setDownloadTimes(0);
                shareInfoService.add(shareInfo);
            }else{
                System.out.println("shareInfo:"+shareInfo.getFilename());
                shareInfoService.updateById(shareInfo);
            }
            return Response.success(shareInfo);
        }
    

    最后就可以啦。

    展开全文
  • 2,加入对富文本的支持; 3,富文本他终究是文本,只是串联的入口和形式不一样。于是封装富文本支持在UILabel层,以分类的形式,减少代码入侵; #import“ UILabel + RichText.h” 4,UIButton里面的titleLabel是...
  • 看了一下市面上没啥人发布配置富文本编辑器文章 有些都是几年前 已经停止维护百度富文本意义 所以今天早上特意进去配置了一下 Csdn用也是wangEditor富文本编辑器哦~~ 使用及其简单 不过几行代码 ...

    看了一下市面上没啥人发布配置富文本编辑器的文章 有些的都是几年前的 已经停止维护的百度富文本 没意义 所以今天早上特意进去配置了一下

    Csdn用的也是wangEditor富文本编辑器哦~~

    使用及其简单 不过几行代码

    发布界面

    文章显示界面

     

     

    先自行在页面中配置富文本编辑器 如果都不会使用它 那么下面就不建议在看了

     

     

     

    ###############################################################################################################################################################################################################################################################################################################

     

    生成好了富文本编辑器后

     

    在ajax加上content 把富文本里面的内容 转成html标签

    然后你可以consolog.log(req.body)

    看看数据是否正确

    正确后 你就可以存到数据库了

     

    如果有时候无法获取到富文本的内容 可以在form里面多加上一个input框 你会发现富文本的内容会滑入input框中

    展开全文
  • 今天我在使用django-tinymce给后台管理页面添加富文本编辑器时,在浏览器测试无法显示。 一开始很懵逼,搞不清楚到底是哪里出问题了,都没报错,想找找哪里有问题也无从下手。 然后偶然间看到了控制台记录,发现...
  • 1 引言「可视化搭建系统」——从设计到架构,探索前端的领域和意义 这篇文章主要分析了现阶段可视化搭建的几种表现形式和实现原理,并重点介绍了基于富文本的可视化搭建思路,让人耳目一新。基于富...
  • UEditor富文本编辑器 1、下载ueditor         进入ueditor下载地址下载ueditor。一共需要下载俩个压缩包,一个是完整源码包,另外一个是jsp版本【UTF-8】。  &...
  • 的意义是什么?我们可以用UILabel来写文字,但两者不是一码事,CATextLayer的渲染速度比UILabel快的多,而UILabel的精髓就是用图层代理把字符串用Core Graphics写入如层,CATextLayer则不用,它以涂层的形式几乎...
  • 上期,我们在《「微信同声传译」小程序插件:快速实现语音转文字、文本翻译、语音合成等能力》一文中介绍了「微信同声传译」小程序插件的意义、作用...今天我们为大家推荐的是一款富文本渲染插件「wxParser」,目前 ...
  • 0x01前言本文献给永远Avicii,严格意义上我不算是一个reaver。但并不妨碍我深深喜欢你作品,它们陪伴着我度过了无数个编程夜晚,十分感谢。今天不同人用不同方式怀念你,我不会作曲,也不敢纹身。能给你...
  • 上期,我们在《「微信同声传译」小程序插件:快速实现语音转文字、文本翻译、语音合成等能力》一文中介绍了「微信同声传译」小程序插件的意义、作用以及应用。而在此之前,我们还介绍过「腾讯地图」、「腾讯视频」、...
  • ​移动互联网时代,手机不再仅仅是通话工具,更是完整意义通讯工具。这个通讯定义,可以指定为社交、办公、购物、出行等等交换讯息和体验过程,尤其是到了5g时代,万物互联,讯息交换效率大大提高,于是,...
  • 但这样没有意义的我还是想要写些什么。愿意听这样苍白日记吗?那么请进。 资料夹索引 omcdiary_sourcefiles :内容是苍白球日志原始档,以markdown格式纪录,每日一个档案。 omcdiary_export :苍白球日志按月...
  • Web 应用中撤销与重做

    千次阅读 2019-06-23 18:34:10
    Web 应用中撤销与重做 撤销(Undo)与重做(Redo)是绝大部分应用中都有功能,它...Web 应用中撤销与重做,很容易想到富文本编辑器,但本文不特指富文本编辑器,而是更具有普遍意义的 Web 交互应用。只要有...
  • 迄今为止,正儿八经上线了真正意义程序,但是这个小程序却着实不小。 之所以不小,是因为这个类似于社区小程序,已经做了大部分都有功能了 举例说明,具体一些功能点: 1、帖子列表页面:会有功能:...
  • 【需求】服务端 返回富文本形式(实则不是真正意义html文本)图片.png【工具类】/*** @Author Lee* @Time 2018/9/18* @Theme*/public class ...public static final b...
  • 所有的富文本编辑器都是这样富文本编辑器把每一个双字节字符(比如汉字)都当作一个单词,把连续单字节字符串当成一个单词。单词与单词之间是可以自动换行,单词内部不能自动换行。对于双字节字符所代表...
  • 早些个月业务中需要实现editable 功能,于是...然后就开始吭哧吭哧做轮子了,实现了大部分功能,然后富文本部分用quill 。跑了一段时间,发现很多小问题。 上周痛定思痛决定还是依赖于x-editable,确保稳定性。 ...
  • 我们遇到很多实际问题,愈发感觉到这是一个非常有深度前端技术领域,所以我们将新版编辑器技术选型、架构和部分实现细节拿出来分享给大家,希望对大家开发富文本编辑器、做复杂系统架构设计有一定参考意义。...
  • UEditor API

    2015-12-09 13:18:32
    UEditor是百度开发的富文本编辑器,提供强大在线编辑功能.由于官方文档都是在线,所以特意制作了离线版本API API介绍了所有函数意义
  • tp5 html与word相互转换

    2020-11-19 17:21:55
    最近遇到了一个需求,需要将富文本编辑器内容转存到云服务器中,富文本编辑器保存其实是html字符串,然而存云服务器中就需要用到文件形式数据。 所以我就打算将html转存word形式存储。 PHP有自带PHPword包,...
  •  据谷歌自己介绍,Wave可以让用户使用格式化文本、图片、视频、地图等内容与其他用户实时协作和沟通。 从字面意义来说,这本来应该是一项不错业务。 但是这种技术并不能吸引用户注意,大多数社交网站...
  • Flutter组件的分类 文字类型 容器类型 辅助提示类型 列表类型 系统主题风格类型 ...RichText组件,一个富文本, 可以描述丰富的字体样式; 案例如下:(Text的所有属性及相关的意义) /// color 颜色 /// ...
  • 请教一个问题,看了一个程序,将富文本提交上来程序做了转义htmlspecialchars, 然后进数据库时候做了如下处理$content = htmlspecialchars_decode($_GPC["content"]);,那之前htmlspecialchars有何意义,不会...
  • 在做自己项目时候,再选择富文本编辑器时候小小纠结了一下,之前项目大多使用是百度Ueditor,但是自己练习项目上面再使用这个那么练习就变得毫无意义,所以选择了CKeditor编辑器(文档纯英文所以不是...
  • myBase 是一款用于分类管理自由格式资料小型个人数据库软件, 有助于个人用户在( Linux/MacOSX/Windows )桌面... 与传统意义数据库软件不同,myBase 通过内置的富文本编辑器接受图文信息输入,并按树形 列...
  • Mybase7绿色版

    2015-12-06 19:24:20
    与传统意义数据库软件不同,myBase 通过内置的富文本编辑器接受图文信息输入,并按树形大纲分门别类保存, 同时接受任意磁盘文件作为树形大纲条目附件。 myBase 提供了更好方式使知识/信息捕获、编辑、...
  • 我们是钉钉文档协同团队,我们在做一些很有意义的事情,其中之一就是自研文字编辑器。为了把自研文字编辑器做好,我们调研了开源社区各种优秀编辑器,Slate.js ...TOC一行代码实现富文本编辑器拯救 ContentEdita...

空空如也

空空如也

1 2 3
收藏数 51
精华内容 20
关键字:

富文本的意义