Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • wax/wax-prosemirror
  • CwenMab/wax-prosemirror
  • jgay/wax-prosemirror
  • Mohan-A/wax-prosemirror
4 results
Show changes
Commits on Source (16)
Showing
with 750 additions and 16 deletions
[Template for request for comments (RFC) on feature proposals]
# RFC: Feature proposal: [Title]
## Context
[Give the necessary context for your proposal. For example, what problem will this feature solve for users? What are the use cases, benefits, and goals?]
## Proposal
[A precise statement of the proposed feature.]
## Design
[Include sketch or wireframes of the UI changes necessary for this feature]
## Implementation (if applicable)
[A description of the steps to implement the feature.]
## Alternative approaches (if applicable)
[Include any alternatives to meet this use case.]
## Open issues (if applicable)
[Links to and a discussion of related issues, if applicable.]
......@@ -21,6 +21,7 @@ We maintain master as the production branch and tag it with release names. If yo
- Create a user account on Coko GitLab : http://gitlab.coko.foundation
- Clone master with `git clone https://gitlab.coko.foundation/wax/wax-prosemirror.git`
- Create a new branch and work off that. Please name the branch in a way that sensibly identifies the feature you are working on. You can push the branch to Coko Gitlab at anytime.
- If the master branch has moved forward, at the time of finishing the feature, rebase your branch to master(git rebase master),resolve if any conflicts, check that everything worked as before, and then submit a MR
## Getting your contributions merged
......
......@@ -34,6 +34,13 @@ import {
SpecialCharactersToolGroupService,
HighlightService,
TextHighlightToolGroupServices,
EditorInfoToolGroupServices,
ShortcutToolGroupServices,
HelpToolGroupServices,
CounterInfoService,
BottomInfoService,
TransformService,
TransformToolGroupService,
} from 'wax-prosemirror-services';
import { DefaultSchema } from 'wax-prosemirror-utilities';
......@@ -57,6 +64,7 @@ export default {
more: ['Superscript', 'Subscript', 'SmallCaps'],
},
'HighlightToolGroup',
'TransformToolGroup',
'Notes',
'Lists',
'Images',
......@@ -88,6 +96,19 @@ export default {
},
],
},
{
templateArea: 'BottomRightInfo',
toolGroups: [
{
name: 'InfoToolGroup',
more: [
'CounterInfoTool',
'ShortcutTool',
'HelpTool'
],
},
],
},
],
SchemaService: DefaultSchema,
......@@ -139,5 +160,12 @@ export default {
new SpecialCharactersToolGroupService(),
new HighlightService(),
new TextHighlightToolGroupServices(),
new EditorInfoToolGroupServices(),
new CounterInfoService(),
new BottomInfoService(),
new ShortcutToolGroupServices(),
new HelpToolGroupServices(),
new TransformService(),
new TransformToolGroupService(),
],
};
......@@ -28,10 +28,15 @@ import {
BlockDropDownToolGroupService,
HighlightService,
TextHighlightToolGroupServices,
EditorInfoToolGroupServices,
ShortcutToolGroupServices,
HelpToolGroupServices,
CounterInfoService,
BottomInfoService,
TransformService,
TransformToolGroupService,
} from 'wax-prosemirror-services';
import { DefaultSchema } from 'wax-prosemirror-utilities';
import { WaxSelectionPlugin } from 'wax-prosemirror-plugins';
import invisibles, {
......@@ -51,6 +56,7 @@ export default {
more: ['Superscript', 'Subscript', 'SmallCaps'],
},
'HighlightToolGroup',
'TransformToolGroup',
'BlockDropDown',
'Notes',
'Lists',
......@@ -60,9 +66,21 @@ export default {
'TrackChange',
],
},
{
templateArea: 'BottomRightInfo',
toolGroups: [
{
name: 'InfoToolGroup',
more: [
'CounterInfoTool',
'ShortcutTool',
'HelpTool'
],
},
],
},
],
SchemaService: DefaultSchema,
RulesService: [emDash, ellipsis],
ShortCutsService: {},
EnableTrackChangeService: { enabled: false },
......@@ -104,5 +122,12 @@ export default {
new BlockDropDownToolGroupService(),
new HighlightService(),
new TextHighlightToolGroupServices(),
new EditorInfoToolGroupServices(),
new CounterInfoService(),
new BottomInfoService(),
new ShortcutToolGroupServices(),
new HelpToolGroupServices(),
new TransformService(),
new TransformToolGroupService(),
],
};
......@@ -160,7 +160,19 @@ const NotesContainer = styled.div`
height: 100%;
width: 65%;
`;
const WaxBottomRightInfo= styled.div`
`;
const InfoContainer= styled.div`
display:flex;
position:fixed !important;
bottom:1px;
right:21px;
z-index:1;
`;
const InfoArea=styled.div`
`;
let surfaceHeight = 600;
let notesHeight = 200;
......@@ -184,7 +196,7 @@ const NotesArea = ComponentPlugin('notesArea');
const RightArea = ComponentPlugin('rightArea');
const CommentTrackToolBar = ComponentPlugin('commentTrackToolBar');
const WaxOverlays = ComponentPlugin('waxOverlays');
const BottomRightInfo=ComponentPlugin('BottomRightInfo');
const EditoriaLayout = ({ editor }) => {
const {
view: { main },
......@@ -209,6 +221,13 @@ const EditoriaLayout = ({ editor }) => {
return (
<ThemeProvider theme={cokoTheme}>
<Wrapper>
<WaxBottomRightInfo>
<InfoContainer id="info-container">
<BottomRightInfo/>
</InfoContainer>
</WaxBottomRightInfo>
<TopMenu>
<MainMenuToolBar />
</TopMenu>
......
......@@ -147,7 +147,19 @@ const NotesContainer = styled.div`
padding-right: ${grid(1)};
}
`;
const WaxBottomRightInfo= styled.div`
`;
const InfoContainer= styled.div`
display:flex;
position:fixed !important;
bottom:1px;
right:21px;
z-index:1;
`;
const InfoArea=styled.div`
`;
let surfaceHeight = 500;
let notesHeight = 150;
......@@ -194,6 +206,13 @@ const EditoriaLayout = ({ editor }) => {
return (
<ThemeProvider theme={cokoTheme}>
<Wrapper>
<WaxBottomRightInfo>
<InfoContainer id="info-container">
<BottomRightInfo/>
</InfoContainer>
</WaxBottomRightInfo>
<TopMenu>
<TopBar />
</TopMenu>
......
......@@ -18,3 +18,5 @@ export { default as FindAndReplaceTool } from './src/components/findAndReplace/F
export { default as FullScreen } from './src/components/FullScreen';
export { default as SpecialCharactersTool } from './src/components/specialCharacters/SpecialCharactersTool';
export { default as TextHighlightingTool } from './src/components/textHighlight/TextHighlightingTool';
export { default as EditorInfoTool} from './src/components/EditorInfo/CounterInfo/EditorInfoTool';
export { default as TransformCaseComponent } from './src/components/transformCase/TransformCaseComponent';
import React, { useMemo, useState, useRef, useContext, useEffect, useCallback } from 'react';
import styled from 'styled-components';
import { grid } from '@pubsweet/ui-toolkit';
import { v4 as uuidv4 } from 'uuid';
import { WaxContext } from 'wax-prosemirror-core';
import { DocumentHelpers } from 'wax-prosemirror-utilities';
import MenuButton from '../../../ui/buttons/MenuButton';
import useOnClickOutside from '../../../helpers/useOnClickOutside';
const Wrapper = styled.div`
font-size: 0;
position: relative;
z-index: 2;
`;
const DropWrapper = styled.div`
background: white;
margin-top: ${grid(1)};
position: absolute;
top: 32px;
width: max-content;
`;
const CounterInfoComponent = styled.div`
background:white;
border:1px solid gray;
bottom:45px;
display: flex;
flex-direction: column;
position:fixed;
right:50px;
`;
const Counter = styled.div`
color:black;
cursor: pointer;
display: block;
font-size:14px;
height: 25px;
margin:5px;
min-width: 150px;
`;
const EditorInfoTool = ({ view: { state }, item }) => {
const { title } = item;
const [isOpen, setIsOpen] = useState(false);
const [getWordCountFromState, setTotalWords] = useState(0);
const [totalCharCount, setTotalCharCount] = useState();
const [totalCharCountWithoutSpace, setTotalCharWithoutSpace] = useState();
const [getSelectionCountFromState, setSelectedTextCount] = useState();
const [paraCount, setTotalParagraph] = useState();
const [imgCount, setImgCount] = useState();
const [tableCount, setTableCount] = useState();
const [footnoteCount, setFootNoteCount] = useState();
const [blocklevelNode, setBlockLevelNodes] = useState();
const ref = useRef();
const {activeView,view: { main } } = useContext(WaxContext);
const allBlockNodes = DocumentHelpers.findBlockNodes(main.state.doc);
const InlineNodes = DocumentHelpers.findInlineNodes(main.state.doc);
useOnClickOutside(ref, () => setIsOpen(false));
const infoDropDownOptions = [
{ name: `${getWordCountFromState} Words` },
{ name: `${totalCharCount} Characters` },
{ name: `${totalCharCountWithoutSpace} Character Without Space` },
{ name: `${paraCount} Paragraph` },
{ name: `${imgCount} Images` },
{ name: `${tableCount} Tables` },
{ name: `${footnoteCount} Footnotes` },
{ name: `${blocklevelNode} Block-Level Nodes` },
];
const renderList = () => {
const lists = [];
Object.keys(infoDropDownOptions).forEach(key=>{
lists.push(
<Counter key={uuidv4()}
title={infoDropDownOptions[key].name}><span>{infoDropDownOptions[key].name}</span>
</Counter>
);
});
return <div>{lists}</div>;
};
const getCount = useCallback(() => {
let getWordCountFromStates = 0;
InlineNodes.forEach(value => {
if (value.node.text !== undefined && value.node.text.length > 0) {
value.node.text.trim().split(" ").forEach((key, pos) => {
if (key.length > 0) {
getWordCountFromStates += 1;
}
})
}
})
return getWordCountFromStates
});
const getCharCount = useCallback(() => {
let totalCharCounts = 0;
InlineNodes.forEach(value => {
if (value.node.text !== undefined) {
totalCharCounts += value.node.text.length;
}
})
return totalCharCounts;
});
const getCharCountWithoutSpace = useCallback(() => {
let totalCharCountWithoutSpaces = 0;
InlineNodes.forEach(value => {
if (value.node.text !== undefined) {
totalCharCountWithoutSpaces += value.node.text.replace(/\s+/g, '').length;
}
})
return totalCharCountWithoutSpaces;
});
useEffect(() => {
let footNoteCount = 0;
let blockLevelCount = 0;
let paraCounts = 0;
let tableCounts = 0;
let imgCounts = 0;
let listTableCount = 0;
let nestTableCount = 0;
allBlockNodes.forEach(value => {
if (value.pos === 0) {
blockLevelCount = 0;
}
else {
blockLevelCount = allBlockNodes.length;
}
})
setBlockLevelNodes(blockLevelCount);
allBlockNodes.forEach(value => {
value.node.forEach(imgs => {
if (imgs.type.name === "image") {
imgCounts += 1;
}
if (imgs.type.name === "footnote") {
footNoteCount += 1;
}
})
})
main.state.doc.content.content.forEach(value => {
if (value.attrs.class === "paragraph" && value.content.size > 0) {
paraCounts += 1;
}
if (value.type.name === "table") {
tableCounts += 1;
}
value.content.content.forEach(listTable => {
listTable.content.content.forEach(lastListTable => {
if (lastListTable.type.name === "table") {
listTableCount += 1
}
lastListTable.content.content.forEach(nestedTable => {
nestedTable.content.content.forEach(nestedTypeTable => {
if (nestedTypeTable.type.name === "table") {
nestTableCount += 1;
}
})
})
})
})
})
setImgCount(imgCounts);
setTotalParagraph(paraCounts);
setTableCount(tableCounts + listTableCount + nestTableCount);
setFootNoteCount(footNoteCount);
setTotalCharCount(getCharCount());
setTotalWords(getCount());
setTotalCharWithoutSpace(getCharCountWithoutSpace());
let selectedCountPara = 0;
let selectedCountList = 0;
let selectedCountNest = 0;
let noteTextValue = 0;
let footNodeCount = 0;
let selectedListTableCount = 0;
let finalNestedValueCount = 0;
state.selection.content().content.content.forEach(value => {
value.content.content.forEach((textValue) => {
if (textValue.text) {
const textArray = textValue.text.trim().split(" ");
let isChar = false;
textArray.forEach((key, pos) => {
// eslint-disable-next-line no-restricted-globals
if (key.charCodeAt(pos) !== 32 && isNaN(key.charCodeAt(pos))===false) {
isChar = true;
}
})
if (isChar) {
selectedCountPara += textValue.text.trim().split(' ').length;
}
}
textValue.content.content.forEach(listValue => {
if (listValue.text && listValue.text !== ' ') {
const listArray = listValue.text.trim().split(' ');
let isFootChar = false;
listArray.forEach((key, pos) => {
if (key.charCodeAt(pos) !== 32) {
isFootChar = true;
}
})
if (isFootChar) {
footNodeCount += listValue.text.trim().split(' ').length;
}
}
listValue.content.content.forEach(listItem => {
if (listItem.text && listItem.text !== ' ') {
const itemArray = listItem.text.trim().split(' ');
let isItemChar = false;
itemArray.forEach((key, pos) => {
// eslint-disable-next-line no-restricted-globals
if (key.charCodeAt(pos) !== 32 && isNaN(key.charCodeAt(pos))===false) {
isItemChar = true;
}
})
if (isItemChar) {
selectedCountList += listItem.text.trim().split(' ').length;
}
}
listItem.content.content.forEach(nestedItem => {
nestedItem.content.content.forEach(nestIn => {
if (nestIn.text !== undefined) {
const nestArray = nestIn.text.trim().split(" ");
let isNestChar = false;
nestArray.forEach((key, pos) => {
// eslint-disable-next-line no-restricted-globals
if (key.charCodeAt(pos) !== 32 && isNaN(key.charCodeAt(pos))===false) {
isNestChar = true;
}
})
if (nestIn.text && isNestChar) {
selectedCountNest += nestIn.text.trim().split(' ').length;
}
}
nestIn.content.content.forEach(listTable => {
if (listTable.text !== undefined) {
const listTableArray = listTable.text.trim().split(' ');
let isListChar = false;
listTableArray.forEach((key, pos) => {
// eslint-disable-next-line no-restricted-globals
if (key.charCodeAt(pos) !== 32 && isNaN(key.charCodeAt(pos))===false) {
isListChar = true;
}
})
if (listTable.text && isListChar) {
selectedListTableCount += listTable.text.trim().split(' ').length
}
}
listTable.content.content.forEach(tableValue => {
tableValue.content.content.forEach(finalTableValue => {
if (finalTableValue.text !== undefined) {
const finalTableArray = finalTableValue.text.trim().split(" ")
let isFinalTable = false;
finalTableArray.forEach((key, pos) => {
// eslint-disable-next-line no-restricted-globals
if (key.charCodeAt(pos) !== 32 && isNaN(key.charCodeAt(pos))===false) {
isFinalTable = true;
}
})
if (finalNestedValueCount.text && isFinalTable) {
finalNestedValueCount = finalTableValue.text.trim().split(" ").length
}
}
})
})
})
})
})
})
})
})
if (value.text !== undefined) {
const valueArray = value.text.trim().split(" ");
let isValue = false;
valueArray.forEach((key, pos) => {
// eslint-disable-next-line no-restricted-globals
if (key.charCodeAt(pos) !== 32 && isNaN(key.charCodeAt(pos))===false) {
isValue = true;
}
})
if (isValue) {
noteTextValue += value.text.trim().split(" ").length;
}
}
});
setSelectedTextCount(selectedCountNest + finalNestedValueCount + selectedListTableCount + selectedCountPara + selectedCountList + noteTextValue + footNodeCount)
if (activeView.state.selection.$from.pos === activeView.state.selection.$to.pos) {
setSelectedTextCount(0);
}
})
const MenuButtonComponent = useMemo(
() => (
<Wrapper ref={ref}>
<MenuButton
active={isOpen}
disabled={false}
label={`${getSelectionCountFromState >0 ? getSelectionCountFromState : getWordCountFromState}
word${getSelectionCountFromState && getSelectionCountFromState > 1 ? 's' : ''}${!getSelectionCountFromState && getWordCountFromState > 1 ? 's' : ''}`}
onMouseDown={() => setIsOpen(true)}
title={title}
/>
{isOpen && (
<DropWrapper>
<CounterInfoComponent key={uuidv4()} item={item} view={state}
close={() => {
setIsOpen(false);
}}>{renderList()}</CounterInfoComponent>
</DropWrapper>
)}
</Wrapper>
),
[isOpen, getWordCountFromState, getSelectionCountFromState],
);
return MenuButtonComponent
};
export default EditorInfoTool;
import React, { useContext, useMemo, useRef, useState } from 'react';
import styled from 'styled-components';
import { grid } from '@pubsweet/ui-toolkit';
import { v4 as uuid } from 'uuid';
import { WaxContext } from 'wax-prosemirror-core';
import MenuButton from '../../ui/buttons/MenuButton';
import useOnClickOutside from '../../helpers/useOnClickOutside';
import Icon from '../../helpers/Icon';
const Wrapper = styled.div`
font-size: 0;
position: relative;
z-index: 2;
`;
const DropWrapper = styled.div`
background: white;
margin-top: ${grid(1)};
position: absolute;
top: 32px;
width: max-content;
`;
const TextTransformCaseComponent = styled.div`
background: white;
border: 1px solid gray;
display: flex;
flex-direction: column;
`;
const Transformer = styled.div`
cursor: pointer;
display: inline-grid;
height: 25px;
margin: 5px 10px;
min-width: 25px;
`;
const StyledIcon = styled(Icon)`
height: 24px;
width: 24px;
`;
const TransformCaseComponent = ({ view: { state }, item }) => {
const { icon, title, select } = item;
const [isOpen, setIsOpen] = useState(false);
const ref = useRef();
const { activeViewId, activeView } = useContext(WaxContext);
const isDisabled = !select(state, activeViewId, activeView);
useOnClickOutside(ref, () => setIsOpen(false));
const transformCaseDropDown = [
{ id: 1, name: 'Upper Case', iconName: 'transformCase' },
{ id: 2, name: 'Lower Case', iconName: 'lowerCaseTransform' },
{ id: 3, name: 'Sentence Case', iconName: 'transformCase' },
{ id: 4, name: 'Title Case', iconName: 'transformCase' },
];
const onClickTransform = (e, id) => {
switch (id) {
case 1:
item.run(activeView.state, activeView.dispatch, 'upperCase');
break;
case 2:
item.run(activeView.state, activeView.dispatch, 'lowerCase');
break;
case 3:
item.run(activeView.state, activeView.dispatch, 'sentenceCase');
break;
case 4:
item.run(activeView.state, activeView.dispatch, 'titleCase');
break;
default:
break;
}
setIsOpen(false);
};
const renderList = () => {
return (
<div>
{transformCaseDropDown.map(data => (
<Transformer
key={uuid()}
onClick={e => onClickTransform(e, data.id)}
title={data.name}
>
<StyledIcon name={data.iconName} />
</Transformer>
))}
</div>
);
};
return useMemo(
() => (
<Wrapper ref={ref}>
<MenuButton
active={isOpen}
disabled={isDisabled}
iconName={icon}
onMouseDown={() => {
setIsOpen(!isOpen);
}}
title={title}
/>
{isOpen && (
<DropWrapper>
<TextTransformCaseComponent
close={() => {
setIsOpen(false);
}}
item={item}
key={uuid()}
view={state}
>
{renderList()}
</TextTransformCaseComponent>
</DropWrapper>
)}
</Wrapper>
),
[isOpen, isDisabled],
);
};
export default TransformCaseComponent;
......@@ -23,10 +23,10 @@ const Svg = styled.svg.attrs(() => ({
xmlns: 'http://www.w3.org/2000/svg',
xmlnsXlink: 'http://www.w3.org/1999/xlink',
}))`
height: 24px;
width: 24px;
fill: ${th('colorPrimary')};
height: 24px;
vertical-align: top;
width: 24px;
`;
export default {
......@@ -220,7 +220,7 @@ export default {
className={className}
enable-background="new 0 0 24 24"
viewBox="0 0 24 24"
></Svg>
/>
),
title: ({ className }) => (
<Svg className={className} viewBox="0 0 24 24">
......@@ -229,46 +229,46 @@ export default {
</Svg>
),
findAndReplace: ({ className }) => (
<Svg className={className} viewBox="0 0 24 24" fill="none">
<Svg className={className} fill="none" viewBox="0 0 24 24">
<path d="M0 0h24v24H0z" fill="none" />
<path d="M11 6c1.38 0 2.63.56 3.54 1.46L12 10h6V4l-2.05 2.05C14.68 4.78 12.93 4 11 4c-3.53 0-6.43 2.61-6.92 6H6.1c.46-2.28 2.48-4 4.9-4zm5.64 9.14c.66-.9 1.12-1.97 1.28-3.14H15.9c-.46 2.28-2.48 4-4.9 4-1.38 0-2.63-.56-3.54-1.46L10 12H4v6l2.05-2.05C7.32 17.22 9.07 18 11 18c1.55 0 2.98-.51 4.14-1.36L20 21.49 21.49 20l-4.85-4.86z" />
</Svg>
),
navigatePrevious: ({ className }) => (
<Svg className={className} viewBox="0 0 24 24" fill="none">
<Svg className={className} fill="none" viewBox="0 0 24 24">
<title>Previous</title>
<path d="M0 0h24v24H0z" fill="none" />
<path d="M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z" />
</Svg>
),
navigateNext: ({ className }) => (
<Svg className={className} viewBox="0 0 24 24" fill="none">
<Svg className={className} fill="none" viewBox="0 0 24 24">
<title>Next</title>
<path d="M0 0h24v24H0V0z" fill="none" />
<path d="M10.02 6L8.61 7.41 13.19 12l-4.58 4.59L10.02 18l6-6-6-6z" />
</Svg>
),
close: ({ className }) => (
<Svg className={className} viewBox="0 0 24 24" fill="none">
<Svg className={className} fill="none" viewBox="0 0 24 24">
<title> Close </title>
<path d="M0 0h24v24H0V0z" fill="none" />
<path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12 19 6.41z" />
</Svg>
),
fullScreen: ({ className }) => (
<Svg className={className} viewBox="0 0 24 24" fill="none">
<Svg className={className} fill="none" viewBox="0 0 24 24">
<title> Full screen </title>
<path d="M7 14H5v5h5v-2H7v-3zm-2-4h2V7h3V5H5v5zm12 7h-3v2h5v-5h-2v3zM14 5v2h3v3h2V5h-5z" />
</Svg>
),
fullScreenExit: ({ className }) => (
<Svg className={className} viewBox="0 0 24 24" fill="none">
<Svg className={className} fill="none" viewBox="0 0 24 24">
<title> Exit full screen </title>
<path d="M5 16h3v3h2v-5H5v2zm3-8H5v2h5V5H8v3zm6 11h2v-3h3v-2h-5v5zm2-11V5h-2v5h5V8h-3z" />
</Svg>
),
specialCharacters: ({ className }) => (
<Svg className={className} viewBox="0 0 24 24" fill="none">
<Svg className={className} fill="none" viewBox="0 0 24 24">
<g>
<rect fill="none" height="24" width="24" x="0" />
</g>
......@@ -282,10 +282,34 @@ export default {
</Svg>
),
chapterList: ({ className }) => (
<Svg className={className} viewBox="0 0 24 24" fill="none">
<Svg className={className} fill="none" viewBox="0 0 24 24">
<title> Chapters </title>
<path d="M0 0h24v24H0z" fill="none" />
<path d="M14 2H6c-1.1 0-1.99.9-1.99 2L4 20c0 1.1.89 2 1.99 2H18c1.1 0 2-.9 2-2V8l-6-6zm2 16H8v-2h8v2zm0-4H8v-2h8v2zm-3-5V3.5L18.5 9H13z" />
</Svg>
),
transformCase: ({ className }) => (
<Svg
className={className}
enableBackground="new 0 0 16 16"
fill="none"
viewBox="0 0 28 28"
>
<path d="M11.44,15.353c0-2.99-1.352-5.486-5.59-5.486c-2.314,0-4.056,0.624-4.94,1.118l0.728,2.548 c0.832-0.52,2.21-0.962,3.51-0.962c1.95,0,2.314,0.962,2.314,1.639v0.183C2.964,14.365,0,15.952,0,19.253 c0,2.028,1.534,3.9,4.108,3.9c1.508,0,2.808-0.547,3.64-1.562h0.078l0.234,1.274h3.562c-0.13-0.702-0.182-1.872-0.182-3.096 V15.353z M7.592,18.239c0,0.232-0.026,0.468-0.078,0.676c-0.26,0.807-1.066,1.456-2.054,1.456c-0.884,0-1.56-0.494-1.56-1.508 c0-1.534,1.612-2.028,3.692-2.003V18.239z" />
<path d="M23.062,5.343h-5.201l-5.355,17.524h4.108l1.247-4.498h5.019l1.353,4.498h4.264L23.062,5.343z M18.434,15.404l1.041-3.718 c0.285-1.014,0.545-2.34,0.806-3.38h0.052c0.26,1.04,0.572,2.34,0.884,3.38l1.093,3.718H18.434z" />
<polygon points="8.025,6.584 1.999,6.584 1.999,6.833 1.999,7.461 1.999,7.709 8.025,7.709 8.025,8.95 12.442,7.146 8.025,5.343" />
</Svg>
),
lowerCaseTransform: ({ className }) => (
<Svg
className={className}
enableBackground="new 0 0 28.08 28.08"
fill="none"
viewBox="0 0 28.08 28.08"
>
<path d="M5.356,5.135L0,22.659h4.108l1.248-4.498h5.018l1.352,4.498h4.264L10.556,5.135H5.356z M5.928,15.196l1.04-3.718 c0.286-1.014,0.546-2.34,0.806-3.38h0.052c0.26,1.04,0.572,2.34,0.884,3.38l1.092,3.718H5.928z" />
<path d="M27.898,19.564v-4.42c0-2.99-1.353-5.486-5.59-5.486c-2.314,0-4.058,0.624-4.94,1.118l0.728,2.548 c0.832-0.52,2.211-0.962,3.51-0.962c1.951,0,2.314,0.962,2.314,1.639v0.183c-4.498-0.026-7.462,1.561-7.462,4.861 c0,2.028,1.534,3.9,4.108,3.9c1.508,0,2.808-0.547,3.64-1.562h0.078l0.233,1.274h3.562C27.95,21.957,27.898,20.787,27.898,19.564z M24.05,18.031c0,0.232-0.026,0.468-0.077,0.676c-0.261,0.807-1.066,1.456-2.055,1.456c-0.884,0-1.561-0.494-1.561-1.508 c0-1.534,1.613-2.028,3.692-2.003V18.031z" />
<polygon points="21.663,8.742 26.08,6.938 21.663,5.135 21.663,6.376 15.637,6.376 15.637,6.625 15.637,7.253 15.637,7.501 21.663,7.501" />
</Svg>
),
};
......@@ -14,6 +14,7 @@ export { default as sourceMark } from './src/marks/sourceMark';
export { default as commentMark } from './src/marks/commentMark';
export { default as mathSelectMark } from './src/marks/mathSelectMark';
export { default as highlightMark } from './src/marks/highlightMark';
export { default as transformMark } from './src/marks/transformMark';
/*
LIST OF TRACK CHANGES MARKS
*/
......
const transform = {
excludes: 'transformCase',
attrs: {
style: { default: null },
},
inclusive: false,
parseDOM: [
{
tag: 'transform',
getAttrs(hook, next) {
Object.assign(hook, {
style: hook.dom.getAttribute('style'),
});
next();
},
},
],
toDOM(hook, next) {
hook.value = ['transform', hook.node.attrs, 0]; // eslint-disable-line no-param-reassign
next();
},
};
export default transform;
......@@ -32,6 +32,9 @@ export { default as FindAndReplaceService } from './src/FindAndReplaceService/Fi
export { default as FullScreenService } from './src/FullScreenService/FullScreenService';
export { default as SpecialCharactersService } from './src/SpecialCharactersService/SpecialCharactersService';
export { default as HighlightService } from './src/HighlightService/HightlightService';
export { default as CounterInfoService } from './src/BottomInfoService/CounterInfoService/CounterInfoService';
export { default as BottomInfoService } from './src/BottomInfoService/BottomInfoService';
export { default as TransformService } from './src/TransformService/TransformService';
/*
ToolGroups
......@@ -51,4 +54,8 @@ export { default as BlockDropDownToolGroupService } from './src/WaxToolGroups/Bl
export { default as TrackingAndEditingToolGroupService } from './src/WaxToolGroups/TrackingAndEditingToolGroupService/TrackingAndEditingToolGroupService';
export { default as FullScreenToolGroupService } from './src/WaxToolGroups/FullScreenToolGroupService/FullScreenToolGroupService';
export { default as SpecialCharactersToolGroupService } from './src/WaxToolGroups/SpecialCharactersToolGroupService/SpecialCharactersToolGroupService';
export { default as TextHighlightToolGroupServices } from './src/WaxToolGroups/TextHighlightToolGroupService/TextHighlightToolGroupService';
\ No newline at end of file
export { default as TextHighlightToolGroupServices } from './src/WaxToolGroups/TextHighlightToolGroupService/TextHighlightToolGroupService';
export { default as EditorInfoToolGroupServices } from './src/WaxToolGroups/BottomToolGroupService/InfoToolGroupService/EditorInfoToolGroupService';
export { default as ShortcutToolGroupServices } from './src/WaxToolGroups/BottomToolGroupService/ShotcutToolGroupService/ShortcutToolGroupService';
export {default as HelpToolGroupServices} from './src/WaxToolGroups/BottomToolGroupService/HelpToolGroupService/HelpToolGroupService';
export { default as TransformToolGroupService } from './src/WaxToolGroups/TransformToolGroupService/TransformToolGroupService';
import Service from "../Service";
import BottomInfoServices from "./index";
class BottomInfoService extends Service {
dependencies = BottomInfoServices;
}
export default BottomInfoService;
import Service from '../../Service'
import CounterInfoTool from "./CounterInfoTool"
export default class CounterInfoService extends Service {
register() {
this.container.bind('CounterInfoTool').to(CounterInfoTool);
}
}
import React from 'react';
import { isEmpty } from 'lodash';
import { injectable } from 'inversify';
import { EditorInfoTool } from 'wax-prosemirror-components';
// eslint-disable-next-line import/no-named-as-default,import/no-named-as-default-member
import Tools from '../../lib/Tools';
@injectable()
class CounterInfoTool extends Tools {
title = 'Counter Info';
icon = 'highlight';
name = 'CounterInfo';
get run() {
return () => true;
}
get enable() {
return state => {
return true;
};
}
renderTool(view) {
if (isEmpty(view)) return null;
// eslint-disable-next-line no-underscore-dangle
return this._isDisplayed ? (
<EditorInfoTool key="CounterInfo" item={this.toJSON()} view={view} />
) : null;
}
}
export default CounterInfoTool;
\ No newline at end of file
import Service from '../../Service'
import HelpTool from './HelpTool';
export default class HelpService extends Service {
register() {
this.container.bind('HelpTool').to(HelpTool);
}
}
import { injectable } from 'inversify';
// eslint-disable-next-line import/no-named-as-default,import/no-named-as-default-member
import Tools from '../../lib/Tools';
@injectable()
class HelpTool extends Tools {
title = 'Help';
icon = 'help';
name = 'HelpTool';
get run() {
return () => true;
}
}
export default HelpTool;
\ No newline at end of file
import Service from '../../Service'
import ShortcutTool from './ShortcutTool';
export default class ShortcutService extends Service {
register() {
this.container.bind('ShortcutTool').to(ShortcutTool);
}
}
import { injectable } from 'inversify';
// eslint-disable-next-line import/no-named-as-default,import/no-named-as-default-member
import Tools from '../../lib/Tools';
@injectable()
class ShortcutTool extends Tools {
title = 'Shortcut';
icon = 'fullScreen';
name = 'Shortcut';
get run() {
return () => true;
}
}
export default ShortcutTool;
\ No newline at end of file