I'm trying to edit the actual existing plugin of highlight to be able to add text color customizable from command argument, which means that if you put RGB or hex color it will take it on the selection create a view attribute style = 'color: PARAMETER'
What I got so far just surround the text with font tag and the style attribute with color but with a color value incorrect.
Which mean the value on the command is not being passed to the converter.
I'm being unable to find a way to transfer input information from a command to use directly in the converter to make this feature works.
The normal behavior in this plugin make it impossible to use the 16 million colors from RGB, and it requires an obsolete model of defined colors.
You can see/edit/use what i've done so far in this repo
https://github.com/klys/ckeditor5-highlight-inline
In this part the converter create the font element with the style color but with a incorrect value for color value.
editor.conversion.attributeToElement( {
model: HIGHLIGHT,
view: {
name: 'font',
styles: {
'color': true
},
priority: 5,
model: {
key: 'highlight',
value: viewElement => viewElement.getAttribute( 'color' )
},
type:'pen'
}
} );
And this the edited command executor from the original plugin, which i edit to meet the needs of this feature.
execute( color ) {
const model = this.editor.model;
const document = model.document;
const selection = document.selection;
//const highlighter = options.value;
/*var __model;
for ( const option of options ) {
__model = new Model( {
model: 'color model',
class: 'color-class',
title: 'color pen',
color: option.value,
type: 'pen'
} );
}
const highlighter = __model;*/
model.change( writer => {
const ranges = model.schema.getValidRanges( selection.getRanges(), 'highlight' );
if ( selection.isCollapsed ) {
const position = selection.getFirstPosition();
// When selection is inside text with `highlight` attribute.
if ( selection.hasAttribute( 'highlight' ) ) {
// Find the full highlighted range.
const isSameHighlight = value => {
return value.item.hasAttribute( 'highlight' ) && value.item.getAttribute( 'highlight' ) === this.value;
};
const highlightStart = position.getLastMatchingPosition( isSameHighlight, { direction: 'backward' } );
const highlightEnd = position.getLastMatchingPosition( isSameHighlight );
const highlightRange = writer.createRange( highlightStart, highlightEnd );
// Then depending on current value...
if ( !color || this.value === color ) {
// ...remove attribute when passing highlighter different then current or executing "eraser".
writer.removeAttribute( 'highlight', highlightRange );
writer.removeSelectionAttribute( 'highlight' );
} else {
// ...update `highlight` value.
writer.setAttribute( 'highlight', color, highlightRange );
writer.setSelectionAttribute( 'highlight', color );
}
} else if ( color ) {
writer.setSelectionAttribute( 'highlight', color );
}
} else {
for ( const range of ranges ) {
if ( color ) {
writer.setAttribute( 'highlight', color, range );
} else {
writer.removeAttribute( 'highlight', range );
}
}
}
} );
}
I have been almost a week in this problem.
If you can a least point me out in the right direction, you won't imagine how much you will help me.
Related
I have used Hogan templates in widgets, and now I want to use it inside a widget connector. Does anyone know how to do that?
All docs on instantsearch only uses javascript template literals.
Example:
const fmInfiniteHits = instantsearch.connectors.connectInfiniteHits(
(renderArgs, isFirstRender) => {
const { hits, showMore, widgetParams } = renderArgs;
const { container } = widgetParams;
if (isFirstRender) {
$(container).append('<ul></ul>');
return;
}
// NOW
$(container +' ul').html(hits.map(hit => `<li> ... </li>`));
// WHAT I WANT
let result = hits.renderWithHogan; // <-- How do I do this
$(container +' ul').html(result);
},
);
I created a component to be an Icons wrapper, so I don't need to keep editing the icon in the style of the file I use... However, when testing a property that can be applied to the "hover" component , the test says that this property does not exist, even passing!
file index
export type IconsProps = {
hoverColor?: colorTypes
}
const Icons = ({ hoverColor }: IconsProps) => (
<S.Wrapper color={color} size={size} hoverColor={hoverColor}>
{children}
</S.Wrapper>
)
file style
const wrapperModifiers = {
hoverColor: (theme: DefaultTheme, hoverColor: colorTypes) => css`
& :hover {
color: ${theme.colors[hoverColor]};
}
`,
}
export const Wrapper = styled.main<IconsProps>`
${({ theme, hoverColor }) => css`
> ${StyledIconBase} {
${!!hoverColor && wrapperModifiers.hoverColor(theme, hoverColor)}
}
`}
`
test
import { Coffee } from '#styled-icons/boxicons-solid'
it('deve testar o hover e o transform', () => {
const { debug, container } = renderWithTheme(
<Icons color="primary" size="5rem" hoverColor="secondary">
<Coffee title="Coffee" />
</Icons>,
)
expect(screen.getByRole('img', { name: /coffee/i })).toHaveStyleRule(
'color',
'#0487cc',
{
modifier: ':hover',
},
)
})
error
No style rules found on passed Component using options:
{"modifier":":hover"}
In my opinion, the error that you are getting is that you haven't properly selected the element which is having a hover color. Because of that reason, jest-styled-component is not able to find the element with a hover modifier.
& :hover {
color: ${theme.colors[hoverColor]};
}
You added a space between & and : which is not right. The hover will not be applied to the selected element.
Solution: Remove the space between them.
&:hover {
color: ${theme.colors[hoverColor]};
}
I'm trying to drop image from outside of draft-js editor but it's always inserted at last position of the cursor/selection in editor (or at end if cursor/selection not set).
This is my wrap around draft-js-drag-n-drop-plugin
const droppableBlockDndPlugin = {
...blockDndPlugin,
handleDrop: (
selection,
dataTransfer,
isInternal,
{getEditorState, setEditorState}
) => {
const editorState = getEditorState();
const raw = dataTransfer.data.getData('text');
const data = raw ? raw.split(IMAGE_BLOCK_TYPE_SEPARATOR) : [];
if (data.length > 1 && data[0] === IMAGE_BLOCK_TYPE_PURE) {
const url = data[1];
if (url) {
const newState = imagePlugin.addImage(editorState, url);
setEditorState(newState);
}
}
return blockDndPlugin.handleDrop(selection, dataTransfer, isInternal, {
getEditorState,
setEditorState
});
}
};
Basically I'm just doing extra logic before base handleDrop occurs where I insert image using imagePlugin.addImage. Is there way to drop image to dragged position?
Actually it was quite obvious solution - you should just use passed selection and create new state with it and then add image to that new state:
const newState = imagePlugin.addImage(EditorState.forceSelection(editorState, selection), url);
setEditorState(newState);
I have been changing a form based on REACT and this is something I am a newb with (been using it already for 4 months but just segments of it, sometimes actual progress with the programming is based on pure luck and every time on advices of good people found here).
Currently I have a task of re-developing a form of this look:
What I need to achieve is Calibration radios' behavior based on Type's selection: if argument calibration is set to 0 (zero) then disable option 'Accredited' and check second option automatically.
Edited: 19 Oct 2017
This creates the drop down, and the DD works great:
createSuggestInput(name) {
const { id, value, labels } = this.props;
const _t = this.props.intl.formatMessage;
var options = [
{ value: 'one', label: 'One', calibration: '0' },
{ value: 'two', label: 'Two ', calibration: '1' },
{ value: 'three', label: 'Three', calibration: '0' },
{ value: 'four', label: 'Four', calibration: '1' },
];
return <Select.Creatable
name = {`${id}_${name}`}
value = {this.state.brandSelect}
placeholder = {_t(translations.txtSuggest)}
options = {options}
onChange = {this._onChange.bind(this)}
label = {labels[name]}
key = {`${id}_${name}`}
promptTextCreator = { (label) => _t(translations.txtCreate) + ' ' + label + _t(translations.txtCreateEnter) }
/>;
}
When selected option's calibration value is ZERO, I need to update set of Calibration radio buttons, by disabling the option "Accredited" and at the same time checking the second option, "Not Accredited".
createRadioCalibration(name) {
const { id, value, labels } = this.props;
const _t = this.props.intl.formatMessage;
const ACCREDITATION_TYPES = [
[CALIBRATION_ACCREDITED, _t(messages.calibrationAccredited)],
[CALIBRATION_NOT_ACCREDITED, _t(messages.calibrationNotAccredited)]
];
return <FormChoiceGroup
type = "radio"
values = {ACCREDITATION_TYPES.map(mapValueArray)}
key = {`${id}_${name}`}
name = {`${id}_${name}`}
value = {value[name]}
handleChange = {this.handleFieldChangeFn(name)}
/>;
}
These two are rendered as follows:
render () {
const FIELDS = {
[CALIBRATION]: this.createRadioCalibration(CALIBRATION),
[TYPE]: this.createSuggestInput(TYPE),
};
return (
<div className="repair-form-device repair-form-device-field-row">
<div className="repair-form-device-id">
{id + 1}
</div>
<div className="clearfix repair-form-device-content">
<div className="">
{ FIELDS[TYPE] }
</div>
<div className="">
<label>{_t(messages.repair)}</label>
{ FIELDS[CALIBRATION] }
</div>
.....
And lastly the _onChange function:
_onChange(tool) {
const { id } = this.props;
this.setState({
brandSelect: tool
});
}
As I stated previously, I am stuck with the main task, which is manipulating the Calibration radio buttons.
I believe I can update its status inside the _onChange function, but everything I tested so far lead me nowhere.
Your patience is much appreciated!
Now I make markdown highlighter.
Highlight inline is not so difficult. I use CompositeDecorator to rewrite text. https://facebook.github.io/draft-js/docs/advanced-topics-decorators.html
But I can't use multiline syntax (for example, codeblock). By default, newline becomes next block and decorator is handled by block to block.
Below image is example of my implementation. I can't decorate codeblock syntax.
How do I make multiline highlighter on draft-js?
Depends on what 'Highlight' style you want. Mostly the inline style should be enough if you just want some color or font size. check the color example.
While for block style, you need a custom CSS class and map the block to your class, refer this.
I found work around. Detecting markdown codeblock by dand on blockRendererFn.
// use blockRedererFn
<Editor
blockRendererFn={(block) => blockRenderer(block, this.state.editorState)}
editorState={this.state.editorState}
/>;
// detect code block and add fontFamily: monospace
// Example
//
// ```
// here
// ```
function blockRenderer(contentBlock, editorState) {
const type = contentBlock.getType();
if (type === "unstyled") {
const allText = editorState.getCurrentContent().getPlainText();
const allCount = countCodeBlockHeader(allText);
if (allCount > 0 && allCount % 2 === 0) {
const contentText = contentBlock.getText();
const [before, after] = allText.split(contentText);
const beforeCount = countCodeBlockHeader(before);
const afterCount = countCodeBlockHeader(after);
if (beforeCount % 2 === 1) {
if (afterCount % 2 === 1) {
return {
component: (_props) => {
return <code style={{
fontFamily: "monospace",
direction: "ltr",
unicodeBidi: "bidi-override",
}}>{contentText}</code>;
},
editable: true
};
}
}
}
}
}
function countCodeBlockHeader(text) {
return text
.split("\n")
.filter(l => l.match(new RegExp("^(```)")))
.length;
}
but it's dirty.