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 |
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 |
/**
* 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 |
/**
* 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 |
/**
* 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 |
/**
* 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;
},
};
}