diff --git a/app/README.md b/README.md
similarity index 100%
rename from app/README.md
rename to README.md
diff --git a/app/src/js/i18n/build-dictionary.js b/app/src/js/i18n/build-dictionary.js
index bed349ceb..e64d7a2c9 100644
--- a/app/src/js/i18n/build-dictionary.js
+++ b/app/src/js/i18n/build-dictionary.js
@@ -78,7 +78,4 @@ export const getMessageForSecondLang = message => {
export default createDictionary(getLang());
-export const bauhausLibraryDictionary = createDictionary(
- getLang(),
- bauhausLibrary
-);
+export const bauhausLibraryDictionary = createDictionary(getLang(), dictionary);
diff --git a/packages/bauhaus-library/package.json b/packages/bauhaus-library/package.json
index 22518ac2c..49afa0c85 100644
--- a/packages/bauhaus-library/package.json
+++ b/packages/bauhaus-library/package.json
@@ -47,6 +47,7 @@
"useTabs": true
},
"dependencies": {
+ "lodash": "^4.17.15",
"react-loading": "^2.0.3",
"react-select": "^3.0.4"
}
diff --git a/packages/bauhaus-library/src/panel/index.js b/packages/bauhaus-library/src/panel/index.js
index cf2e11adb..8be56d11e 100644
--- a/packages/bauhaus-library/src/panel/index.js
+++ b/packages/bauhaus-library/src/panel/index.js
@@ -3,20 +3,19 @@ import PropTypes from 'prop-types';
import Flag from '../flag';
import './panel.scss';
-function Panel({ title, children, context = 'concepts', flag }) {
- const flagComponent = flag ? ` ( ${} )` : '';
- return (
-
-
-
- {title}
- {flagComponent}
-
-
-
{children}
+const Panel = ({ title, children, context = 'concepts', flag }) => (
+
+
+
+ {title}
+ {flag && ` ( `}
+ {flag && }
+ {flag && ` )`}
+
- );
-}
+
{children}
+
+);
Panel.propTypes = {
title: PropTypes.oneOfType([PropTypes.string, PropTypes.object]).isRequired,
diff --git a/packages/bauhaus-library/src/search-rmes/index.js b/packages/bauhaus-library/src/search-rmes/index.js
index f9f9dc98d..8ed37c038 100644
--- a/packages/bauhaus-library/src/search-rmes/index.js
+++ b/packages/bauhaus-library/src/search-rmes/index.js
@@ -3,7 +3,7 @@ import I18NContext from '../i18n-provider';
import PropTypes from 'prop-types';
import { Link } from 'react-router-dom';
import Pagination from '../pagination';
-import { filterKeyDeburr, nbResults } from 'js/utils/array-utils';
+import { filterKeyDeburr, nbResults } from '../utils/array-utils';
function SearchRmes({
items = [],
@@ -17,7 +17,7 @@ function SearchRmes({
label,
}) {
const [search, handleSearch] = useState('');
- const D = useContext(I18NContext).backToTop || label;
+ const D = useContext(I18NContext);
const filter = filterKeyDeburr(
Object.keys(items[0] || {}).filter(k => k !== 'id')
@@ -42,7 +42,7 @@ function SearchRmes({
value={search}
onChange={e => handleSearch(e.target.value)}
type="text"
- placeholder={D.searchLabelPlaceholder}
+ placeholder={D.searchLabelPlaceholder || placeholder}
className="form-control"
aria-label={D.search}
/>
@@ -64,7 +64,7 @@ function SearchRmes({
)}
-
{nbResults(hits)}
+
{nbResults(hits, D)}
diff --git a/packages/bauhaus-library/src/utils/array-utils.js b/packages/bauhaus-library/src/utils/array-utils.js
new file mode 100644
index 000000000..b93df0fd4
--- /dev/null
+++ b/packages/bauhaus-library/src/utils/array-utils.js
@@ -0,0 +1,20 @@
+import _ from 'lodash';
+
+export const filterKeyDeburr = keys => rawStr => {
+ const str = _.deburr(rawStr).toLocaleLowerCase();
+ return item => {
+ let isIn = false;
+ for (var i = 0; i < keys.length; i++) {
+ if (_.deburr((item[keys[i]] || '').toLocaleLowerCase()).includes(str)) {
+ isIn = true;
+ break;
+ }
+ }
+ return isIn;
+ };
+};
+
+export const nbResults = (array, dictionnary) => {
+ const { result, results } = dictionnary;
+ return `${array.length} ${array.length > 1 ? results : result}`;
+};
diff --git a/packages/bauhaus-library/src/utils/array-utils.spec.js b/packages/bauhaus-library/src/utils/array-utils.spec.js
new file mode 100644
index 000000000..1b57088be
--- /dev/null
+++ b/packages/bauhaus-library/src/utils/array-utils.spec.js
@@ -0,0 +1,16 @@
+import * as A from './array-utils';
+
+const D = { result: 'result', results: 'results' };
+
+describe('array utils', () => {
+ describe('nbResults', () => {
+ it('should return string ends with any letter', () => {
+ expect(A.nbResults([], D)).toMatch(/[A-Za-z]{1}$/);
+ expect(A.nbResults(['A'], D)).toMatch(/[A-Za-z]{1}$/);
+ });
+
+ it("should return string ends with 's'", () => {
+ expect(A.nbResults(['a', 'b'], D).endsWith('s')).toBeTruthy();
+ });
+ });
+});
diff --git a/src/js/actions/classifications/correspondences/association.spec.js b/src/js/actions/classifications/correspondences/association.spec.js
deleted file mode 100644
index 152fec7f5..000000000
--- a/src/js/actions/classifications/correspondences/association.spec.js
+++ /dev/null
@@ -1,38 +0,0 @@
-import getCorrespondenceAssociation from './association';
-import * as A from 'js/actions/constants';
-import api from 'js/remote-api/classifications-api';
-
-const dispatch = jest.fn();
-jest.mock('js/remote-api/classifications-api');
-
-describe('Associations actions', () => {
- it('should call dispatch LOAD_CLASSIFICATION_CORRESPONDENCE_ASSOCIATIONS_SUCCESS action with the right data', async () => {
- api.getCorrespondenceAssociation = function() {
- return Promise.resolve('results');
- };
- await getCorrespondenceAssociation(1, 2)(dispatch);
- expect(dispatch).toHaveBeenCalledWith({
- type: A.LOAD_CLASSIFICATION_CORRESPONDENCE_ASSOCIATION,
- payload: { correspondenceId: 1, associationId: 2 },
- });
- expect(dispatch).toHaveBeenLastCalledWith({
- type: A.LOAD_CLASSIFICATION_CORRESPONDENCE_ASSOCIATION_SUCCESS,
- payload: { correspondenceId: 1, associationId: 2, results: 'results' },
- });
- });
-
- it('should call dispatch LOAD_CLASSIFICATION_CORRESPONDENCE_ASSOCIATIONS_FAILURE action with an error object', async () => {
- api.getCorrespondenceAssociation = function() {
- return Promise.reject('error');
- };
- await getCorrespondenceAssociation(1, 2)(dispatch);
- expect(dispatch).toHaveBeenCalledWith({
- type: A.LOAD_CLASSIFICATION_CORRESPONDENCE_ASSOCIATION,
- payload: { correspondenceId: 1, associationId: 2 },
- });
- expect(dispatch).toHaveBeenLastCalledWith({
- type: A.LOAD_CLASSIFICATION_CORRESPONDENCE_ASSOCIATION_FAILURE,
- payload: { err: 'error', correspondenceId: 1, associationId: 2 },
- });
- });
-});
diff --git a/src/js/actions/classifications/correspondences/associations.spec.js b/src/js/actions/classifications/correspondences/associations.spec.js
deleted file mode 100644
index 1946a00e2..000000000
--- a/src/js/actions/classifications/correspondences/associations.spec.js
+++ /dev/null
@@ -1,38 +0,0 @@
-import getCorrespondenceAssociations from './associations';
-import * as A from 'js/actions/constants';
-import api from 'js/remote-api/classifications-api';
-
-const dispatch = jest.fn();
-jest.mock('js/remote-api/classifications-api');
-
-describe('Associations actions', () => {
- it('should call dispatch LOAD_CLASSIFICATION_CORRESPONDENCE_ASSOCIATIONS_SUCCESS action with the right data', async () => {
- api.getCorrespondenceAssociations = function() {
- return Promise.resolve('results');
- };
- await getCorrespondenceAssociations(1)(dispatch);
- expect(dispatch).toHaveBeenCalledWith({
- type: A.LOAD_CLASSIFICATION_CORRESPONDENCE_ASSOCIATIONS,
- payload: { id: 1 },
- });
- expect(dispatch).toHaveBeenLastCalledWith({
- type: A.LOAD_CLASSIFICATION_CORRESPONDENCE_ASSOCIATIONS_SUCCESS,
- payload: { id: 1, results: 'results' },
- });
- });
-
- it('should call dispatch LOAD_CLASSIFICATION_CORRESPONDENCE_ASSOCIATIONS_FAILURE action with an error object', async () => {
- api.getCorrespondenceAssociations = function() {
- return Promise.reject('error');
- };
- await getCorrespondenceAssociations(1)(dispatch);
- expect(dispatch).toHaveBeenCalledWith({
- type: A.LOAD_CLASSIFICATION_CORRESPONDENCE_ASSOCIATIONS,
- payload: { id: 1 },
- });
- expect(dispatch).toHaveBeenLastCalledWith({
- type: A.LOAD_CLASSIFICATION_CORRESPONDENCE_ASSOCIATIONS_FAILURE,
- payload: { err: 'error', id: 1 },
- });
- });
-});
diff --git a/src/js/components/operations/families/edition/validation.spec.js b/src/js/components/operations/families/edition/validation.spec.js
deleted file mode 100644
index c0887254d..000000000
--- a/src/js/components/operations/families/edition/validation.spec.js
+++ /dev/null
@@ -1,36 +0,0 @@
-import { validate } from './validation';
-
-describe('validation family', () => {
- it('should return an error if the prefLabelLg1 is not defined', () => {
- expect(validate({ prefLabelLg2: 'prefLabelLg2' })).toEqual({
- errorMessage: 'The title is required',
- fields: {
- prefLabelLg1: true,
- prefLabelLg2: false,
- },
- });
- });
- it('should return an error if the prefLabelLg2 is not defined', () => {
- expect(validate({ prefLabelLg1: 'prefLabelLg1' })).toEqual({
- errorMessage: 'The title is required',
- fields: {
- prefLabelLg1: false,
- prefLabelLg2: true,
- },
- });
- });
- it('should not return any errors', () => {
- expect(
- validate({
- prefLabelLg1: 'prefLabelLg1',
- prefLabelLg2: 'prefLabelLg2',
- })
- ).toEqual({
- errorMessage: '',
- fields: {
- prefLabelLg1: false,
- prefLabelLg2: false,
- },
- });
- });
-});
diff --git a/src/js/components/operations/operations/edition/validation.spec.js b/src/js/components/operations/operations/edition/validation.spec.js
deleted file mode 100644
index b0c23bc2b..000000000
--- a/src/js/components/operations/operations/edition/validation.spec.js
+++ /dev/null
@@ -1,56 +0,0 @@
-import { validate } from './validation';
-
-describe('validation operations', () => {
- it('should return an error if the prefLabelLg1 is not defined', () => {
- expect(
- validate({ prefLabelLg2: 'prefLabelLg2', series: 'series' })
- ).toEqual({
- errorMessage: 'The title is required',
- fields: {
- series: false,
- prefLabelLg1: true,
- prefLabelLg2: false,
- },
- });
- });
- it('should return an error if the prefLabelLg2 is not defined', () => {
- expect(
- validate({ prefLabelLg1: 'prefLabelLg1', series: 'series' })
- ).toEqual({
- errorMessage: 'The title is required',
- fields: {
- series: false,
- prefLabelLg1: false,
- prefLabelLg2: true,
- },
- });
- });
- it('should return an error if the series is not defined', () => {
- expect(
- validate({ prefLabelLg1: 'prefLabelLg1', prefLabelLg2: 'prefLabelLg2' })
- ).toEqual({
- errorMessage: 'The series is required',
- fields: {
- series: true,
- prefLabelLg1: false,
- prefLabelLg2: false,
- },
- });
- });
- it('should not return any errors', () => {
- expect(
- validate({
- prefLabelLg1: 'prefLabelLg1',
- prefLabelLg2: 'prefLabelLg2',
- series: 'series',
- })
- ).toEqual({
- errorMessage: '',
- fields: {
- series: false,
- prefLabelLg1: false,
- prefLabelLg2: false,
- },
- });
- });
-});
diff --git a/src/js/components/operations/series/edition/validation.spec.js b/src/js/components/operations/series/edition/validation.spec.js
deleted file mode 100644
index d8c80713d..000000000
--- a/src/js/components/operations/series/edition/validation.spec.js
+++ /dev/null
@@ -1,56 +0,0 @@
-import { validate } from './validation';
-
-describe('validation series', () => {
- it('should return an error if the prefLabelLg1 is not defined', () => {
- expect(
- validate({ prefLabelLg2: 'prefLabelLg2', family: 'family' })
- ).toEqual({
- errorMessage: 'The title is required',
- fields: {
- family: false,
- prefLabelLg1: true,
- prefLabelLg2: false,
- },
- });
- });
- it('should return an error if the prefLabelLg2 is not defined', () => {
- expect(
- validate({ prefLabelLg1: 'prefLabelLg1', family: 'family' })
- ).toEqual({
- errorMessage: 'The title is required',
- fields: {
- family: false,
- prefLabelLg1: false,
- prefLabelLg2: true,
- },
- });
- });
- it('should return an error if the family is not defined', () => {
- expect(
- validate({ prefLabelLg1: 'prefLabelLg1', prefLabelLg2: 'prefLabelLg2' })
- ).toEqual({
- errorMessage: 'The family is required',
- fields: {
- family: true,
- prefLabelLg1: false,
- prefLabelLg2: false,
- },
- });
- });
- it('should not return any errors', () => {
- expect(
- validate({
- prefLabelLg1: 'prefLabelLg1',
- prefLabelLg2: 'prefLabelLg2',
- family: 'family',
- })
- ).toEqual({
- errorMessage: '',
- fields: {
- family: false,
- prefLabelLg1: false,
- prefLabelLg2: false,
- },
- });
- });
-});
diff --git a/src/js/components/operations/shared/relations/index.spec.js b/src/js/components/operations/shared/relations/index.spec.js
deleted file mode 100644
index f5c3266f7..000000000
--- a/src/js/components/operations/shared/relations/index.spec.js
+++ /dev/null
@@ -1,189 +0,0 @@
-import React from 'react';
-import RelationsView, {
- RelationsViewPerLg,
- RelationsViewPerLgContent,
-} from './index';
-import { shallow } from 'enzyme';
-import { Note } from 'js/components/shared/note/note';
-import { Link } from 'react-router-dom';
-
-describe('RelationsView', () => {
- it('should display only the first lang', () => {
- const component = shallow(
-
- );
- const relationsViewPerLg = component.find(RelationsViewPerLg);
- expect(relationsViewPerLg.length).toBe(1);
- expect(relationsViewPerLg.props().langSuffix).toBe('Lg1');
- expect(relationsViewPerLg.props().currentLang).toBe('Lg1');
- });
-
- it('should display the first and second langs', () => {
- const component = shallow(
-
- );
- const relationsViewPerLg = component.find(RelationsViewPerLg);
- expect(relationsViewPerLg.length).toBe(2);
- expect(relationsViewPerLg.get(0).props.langSuffix).toBe('Lg1');
- expect(relationsViewPerLg.get(0).props.currentLang).toBe('Lg1');
-
- expect(relationsViewPerLg.get(1).props.langSuffix).toBe('Lg2');
- expect(relationsViewPerLg.get(1).props.currentLang).toBe('Lg2');
- });
-});
-
-describe('RelationsViewPerLgContent', () => {
- describe('parent', () => {
- it('should not display the title if the parent is not defined', () => {
- const component = shallow(
-
- );
-
- expect(component.find('.linksTitle').length).toBe(0);
- });
- it('should display the title if the parent is defined', () => {
- const component = shallow(
-
- );
-
- expect(
- component
- .find('.linksTitle')
- .html()
- .includes('parentTitle')
- ).toBeTruthy();
- });
- it('should display a link to the parent', () => {
- const component = shallow(
-
- );
-
- const link = component.find(Link).get(0);
- expect(link.props.to).toBe('/operations/parentPath/1');
- expect(link.props.children).toBe('labelLg1');
- });
- });
-
- describe('children', () => {
- it('should not display the title if the children are not defined', () => {
- const component = shallow(
-
- );
-
- expect(component.find('.linksTitle').length).toBe(1);
- });
- it('should display the title if the children are defined', () => {
- const component = shallow(
-
- );
-
- expect(component.find('.linksTitle').length).toBe(1);
- expect(
- component
- .find('.linksTitle')
- .html()
- .includes('childrenTitle')
- ).toBeTruthy();
- });
-
- it('should display a link per child', () => {
- const component = shallow(
-
- );
-
- expect(component.find('li').length).toBe(3);
-
- const links = component.find(Link);
- expect(links.length).toBe(3);
-
- expect(links.get(0).props.to).toBe('/operations/childrenPath/0');
- expect(links.get(0).props.children).toBe('label1');
-
- expect(links.get(1).props.to).toBe('/operations/childrenPath/1');
- expect(links.get(1).props.children).toBe('label2');
-
- expect(links.get(2).props.to).toBe('/operations/childrenPath/2');
- expect(links.get(2).props.children).toBe('label3');
- });
-
- it('should sort children alphabetically', () => {
- const component = shallow(
-
- );
-
- expect(component.find('li').length).toBe(3);
-
- const links = component.find(Link);
- expect(links.length).toBe(3);
-
- expect(links.get(0).props.to).toBe('/operations/childrenPath/0');
- expect(links.get(0).props.children).toBe('label1');
-
- expect(links.get(1).props.to).toBe('/operations/childrenPath/1');
- expect(links.get(1).props.children).toBe('label2');
-
- expect(links.get(2).props.to).toBe('/operations/childrenPath/2');
- expect(links.get(2).props.children).toBe('label3');
- });
- });
-});
-describe('RelationsViewPerLg', () => {
- it('should display one Note', () => {
- const component = shallow(
-
- );
-
- const note = component.find(Note);
- expect(note.length).toBe(1);
-
- const props = note.props();
- expect(props.allowEmpty).toBeTruthy();
- expect(props.title).toBe('title');
- expect(props.lang).toBe('lg1');
- expect(props.alone).toBeTruthy();
- });
-});
diff --git a/src/js/utils/draftjs/draftjsToMd.js b/src/js/utils/draftjs/draftjsToMd.js
deleted file mode 100644
index d77771703..000000000
--- a/src/js/utils/draftjs/draftjsToMd.js
+++ /dev/null
@@ -1,210 +0,0 @@
-const defaultMarkdownDict = {
- BOLD: "__",
- ITALIC: "*",
- STRIKETHROUGH: "+"
-};
-
-const RGB_REGEXP = /((bg)?color)-rgb\((.*)\)/;
-
-const blockStyleDict = {
- "unordered-list-item": "- ",
- "header-one": "# ",
- "header-two": "## ",
- "header-three": "### ",
- "header-four": "#### ",
- "header-five": "##### ",
- "header-six": "###### ",
- blockquote: "> "
-};
-
-const wrappingBlockStyleDict = {
- "code-block": "```"
-};
-
-const getBlockStyle = (currentStyle, appliedBlockStyles) => {
- if (currentStyle === "ordered-list-item") {
- const counter = appliedBlockStyles.reduce((prev, style) => {
- if (style === "ordered-list-item") {
- return prev + 1;
- }
- return prev;
- }, 1);
- return `${counter}. `;
- }
- return blockStyleDict[currentStyle] || "";
-};
-
-const applyWrappingBlockStyle = (currentStyle, content) => {
- if (currentStyle in wrappingBlockStyleDict) {
- const wrappingSymbol = wrappingBlockStyleDict[currentStyle];
- return `${wrappingSymbol}\n${content}\n${wrappingSymbol}`;
- }
-
- return content;
-};
-
-const applyAtomicStyle = (block, entityMap, content) => {
- if (block.type !== "atomic") return content;
- // strip the test that was added in the media block
- const strippedContent = content.substring(
- 0,
- content.length - block.text.length
- );
- const key = block.entityRanges[0].key;
- const type = entityMap[key].type;
- const data = entityMap[key].data;
- if (type === "draft-js-video-plugin-video") {
- return `${strippedContent}[[ embed url=${data.url || data.src} ]]`;
- }
- return `${strippedContent}![${data.fileName || ""}](${data.url || data.src})`;
-};
-
-const getEntityStart = entity => {
- switch (entity.type) {
- case "LINK":
- return "[";
- default:
- return "";
- }
-};
-
-const getEntityEnd = entity => {
- switch (entity.type) {
- case "LINK":
- return `](${entity.data.url})`;
- default:
- return "";
- }
-};
-
-function fixWhitespacesInsideStyle(text, style) {
- const { symbol } = style;
-
- // Text before style-opening marker (including the marker)
- const pre = text.slice(0, style.range.start);
- // Text between opening and closing markers
- const body = text.slice(style.range.start, style.range.end);
- // Trimmed text between markers
- const bodyTrimmed = body.trim();
- // Text after closing marker
- const post = text.slice(style.range.end);
-
- const bodyTrimmedStart = style.range.start + body.indexOf(bodyTrimmed);
-
- // Text between opening marker and trimmed content (leading spaces)
- const prefix = text.slice(style.range.start, bodyTrimmedStart);
- // Text between the end of trimmed content and closing marker (trailing spaces)
- const postfix = text.slice(
- bodyTrimmedStart + bodyTrimmed.length,
- style.range.end
- );
-
- // Temporary text that contains trimmed content wrapped into original pre- and post-texts
- const newText = `${pre}${bodyTrimmed}${post}`;
- // Insert leading and trailing spaces between pre-/post- contents and their respective markers
- return newText.replace(
- `${symbol}${bodyTrimmed}${symbol}`,
- `${prefix}${symbol}${bodyTrimmed}${symbol}${postfix}`
- );
-}
-
-function getInlineStyleRangesByLength(inlineStyleRanges) {
- return [...inlineStyleRanges].sort((a, b) => b.length - a.length);
-}
-
-export function draftjsToMd(raw, extraMarkdownDict) {
- const markdownDict = { ...defaultMarkdownDict, ...extraMarkdownDict };
- const appliedBlockStyles = [];
-
- return raw.blocks
- .map(block => {
- // totalOffset is a difference of index position between raw string and enhanced ones
- let totalOffset = 0;
- let returnString = "";
-
- // add block style
- returnString += getBlockStyle(block.type, appliedBlockStyles);
- appliedBlockStyles.push(block.type);
-
- const appliedStyles = [];
- returnString += block.text
- .split("")
- .reduce((text, currentChar, index) => {
- let newText = text;
-
- const sortedInlineStyleRanges = getInlineStyleRangesByLength(
- block.inlineStyleRanges
- );
-
- // find all styled at this character
- sortedInlineStyleRanges
- .filter(range => range.offset === index)
- .filter(
- range => markdownDict[range.style] || RGB_REGEXP.test(range.style)
- )
- .forEach(currentStyle => {
- let symbol;
- let symbolLength;
- if (RGB_REGEXP.test(currentStyle.style)) {
- symbol = `${currentStyle.style}`;
- symbolLength = symbol.length;
- newText += symbol;
- totalOffset += symbolLength;
- } else {
- symbolLength = markdownDict[currentStyle.style].length;
- newText += markdownDict[currentStyle.style];
- totalOffset += symbolLength;
- symbol = markdownDict[currentStyle.style];
- }
-
- appliedStyles.push({
- symbol,
- range: {
- start: currentStyle.offset + totalOffset,
- end: currentStyle.offset + currentStyle.length + totalOffset
- },
- end: currentStyle.offset + (currentStyle.length - 1)
- });
- });
-
- // check for entityRanges starting and add if existing
- const entitiesStartAtChar = block.entityRanges.filter(
- range => range.offset === index
- );
- entitiesStartAtChar.forEach(entity => {
- newText += getEntityStart(raw.entityMap[entity.key]);
- });
-
- // add the current character to the md string
- newText += currentChar;
-
- // check for entityRanges ending and add if existing
- const entitiesEndAtChar = block.entityRanges.filter(
- range => range.offset + range.length - 1 === index
- );
- entitiesEndAtChar.forEach(entity => {
- newText += getEntityEnd(raw.entityMap[entity.key]);
- });
-
- // apply the 'ending' tags for any styles that end in the current position in order (stack)
- while (
- appliedStyles.length !== 0 &&
- appliedStyles[appliedStyles.length - 1].end === index
- ) {
- const endingStyle = appliedStyles.pop();
- newText += endingStyle.symbol;
-
- newText = fixWhitespacesInsideStyle(newText, endingStyle);
- totalOffset += endingStyle.symbol.length;
- }
-
- return newText;
- }, "");
-
- returnString = applyWrappingBlockStyle(block.type, returnString);
- returnString = applyAtomicStyle(block, raw.entityMap, returnString);
-
- return returnString;
- })
- .join("\n");
-}
diff --git a/src/js/utils/draftjs/mdToDraftjs.js b/src/js/utils/draftjs/mdToDraftjs.js
deleted file mode 100644
index 0381856cd..000000000
--- a/src/js/utils/draftjs/mdToDraftjs.js
+++ /dev/null
@@ -1,321 +0,0 @@
-const parse = require('@textlint/markdown-to-ast').parse;
-
-const defaultInlineStyles = {
- Strong: {
- type: 'BOLD',
- symbol: '__',
- },
- Emphasis: {
- type: 'ITALIC',
- symbol: '*',
- },
- STRIKETHROUGH: {
- type: 'STRIKETHROUGH',
- symbol: '+',
- },
-};
-
-export const REGEXPS = [
- {
- regexp: /^(\+)/,
- type: defaultInlineStyles.STRIKETHROUGH.type,
- },
- {
- regexp: /^((bg)?color-rgb\(\d*,\d*,\d*\))/,
- },
-];
-
-const defaultBlockStyles = {
- List: 'unordered-list-item',
- Header1: 'header-one',
- Header2: 'header-two',
- Header3: 'header-three',
- Header4: 'header-four',
- Header5: 'header-five',
- Header6: 'header-six',
- CodeBlock: 'code-block',
- BlockQuote: 'blockquote',
-};
-
-const getBlockStyleForMd = (node, blockStyles) => {
- const style = node.type;
- const ordered = node.ordered;
- const depth = node.depth;
- if (style === 'List' && ordered) {
- return 'ordered-list-item';
- } else if (style === 'Header') {
- return blockStyles[`${style}${depth}`];
- } else if (
- node.type === 'Paragraph' &&
- node.children &&
- node.children[0] &&
- node.children[0].type === 'Image'
- ) {
- return 'atomic';
- } else if (
- node.type === 'Paragraph' &&
- node.raw &&
- node.raw.match(/^\[\[\s\S+\s.*\S+\s\]\]/)
- ) {
- return 'atomic';
- }
- return blockStyles[style];
-};
-
-const joinCodeBlocks = splitMd => {
- const opening = splitMd.indexOf('```');
- const closing = splitMd.indexOf('```', opening + 1);
-
- if (opening >= 0 && closing >= 0) {
- const codeBlock = splitMd.slice(opening, closing + 1);
- const codeBlockJoined = codeBlock.join('\n');
- const updatedSplitMarkdown = [
- ...splitMd.slice(0, opening),
- codeBlockJoined,
- ...splitMd.slice(closing + 1),
- ];
-
- return joinCodeBlocks(updatedSplitMarkdown);
- }
-
- return splitMd;
-};
-
-const splitMdBlocks = md => {
- const splitMd = md.split('\n');
-
- // Process the split markdown include the
- // one syntax where there's an block level opening
- // and closing symbol with content in the middle.
- const splitMdWithCodeBlocks = joinCodeBlocks(splitMd);
- return splitMdWithCodeBlocks;
-};
-
-const parseMdLine = (line, existingEntities, extraStyles = {}) => {
- const inlineStyles = { ...defaultInlineStyles, ...extraStyles.inlineStyles };
- const blockStyles = { ...defaultBlockStyles, ...extraStyles.blockStyles };
-
- const astString = parse(line);
- let text = '';
- const inlineStyleRanges = [];
- const entityRanges = [];
- const entityMap = existingEntities;
-
- const addInlineStyleRange = (offset, length, style) => {
- inlineStyleRanges.push({ offset, length, style });
- };
-
- const getRawLength = children =>
- children.reduce(
- (prev, current) => prev + (current.value ? current.value.length : 0),
- 0
- );
-
- const addLink = child => {
- const entityKey = Object.keys(entityMap).length;
- entityMap[entityKey] = {
- type: 'LINK',
- mutability: 'MUTABLE',
- data: {
- url: child.url,
- },
- };
- entityRanges.push({
- key: entityKey,
- length: getRawLength(child.children),
- offset: text.length,
- });
- };
-
- const addImage = child => {
- const entityKey = Object.keys(entityMap).length;
- entityMap[entityKey] = {
- type: 'IMAGE',
- mutability: 'IMMUTABLE',
- data: {
- url: child.url,
- src: child.url,
- fileName: child.alt || '',
- },
- };
- entityRanges.push({
- key: entityKey,
- length: 1,
- offset: text.length,
- });
- };
-
- const addVideo = child => {
- const string = child.raw;
-
- // RegEx: [[ embed url= ]]
- const url = string.match(/^\[\[\s(?:embed)\s(?:url=(\S+))\s\]\]/)[1];
-
- const entityKey = Object.keys(entityMap).length;
- entityMap[entityKey] = {
- type: 'draft-js-video-plugin-video',
- mutability: 'IMMUTABLE',
- data: {
- src: url,
- },
- };
- entityRanges.push({
- key: entityKey,
- length: 1,
- offset: text.length,
- });
- };
-
- const parseChildren = (child, style) => {
- // RegEx: [[ embed url= ]]
- const videoShortcodeRegEx = /^\[\[\s(?:embed)\s(?:url=(\S+))\s\]\]/;
- switch (child.type) {
- case 'Link':
- addLink(child);
- break;
- case 'Image':
- addImage(child);
- break;
- case 'Paragraph':
- if (videoShortcodeRegEx.test(child.raw)) {
- addVideo(child);
- }
- break;
- default:
- }
- if (!videoShortcodeRegEx.test(child.raw) && child.children && style) {
- const rawLength = getRawLength(child.children);
- addInlineStyleRange(text.length, rawLength, style.type);
- const newStyle = inlineStyles[child.type];
- child.children.forEach(grandChild => {
- parseChildren(grandChild, newStyle);
- });
- } else if (!videoShortcodeRegEx.test(child.raw) && child.children) {
- const newStyle = inlineStyles[child.type];
- child.children.forEach(grandChild => {
- parseChildren(grandChild, newStyle);
- });
- } else {
- if (style) {
- addInlineStyleRange(text.length, child.value.length, style.type);
- }
- if (inlineStyles[child.type]) {
- addInlineStyleRange(
- text.length,
- child.value.length,
- inlineStyles[child.type].type
- );
- }
-
- if (child.type === 'Str') {
- let i = 0;
- let startIndex = null;
- let finalText = '';
-
- const REGEXPS = [
- {
- regexp: /^(\+)/,
- type: inlineStyles.STRIKETHROUGH.type,
- },
- {
- regexp: /^((bg)?color-rgb\(\d*,\d*,\d*\))/,
- },
- ];
-
- let removedSymbolLength = 0;
- const regexpPredicate = reg => reg.regexp.test(child.value.substr(i));
- while (i < child.value.length) {
- const regexpConfig = REGEXPS.find(regexpPredicate);
- if (regexpConfig) {
- const matches = child.value.substr(i).match(regexpConfig.regexp);
- const symbol = matches[1];
- if (startIndex === null) {
- startIndex = i + text.length - removedSymbolLength;
- i += symbol.length - 1;
- } else {
- addInlineStyleRange(
- startIndex,
- i -
- startIndex -
- symbol.length -
- removedSymbolLength +
- text.length,
- regexpConfig.type || symbol
- );
- removedSymbolLength += symbol.length * 2;
-
- startIndex = null;
- i += symbol.length - 1;
- }
- } else {
- finalText += child.value[i];
- }
-
- i++;
- }
-
- text = `${text}${finalText}`;
- } else {
- text = `${text}${
- child.type === 'Image' || videoShortcodeRegEx.test(child.raw)
- ? ' '
- : child.value
- }`;
- }
- }
- };
-
- astString.children.forEach(child => {
- const style = inlineStyles[child.type];
- parseChildren(child, style);
- });
-
- // add block style if it exists
- let blockStyle = 'unstyled';
- if (astString.children[0]) {
- const style = getBlockStyleForMd(astString.children[0], blockStyles);
- if (style) {
- blockStyle = style;
- }
- }
-
- return {
- text,
- inlineStyleRanges,
- entityRanges,
- blockStyle,
- entityMap,
- };
-};
-
-export function mdToDraftjs(mdString, extraStyles) {
- const paragraphs = splitMdBlocks(mdString);
- const blocks = [];
- let entityMap = {};
-
- paragraphs.forEach(paragraph => {
- const result = parseMdLine(paragraph, entityMap, extraStyles);
- blocks.push({
- text: result.text,
- type: result.blockStyle,
- depth: 0,
- inlineStyleRanges: result.inlineStyleRanges,
- entityRanges: result.entityRanges,
- });
- entityMap = result.entityMap;
- });
-
- // add a default value
- // not sure why that's needed but Draftjs convertToRaw fails without it
- if (Object.keys(entityMap).length === 0) {
- entityMap = {
- data: '',
- mutability: '',
- type: '',
- };
- }
- return {
- blocks,
- entityMap,
- };
-}