mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
This reverts commit 601853fc84.
This commit is contained in:
@@ -149,7 +149,7 @@ export const getWebpackConfig: WebpackConfigurationGetter = options => {
|
||||
'emotion',
|
||||
'prismjs',
|
||||
'slate-plain-serializer',
|
||||
'@grafana/slate-react',
|
||||
'slate-react',
|
||||
'react',
|
||||
'react-dom',
|
||||
'react-redux',
|
||||
|
||||
@@ -26,12 +26,10 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@grafana/data": "^6.4.0-alpha",
|
||||
"@grafana/slate-react": "0.22.9-grafana",
|
||||
"@torkelo/react-select": "2.1.1",
|
||||
"@types/react-color": "2.17.0",
|
||||
"classnames": "2.2.6",
|
||||
"d3": "5.9.1",
|
||||
"immutable": "3.8.2",
|
||||
"jquery": "3.4.1",
|
||||
"lodash": "4.17.15",
|
||||
"moment": "2.24.0",
|
||||
@@ -47,7 +45,6 @@
|
||||
"react-storybook-addon-props-combinations": "1.1.0",
|
||||
"react-transition-group": "2.6.1",
|
||||
"react-virtualized": "9.21.0",
|
||||
"slate": "0.47.8",
|
||||
"tinycolor2": "1.4.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -68,8 +65,6 @@
|
||||
"@types/react-custom-scrollbars": "4.0.5",
|
||||
"@types/react-test-renderer": "16.8.1",
|
||||
"@types/react-transition-group": "2.0.16",
|
||||
"@types/slate": "0.47.1",
|
||||
"@types/slate-react": "0.22.5",
|
||||
"@types/storybook__addon-actions": "3.4.2",
|
||||
"@types/storybook__addon-info": "4.1.1",
|
||||
"@types/storybook__addon-knobs": "4.0.4",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import resolve from 'rollup-plugin-node-resolve';
|
||||
import commonjs from 'rollup-plugin-commonjs';
|
||||
// import sourceMaps from 'rollup-plugin-sourcemaps';
|
||||
import sourceMaps from 'rollup-plugin-sourcemaps';
|
||||
import { terser } from 'rollup-plugin-terser';
|
||||
|
||||
const pkg = require('./package.json');
|
||||
@@ -47,20 +47,19 @@ const buildCjsPackage = ({ env }) => {
|
||||
],
|
||||
'../../node_modules/react-color/lib/components/common': ['Saturation', 'Hue', 'Alpha'],
|
||||
'../../node_modules/immutable/dist/immutable.js': [
|
||||
'Record',
|
||||
'Set',
|
||||
'Map',
|
||||
'List',
|
||||
'OrderedSet',
|
||||
'is',
|
||||
'Stack',
|
||||
'Record',
|
||||
],
|
||||
'node_modules/immutable/dist/immutable.js': ['Record', 'Set', 'Map', 'List', 'OrderedSet', 'is', 'Stack'],
|
||||
'../../node_modules/esrever/esrever.js': ['reverse'],
|
||||
},
|
||||
}),
|
||||
resolve(),
|
||||
// sourceMaps(),
|
||||
sourceMaps(),
|
||||
env === 'production' && terser(),
|
||||
],
|
||||
};
|
||||
|
||||
@@ -1,16 +1,19 @@
|
||||
import React, { useState, useMemo, useCallback, useContext } from 'react';
|
||||
import { VariableSuggestion, VariableOrigin, DataLinkSuggestions } from './DataLinkSuggestions';
|
||||
import { makeValue, ThemeContext, DataLinkBuiltInVars, SCHEMA } from '../../index';
|
||||
import { makeValue, ThemeContext, DataLinkBuiltInVars } from '../../index';
|
||||
import { SelectionReference } from './SelectionReference';
|
||||
import { Portal } from '../index';
|
||||
import { Editor } from '@grafana/slate-react';
|
||||
import { Value, Editor as CoreEditor } from 'slate';
|
||||
// @ts-ignore
|
||||
import { Editor } from 'slate-react';
|
||||
// @ts-ignore
|
||||
import { Value, Change, Document } from 'slate';
|
||||
// @ts-ignore
|
||||
import Plain from 'slate-plain-serializer';
|
||||
import { Popper as ReactPopper } from 'react-popper';
|
||||
import useDebounce from 'react-use/lib/useDebounce';
|
||||
import { css, cx } from 'emotion';
|
||||
|
||||
import { SlatePrism } from '../../slate-plugins';
|
||||
// @ts-ignore
|
||||
import PluginPrism from 'slate-prism';
|
||||
|
||||
interface DataLinkInputProps {
|
||||
value: string;
|
||||
@@ -19,7 +22,7 @@ interface DataLinkInputProps {
|
||||
}
|
||||
|
||||
const plugins = [
|
||||
SlatePrism({
|
||||
PluginPrism({
|
||||
onlyIn: (node: any) => node.type === 'code_block',
|
||||
getSyntax: () => 'links',
|
||||
}),
|
||||
@@ -76,28 +79,27 @@ export const DataLinkInput: React.FC<DataLinkInputProps> = ({ value, onChange, s
|
||||
|
||||
useDebounce(updateUsedSuggestions, 250, [linkUrl]);
|
||||
|
||||
const onKeyDown = (event: Event, editor: CoreEditor, next: Function) => {
|
||||
const keyboardEvent = event as KeyboardEvent;
|
||||
if (keyboardEvent.key === 'Backspace') {
|
||||
const onKeyDown = (event: KeyboardEvent) => {
|
||||
if (event.key === 'Backspace' || event.key === 'Escape') {
|
||||
setShowingSuggestions(false);
|
||||
setSuggestionsIndex(0);
|
||||
}
|
||||
|
||||
if (keyboardEvent.key === 'Enter') {
|
||||
if (event.key === 'Enter') {
|
||||
if (showingSuggestions) {
|
||||
onVariableSelect(currentSuggestions[suggestionsIndex]);
|
||||
}
|
||||
}
|
||||
|
||||
if (showingSuggestions) {
|
||||
if (keyboardEvent.key === 'ArrowDown') {
|
||||
keyboardEvent.preventDefault();
|
||||
if (event.key === 'ArrowDown') {
|
||||
event.preventDefault();
|
||||
setSuggestionsIndex(index => {
|
||||
return (index + 1) % currentSuggestions.length;
|
||||
});
|
||||
}
|
||||
if (keyboardEvent.key === 'ArrowUp') {
|
||||
keyboardEvent.preventDefault();
|
||||
if (event.key === 'ArrowUp') {
|
||||
event.preventDefault();
|
||||
setSuggestionsIndex(index => {
|
||||
const nextIndex = index - 1 < 0 ? currentSuggestions.length - 1 : (index - 1) % currentSuggestions.length;
|
||||
return nextIndex;
|
||||
@@ -105,24 +107,21 @@ export const DataLinkInput: React.FC<DataLinkInputProps> = ({ value, onChange, s
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
keyboardEvent.key === '?' ||
|
||||
keyboardEvent.key === '&' ||
|
||||
keyboardEvent.key === '$' ||
|
||||
(keyboardEvent.keyCode === 32 && keyboardEvent.ctrlKey)
|
||||
) {
|
||||
if (event.key === '?' || event.key === '&' || event.key === '$' || (event.keyCode === 32 && event.ctrlKey)) {
|
||||
setShowingSuggestions(true);
|
||||
}
|
||||
|
||||
if (keyboardEvent.key === 'Backspace') {
|
||||
return next();
|
||||
if (event.key === 'Enter' && showingSuggestions) {
|
||||
// Preventing entering a new line
|
||||
// As of https://github.com/ianstormtaylor/slate/issues/1345#issuecomment-340508289
|
||||
return false;
|
||||
} else {
|
||||
// @ts-ignore
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
const onUrlChange = ({ value }: { value: Value }) => {
|
||||
const onUrlChange = ({ value }: Change) => {
|
||||
setLinkUrl(value);
|
||||
};
|
||||
|
||||
@@ -187,7 +186,6 @@ export const DataLinkInput: React.FC<DataLinkInputProps> = ({ value, onChange, s
|
||||
</Portal>
|
||||
)}
|
||||
<Editor
|
||||
schema={SCHEMA}
|
||||
placeholder="http://your-grafana.com/d/000000010/annotations"
|
||||
value={linkUrl}
|
||||
onChange={onUrlChange}
|
||||
|
||||
@@ -2,4 +2,3 @@ export * from './components';
|
||||
export * from './types';
|
||||
export * from './utils';
|
||||
export * from './themes';
|
||||
export * from './slate-plugins';
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
export { SlatePrism } from './slate-prism';
|
||||
@@ -1,3 +0,0 @@
|
||||
const TOKEN_MARK = 'prism-token';
|
||||
|
||||
export default TOKEN_MARK;
|
||||
@@ -1,160 +0,0 @@
|
||||
import Prism from 'prismjs';
|
||||
import { Block, Text, Decoration } from 'slate';
|
||||
import { Plugin } from '@grafana/slate-react';
|
||||
import Options, { OptionsFormat } from './options';
|
||||
import TOKEN_MARK from './TOKEN_MARK';
|
||||
|
||||
/**
|
||||
* A Slate plugin to highlight code syntax.
|
||||
*/
|
||||
export function SlatePrism(optsParam: OptionsFormat = {}): Plugin {
|
||||
const opts: Options = new Options(optsParam);
|
||||
|
||||
return {
|
||||
decorateNode: (node, editor, next) => {
|
||||
if (!opts.onlyIn(node)) {
|
||||
return next();
|
||||
}
|
||||
return decorateNode(opts, Block.create(node as Block));
|
||||
},
|
||||
|
||||
renderDecoration: (props, editor, next) =>
|
||||
opts.renderDecoration(
|
||||
{
|
||||
children: props.children,
|
||||
decoration: props.decoration,
|
||||
},
|
||||
editor as any,
|
||||
next
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
import React from 'react';
|
||||
import { Mark, Node, Decoration } from 'slate';
|
||||
import { Editor } from '@grafana/slate-react';
|
||||
import { Record } from 'immutable';
|
||||
|
||||
import TOKEN_MARK from './TOKEN_MARK';
|
||||
|
||||
export interface OptionsFormat {
|
||||
// Determine which node should be highlighted
|
||||
onlyIn?: (node: Node) => boolean;
|
||||
// Returns the syntax for a node that should be highlighted
|
||||
getSyntax?: (node: Node) => string;
|
||||
// Render a highlighting mark in a highlighted node
|
||||
renderMark?: ({ mark, children }: { mark: Mark; children: React.ReactNode }) => void | React.ReactNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Default filter for code blocks
|
||||
*/
|
||||
function defaultOnlyIn(node: Node): boolean {
|
||||
return node.object === 'block' && node.type === 'code_block';
|
||||
}
|
||||
|
||||
/**
|
||||
* Default getter for syntax
|
||||
*/
|
||||
function defaultGetSyntax(node: Node): string {
|
||||
return 'javascript';
|
||||
}
|
||||
|
||||
/**
|
||||
* 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>;
|
||||
}
|
||||
|
||||
/**
|
||||
* The plugin options
|
||||
*/
|
||||
class Options
|
||||
extends Record({
|
||||
onlyIn: defaultOnlyIn,
|
||||
getSyntax: defaultGetSyntax,
|
||||
renderDecoration: defaultRenderDecoration,
|
||||
})
|
||||
implements OptionsFormat {
|
||||
readonly onlyIn!: (node: Node) => boolean;
|
||||
readonly getSyntax!: (node: Node) => string;
|
||||
readonly renderDecoration!: (
|
||||
{
|
||||
decoration,
|
||||
children,
|
||||
}: {
|
||||
decoration: Decoration;
|
||||
children: React.ReactNode;
|
||||
},
|
||||
editor: Editor,
|
||||
next: () => any
|
||||
) => void | React.ReactNode;
|
||||
|
||||
constructor(props: OptionsFormat) {
|
||||
super(props);
|
||||
}
|
||||
}
|
||||
|
||||
export default Options;
|
||||
@@ -1,22 +1,22 @@
|
||||
import { Block, Document, Text, Value, SchemaProperties } from 'slate';
|
||||
// @ts-ignore
|
||||
import { Block, Document, Text, Value } from 'slate';
|
||||
|
||||
export const SCHEMA: SchemaProperties = {
|
||||
document: {
|
||||
nodes: [
|
||||
{
|
||||
match: [{ type: 'paragraph' }, { type: 'code_block' }, { type: 'code_line' }],
|
||||
},
|
||||
],
|
||||
const SCHEMA = {
|
||||
blocks: {
|
||||
paragraph: 'paragraph',
|
||||
codeblock: 'code_block',
|
||||
codeline: 'code_line',
|
||||
},
|
||||
inlines: {},
|
||||
marks: {},
|
||||
};
|
||||
|
||||
export const makeFragment = (text: string, syntax?: string): Document => {
|
||||
export const makeFragment = (text: string, syntax?: string) => {
|
||||
const lines = text.split('\n').map(line =>
|
||||
Block.create({
|
||||
type: 'code_line',
|
||||
nodes: [Text.create(line)],
|
||||
})
|
||||
} as any)
|
||||
);
|
||||
|
||||
const block = Block.create({
|
||||
@@ -25,17 +25,18 @@ export const makeFragment = (text: string, syntax?: string): Document => {
|
||||
},
|
||||
type: 'code_block',
|
||||
nodes: lines,
|
||||
});
|
||||
} as any);
|
||||
|
||||
return Document.create({
|
||||
nodes: [block],
|
||||
});
|
||||
};
|
||||
|
||||
export const makeValue = (text: string, syntax?: string): Value => {
|
||||
export const makeValue = (text: string, syntax?: string) => {
|
||||
const fragment = makeFragment(text, syntax);
|
||||
|
||||
return Value.create({
|
||||
document: fragment,
|
||||
});
|
||||
SCHEMA,
|
||||
} as any);
|
||||
};
|
||||
|
||||
@@ -5,10 +5,6 @@
|
||||
"compilerOptions": {
|
||||
"rootDirs": [".", "stories"],
|
||||
"typeRoots": ["./node_modules/@types", "types"],
|
||||
"baseUrl": "./node_modules/@types",
|
||||
"paths": {
|
||||
"@grafana/slate-react": ["slate-react"]
|
||||
},
|
||||
"declarationDir": "dist",
|
||||
"outDir": "compiled"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user