【问题标题】:Draftjs replaceText conserving styleDraftjs replaceText 保存样式
【发布时间】:2020-05-12 01:12:16
【问题描述】:

我正在使用 Draftjs 和 Draft-js-plugins-editor,我正在使用两个插件:draft-js-mathjax-plugindraft-js-mention-plugin

当用户使用“@”提及元素时,我想稍后用值替换所有提及。例如,“你有@A”将被“你有 300”替换。我找到并使用了Draft-js building search and replace functionality,它有很好的文档和解释。 我改变了一点函数以使它们更全球化:

function findWithRegex (regex, contentBlock, callback) {
    const text = contentBlock.getText();
    let matchArr, start, end;
    while ((matchArr = regex.exec(text)) !== null) {
        start = matchArr.index;
        end = start + matchArr[0].length;
        callback(start, end);
    }
}

function Replace (editorState,search,replace) {
    const regex = new RegExp(search, 'g');
    const selectionsToReplace = [];
    const blockMap = editorState.getCurrentContent().getBlockMap();

    blockMap.forEach((contentBlock,i) => (
        findWithRegex(regex, contentBlock, (start, end) => {
            const blockKey = contentBlock.getKey();
            const blockSelection = SelectionState
                .createEmpty(blockKey)
                .merge({
                    anchorOffset: start,
                    focusOffset: end,
                });

            selectionsToReplace.push(blockSelection)
        })
    ));

    let contentState = editorState.getCurrentContent();

    selectionsToReplace.forEach((selectionState,i) => {
        contentState = Modifier.replaceText(
            contentState,
            selectionState,
            replace
        )
    });

    return EditorState.push(
        editorState,
        contentState,
    );
}

单独运行效果很好,但是当我使用 mathjax-plugin 进行数学表达式,然后使用 Replace 函数时,所有数学内容都消失了......

我知道在replaceText 函数的定义中我们可以插入inlineStyle,但我没有找到任何“提取”样式的方法。 我尝试使用getEntityAtfindStyleRangesfindEntityRanges 和其他功能,但我无法让它们做我想做的事......

这是我的反应组件:

import React, { Component } from 'react';
import {EditorState, SelectionState, Modifier, convertFromRaw, convertToRaw} from 'draft-js';
import Editor from 'draft-js-plugins-editor';

import createMathjaxPlugin from 'draft-js-mathjax-plugin';
import createMentionPlugin, { defaultSuggestionsFilter } from 'draft-js-mention-plugin';
export default class EditorRplace extends Component {

    constructor(props) {
        super(props);

        this.mentionPlugin = createMentionPlugin({
            entityMutability: 'IMMUTABLE',
            mentionPrefix: '@'
        });

        //We recover the data from the props
        let JSONContentState = JSON.parse(this.props.instruction);
        let inputs = this.props.inputs;
        let values = this.props.values;

        this.state = {
            editorState: EditorState.createWithContent(convertFromRaw(JSONContentState)),
            plugins:[this.mentionPlugin,createMathjaxPlugin({setReadOnly:this.props.isReadOnly})],
            trigger:this.props.trigger,
            inputs:inputs,
            values:values,
        };
    }

    componentDidMount() {
        this.setState({
            editorState:onReplace(this.state.editorState,'A','B')
        })
    }

    onChange = (editorState) => {
        this.setState({
            editorState:editorState,
        })
    };

    render() {
        return (
            <div>
                <Editor
                    readOnly={true}
                    editorState={this.state.editorState}
                    plugins={this.state.plugins}
                    onChange={this.onChange}
                />
            </div>
        );
    }
}

如果我没有使用替换功能,所有内容都会按预期显示,使用正确样式的提及和数学表达式。

【问题讨论】:

    标签: javascript reactjs draftjs draft-js-plugins


    【解决方案1】:

    我找不到“合适”的解决方案,然后我直接在原始内容状态上进行手动编辑。

    首先我对所有进行迭代,然后对这个块中的每个实体进行迭代。我正在手动替换 block[i].text 中的文本。然后我必须比较前一个元素和新元素的长度以更改下一个元素的偏移量。

    我正在使用两个数组,一个称为输入,一个称为值。输入必须按长度排序(从高到低),因为如果我们有 @AB 和 @A 并且我们以 @A 开头,我们可能会发生冲突。

    然后输入数组中的每个元素都必须有一个“索引”值,该值链接到值数组以正确替换为正确的值。

    let instruction = {"blocks":[{"key":"ar0s","text":"Multiply @alpha by @beta  \t\t ","type":"unstyled","depth":0,"inlineStyleRanges":[],"entityRanges":[{"offset":9,"length":6,"key":0},{"offset":19,"length":5,"key":1},{"offset":26,"length":2,"key":2}],"data":{}}],"entityMap":{"0":{"type":"mention","mutability":"IMMUTABLE","data":{"mention":{"index":0,"type":"Integer","name":"alpha","min":0,"max":10}}},"1":{"type":"mention","mutability":"IMMUTABLE","data":{"mention":{"index":1,"type":"Integer","name":"beta","min":0,"max":10}}},"2":{"type":"INLINETEX","mutability":"IMMUTABLE","data":{"teX":"\\frac{@alpha}{@beta}","displaystyle":false}}}}
    
    let inputs = [{index:0,name:'alpha'},{index:1,name:'beta'}];
    let values = [1,123456];
    
    replace(instruction,inputs,values);
    
    function replace(contentState,inputs,values)
    {
        instruction.blocks.forEach((block,i) => {
    
        console.log('Block['+i+'] "' + block.text + '"');
    
        let offsetChange = 0;
    
        block.entityRanges.forEach((entity) => {
    
          entity.offset+=offsetChange;
          console.log('\n[Entity] offsetChange:' + offsetChange);
    
          inputs.forEach(input => {
    
          if(instruction.entityMap[entity.key].type === 'mention') {
              if(input.name === instruction.entityMap[entity.key].data.mention.name)
              {
    
                console.log('replace ' + entity.offset + ' ' + entity.length + ' ' + block.text.toString().substr(entity.offset,entity.length));
    
                block.text = block.text.toString().replace(block.text.toString().substr(entity.offset,entity.length),values[input.index])
    
                let newLength = values[input.index].toString().length
                console.log('newLength:' +newLength);
    
                offsetChange+= (newLength-entity.length);
                entity.length=newLength;
    
    
              }
          }
    
          });
    
        });
    
    
      });
    
      return instruction;
    }
    

    所以它可以满足我的需要。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-08-19
      • 1970-01-01
      • 2016-06-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多