slate#Decoration TypeScript Examples

The following examples show how to use slate#Decoration. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: options.tsx    From grafana-chinese with Apache License 2.0 6 votes vote down vote up
readonly renderDecoration!: (
    {
      decoration,
      children,
    }: {
      decoration: Decoration;
      children: React.ReactNode;
    },
    editor: Editor,
    next: () => any
  ) => void | React.ReactNode;
Example #2
Source File: options.tsx    From grafana-chinese with Apache License 2.0 6 votes vote down vote up
/**
 * Default rendering for decorations
 */
function defaultRenderDecoration(
  props: { children: React.ReactNode; decoration: Decoration },
  editor: Editor,
  next: () => any
): void | React.ReactNode {
  const { decoration } = props;
  if (decoration.type !== TOKEN_MARK) {
    return next();
  }

  const className = decoration.data.get('className');
  return <span className={className}>{props.children}</span>;
}
Example #3
Source File: index.ts    From grafana-chinese with Apache License 2.0 5 votes vote down vote up
/**
 * Returns the decoration for a node
 */
function decorateNode(opts: Options, block: Block) {
  const grammarName = opts.getSyntax(block);
  const grammar = Prism.languages[grammarName];
  if (!grammar) {
    // Grammar not loaded
    return [];
  }

  // Tokenize the whole block text
  const texts = block.getTexts();
  const blockText = texts.map(text => text && text.getText()).join('\n');
  const tokens = Prism.tokenize(blockText, grammar);

  // The list of decorations to return
  const decorations: Decoration[] = [];
  let textStart = 0;
  let textEnd = 0;

  texts.forEach(text => {
    textEnd = textStart + text!.getText().length;

    let offset = 0;
    function processToken(token: string | Prism.Token, accu?: string | number) {
      if (typeof token === 'string') {
        if (accu) {
          const decoration = createDecoration({
            text: text!,
            textStart,
            textEnd,
            start: offset,
            end: offset + token.length,
            className: `prism-token token ${accu}`,
            block,
          });
          if (decoration) {
            decorations.push(decoration);
          }
        }
        offset += token.length;
      } else {
        accu = `${accu} ${token.type} ${token.alias || ''}`;

        if (typeof token.content === 'string') {
          const decoration = createDecoration({
            text: text!,
            textStart,
            textEnd,
            start: offset,
            end: offset + token.content.length,
            className: `prism-token token ${accu}`,
            block,
          });
          if (decoration) {
            decorations.push(decoration);
          }

          offset += token.content.length;
        } else {
          // When using token.content instead of token.matchedStr, token can be deep
          for (let i = 0; i < token.content.length; i += 1) {
            // @ts-ignore
            processToken(token.content[i], accu);
          }
        }
      }
    }

    tokens.forEach(processToken);
    textStart = textEnd + 1; // account for added `\n`
  });

  return decorations;
}
Example #4
Source File: index.ts    From grafana-chinese with Apache License 2.0 5 votes vote down vote up
/**
 * Return a decoration range for the given text.
 */
function createDecoration({
  text,
  textStart,
  textEnd,
  start,
  end,
  className,
  block,
}: {
  text: Text; // The text being decorated
  textStart: number; // Its start position in the whole text
  textEnd: number; // Its end position in the whole text
  start: number; // The position in the whole text where the token starts
  end: number; // The position in the whole text where the token ends
  className: string; // The prism token classname
  block: Block;
}): Decoration | null {
  if (start >= textEnd || end <= textStart) {
    // Ignore, the token is not in the text
    return null;
  }

  // Shrink to this text boundaries
  start = Math.max(start, textStart);
  end = Math.min(end, textEnd);

  // Now shift offsets to be relative to this text
  start -= textStart;
  end -= textStart;

  const myDec = block.createDecoration({
    object: 'decoration',
    anchor: {
      key: text.key,
      offset: start,
      object: 'point',
    },
    focus: {
      key: text.key,
      offset: end,
      object: 'point',
    },
    type: TOKEN_MARK,
    data: { className },
  });

  return myDec;
}
Example #5
Source File: index.tsx    From grafana-chinese with Apache License 2.0 4 votes vote down vote up
/**
 * Code-highlighting plugin based on Prism and
 * https://github.com/ianstormtaylor/slate/blob/master/examples/code-highlighting/index.js
 *
 * (Adapted to handle nested grammar definitions.)
 */

export default function PrismPlugin({ definition, language }: { definition: any; language: string }) {
  if (definition) {
    // Don't override exising modified definitions
    Prism.languages[language] = Prism.languages[language] || definition;
  }

  return {
    /**
     * Render a Slate mark with appropiate CSS class names
     *
     * @param {Object} props
     * @return {Element}
     */

    renderDecoration(props: any, editor: Editor, next: () => any): JSX.Element {
      const { children, decoration } = props;
      // Only apply spans to marks identified by this plugin
      if (decoration.type !== TOKEN_MARK) {
        return next();
      }
      const className = `token ${decoration.data.get('types')}`;
      return <span className={className}>{children}</span>;
    },

    /**
     * Decorate code blocks with Prism.js highlighting.
     *
     * @param {Node} node
     * @return {Array}
     */

    decorateNode(node: any, editor: Editor, next: () => any): any[] {
      if (node.type !== 'paragraph') {
        return [];
      }

      const texts = node.getTexts().toArray();
      const tstring = texts.map((t: { text: any }) => t.text).join('\n');
      const grammar = Prism.languages[language];
      const tokens = Prism.tokenize(tstring, grammar);
      const decorations: Decoration[] = [];
      let startText = texts.shift();
      let endText = startText;
      let startOffset = 0;
      let endOffset = 0;
      let start = 0;

      function processToken(token: any, acc?: string) {
        // Accumulate token types down the tree
        const types = `${acc || ''} ${token.type || ''} ${token.alias || ''}`;

        // Add mark for token node
        if (typeof token === 'string' || typeof token.content === 'string') {
          startText = endText;
          startOffset = endOffset;

          const content = typeof token === 'string' ? token : token.content;
          const newlines = content.split('\n').length - 1;
          const length = content.length - newlines;
          const end = start + length;

          let available = startText.text.length - startOffset;
          let remaining = length;

          endOffset = startOffset + remaining;

          while (available < remaining) {
            endText = texts.shift();
            remaining = length - available;
            available = endText.text.length;
            endOffset = remaining;
          }

          // Inject marks from up the tree (acc) as well
          if (typeof token !== 'string' || acc) {
            const range = node.createDecoration({
              anchor: {
                key: startText.key,
                offset: startOffset,
              },
              focus: {
                key: endText.key,
                offset: endOffset,
              },
              type: TOKEN_MARK,
              data: { types },
            });

            decorations.push(range);
          }

          start = end;
        } else if (token.content && token.content.length) {
          // Tokens can be nested
          for (const subToken of token.content) {
            processToken(subToken, types);
          }
        }
      }

      // Process top-level tokens
      for (const token of tokens) {
        processToken(token);
      }

      return decorations;
    },
  };
}