Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/checklist block #3

Merged
merged 3 commits into from
Apr 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
File renamed without changes.
File renamed without changes.
73 changes: 73 additions & 0 deletions custom-blocks/checklist/src/index.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
.cdx-checklist {
position: relative;
}

@media all and (min-width: 736px) {
.cdx-checklist {
padding-left: 36px;
}
}

.cdx-checklist [contentEditable=true][data-placeholder]::before{
position: absolute;
content: attr(data-placeholder);
color: #707684;
font-weight: normal;
opacity: 0;
}

.cdx-checklist [contentEditable=true][data-placeholder]:empty::before {
opacity: 1;
}

.cdx-checklist [contentEditable=true][data-placeholder]:empty:focus::before {
opacity: 0;
}

.cdx-checklist::before {
content: '';
background-image: url("data:image/svg+xml,%3Csvg width='24' height='24' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M19 21L5 21C4.46957 21 3.96086 20.7893 3.58579 20.4142C3.21071 20.0391 3 19.5304 3 19L3 5C3 4.46957 3.21071 3.96086 3.58579 3.58579C3.96086 3.21071 4.46957 3 5 3L19 3C19.5304 3 20.0391 3.21071 20.4142 3.58579C20.7893 3.96086 21 4.46957 21 5L21 19C21 19.5304 20.7893 20.0391 20.4142 20.4142C20.0391 20.7893 19.5304 21 19 21Z' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3Cpath d='M8 10L12 14L16 10' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
width: 24px;
height: 24px;
background-size: 24px 24px;
position: absolute;
margin-top: 8px;
left: 0;
}

@media all and (max-width: 735px) {
.cdx-checklist::before {
display: none;
}
}

.cdx-checklist__title {
margin-bottom: 20px;
}

.cdx-checklist__item {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 10px;
}

.cdx-checklist__item-input {
flex-grow: 1;
margin-right: 10px; /* Adjust spacing between input and button */
}

.cdx-checklist__item-button {
flex-basis: auto; /* Adjust based on the size of your button */
}

.cdx-button {
background-color: #f5f5f5;
border: none;
padding: 8px 16px;
cursor: pointer;
}

.cdx-button:hover {
background-color: #e0e0e0;
}
134 changes: 134 additions & 0 deletions custom-blocks/checklist/src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
/**
* Import Tool's icon
*/
import { IconCopy } from '@codexteam/icons';

/**
* Build styles
*/
import './index.css';

export default class Checklist {

static get isReadOnlySupported() {
return true;
}

static get toolbox() {
return {
icon: IconCopy,
title: 'Checklist',
};
}

static get enableLineBreaks() {
return true;
}

static get DEFAULT_TITLE_PLACEHOLDER() {
return 'Title';
}

get CSS() {
return {
baseClass: this.api.styles.block,
wrapper: 'cdx-checklist',
title: 'cdx-checklist__title',
input: this.api.styles.input,
item: 'cdx-checklist__item',
button: 'cdx-button',
};
}

constructor({ data, config, api, readOnly }) {
this.api = api;
this.readOnly = readOnly;

this.titlePlaceholder = config.titlePlaceholder || Checklist.DEFAULT_TITLE_PLACEHOLDER;

this.data = {
title: data.title || '',
items: data.items || [],
};
}

render() {
const container = this._make('div', [this.CSS.baseClass, this.CSS.wrapper]);
const title = this._make('div', [this.CSS.input, this.CSS.title], {
contentEditable: !this.readOnly,
innerHTML: this.data.title,
});

title.dataset.placeholder = this.titlePlaceholder;

container.appendChild(title);

this.data.items.forEach(item => {
container.appendChild(this.createItemElement(item));
});

const addButton = this._make('button', [this.CSS.button], {
innerHTML: 'Add item',
});
addButton.onclick = () => {
container.insertBefore(this.createItemElement(''), addButton);
};

container.appendChild(addButton);

return container;
}

createItemElement(itemText) {
const item = this._make('div', ['cdx-checklist__item']);

const input = this._make('div', ['cdx-checklist__item-input', this.CSS.input, this.CSS.item], {
contentEditable: !this.readOnly,
innerHTML: itemText,
});

const removeButton = this._make('button', ['cdx-checklist__item-button', this.CSS.button], {
innerHTML: 'Remove',
});
removeButton.onclick = () => item.remove();

item.appendChild(input);
item.appendChild(removeButton);

return item;
}

save(container) {
const title = container.querySelector(`.${this.CSS.title}`);
const items = [...container.querySelectorAll(`.${this.CSS.item}`)]
.map(item => item.textContent)
.filter(item => !item.endsWith('Remove')); // Not sure why it is like "['Item 1Remove', 'Item 1', 'Item 2Remove', 'Item 2']""
return {
title: title.innerHTML,
items,
};
}

_make(tagName, classNames = null, attributes = {}) {
const el = document.createElement(tagName);

if (Array.isArray(classNames)) {
el.classList.add(...classNames);
} else if (classNames) {
el.classList.add(classNames);
}

for (const attrName in attributes) {
el[attrName] = attributes[attrName];
}

return el;
}

static get sanitize() {
return {
title: {},
items: { br: true },
};
}
}
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
5 changes: 5 additions & 0 deletions custom-blocks/related-article/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
node_modules/*
npm-debug.log
.idea/
.DS_Store
dist
4 changes: 4 additions & 0 deletions custom-blocks/related-article/.npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
src/
.babelrc
vite.config.js
yarn.lock
File renamed without changes.
File renamed without changes.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
File renamed without changes.
10 changes: 10 additions & 0 deletions editorjs-renderer/src/transforms.ts
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,16 @@ const transforms: transforms = {
</div>`;
},

checklist: ({ data, id }) => {
const itemsList = data.items.map(item => `<li style="list-style-type: none; position: relative; padding-left: 30px; margin-top: 0px; margin-bottom: 10px;"><span style="color: #00C853; margin-right: 5px;">✔</span>${item}</li>`).join('');
return `<div style="background-color: #fcfcfc; padding: 10px 0px 10px 10px;">
<div style="display: flex; align-items: center; padding-bottom: 0px">
<div style="margin-left: 10px; font-weight: 600">${data.title}</div>
</div>
<ul style="padding-left: 0; margin-top: 0px;">${itemsList}</ul>
</div>`;
},

embed: ({ data, id }) => {
switch (data.service) {
case "vimeo":
Expand Down
2 changes: 2 additions & 0 deletions md-json-converter/src/core/cleanjson2md/blocksToMarkdown.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ const blocksToMarkdown = (blocks) => {
mdContent += `|ARTICLE title=${block.title} text=${block.text} href=${block.href} ARTICLE|\n\n`;
} else if (block.type === "note") {
mdContent += `|NOTE title=${block.title} message=${block.message} NOTE|\n\n`;
} else if (block.type === "checklist") {
mdContent += `|CHECKLIST title=${block.title} items=${block.items} CHECKLIST|\n\n`;
}
}

Expand Down
8 changes: 7 additions & 1 deletion md-json-converter/src/core/cleanjson2md/convertFromJson.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,13 @@ const convertFromJSON = (jsonData) => {
title: block.data.title,
message: block.data.message
});
}
} else if (block.type === "checklist") {
blocks.push({
type: "checklist",
title: block.data.title,
items: block.data.items
});
}
}

return blocks;
Expand Down
12 changes: 12 additions & 0 deletions md-json-converter/src/parsers/body/block-parsers/parseChecklist.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
const parseChecklist = (line) => {
const checklistMatch = line.match(/\|CHECKLIST title=(.+)\s+items=(.+)\s+CHECKLIST\|/);
if (checklistMatch) {
return {
type: "checklist",
title: checklistMatch[1],
items: checklistMatch[2].split(',').map(item => item.trim())
};
}
};

export default parseChecklist;
3 changes: 3 additions & 0 deletions md-json-converter/src/parsers/body/parseBlocks.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ class BlockFactory {
return { ...baseBlock, data: { title: block.title, text: block.text, href: block.href } };
case "note":
return { ...baseBlock, data: { title: block.title, message: block.message } };
case "checklist":
console.log('checklist switch')
return { ...baseBlock, data: { title: block.title, items: block.items } };
default:
throw new Error("Unsupported block type");
}
Expand Down
6 changes: 6 additions & 0 deletions md-json-converter/src/parsers/body/parseLine.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import parseCodeBlock from "./block-parsers/parseCode.js";
import parseTable from "./block-parsers/parseTable.js";
import parseArticle from "./block-parsers/parseArticle.js";
import parseNote from "./block-parsers/parseNote.js";
import parseChecklist from "./block-parsers/parseChecklist.js";

import convertMdtoHtml from "./utils/convertMdToHtml.js";
import processListItems from "./block-parsers/processListItems.js";
Expand Down Expand Up @@ -72,6 +73,11 @@ const parseNotFaq = (mdContent) => {
continue;
}

if (block = parseChecklist(line)) {
blocks.push(block)
continue;
}

if (line[0] === ">") {
continue;
}
Expand Down
12 changes: 10 additions & 2 deletions md-json-converter/test/clean_json.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,15 @@
"data" : {
"title": "Note",
"message" : "This is the content of the note."
}
}
}
},
{
"id" : "glsdhflkh6",
"type" : "checklist",
"data" : {
"title": "Documents needed to apply for a B1/B2 visa include:",
"items" : ["A passport valid for six months", "A recent digital photograph", "Documentation of the past five previous trips"]
}
}
],
"version":"2.29.1"}
2 changes: 2 additions & 0 deletions md-json-converter/test/markdown_text.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ This is a warning:

|NOTE title=Note: message=If you don't have enough money in the bank, they probably won't accept you. NOTE|

|CHECKLIST title=Documents needed to apply for a B1/B2 visa include: items=A passport valid for six months,A recent digital photograph,Documentation of the past five previous trips CHECKLIST|

## Frequently Asked Questions
<question>What is the first question</question>

Expand Down
6 changes: 3 additions & 3 deletions md-json-converter/test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ let markdown;
const markdownContent = fs.readFileSync(new URL('../test/markdown_text.md', import.meta.url), 'utf-8');
let result = md2cleanjson(markdownContent);
result = JSON.parse(result);
// console.log(JSON.stringify(result))
// console.log(JSON.stringify(result, null, 2))
// console.log(result.blocks.length);
console.assert(result.blocks.length === 25, 'ERROR! MD to clean JSON failed!!!!!!!');
console.assert(result.blocks.length === 26, 'ERROR! MD to clean JSON failed!!!!!!!');


// ------------------------------------------------------------------------------------------------------
Expand All @@ -42,4 +42,4 @@ console.assert(cleanJSON.bodyBlocks.blocks.length === 30, 'ERROR! bodyBlocks len
markdown = cleanjson2md(cleanData);
// console.log(markdown);
// console.log(markdown.length);
console.assert(markdown.length === 3753, 'ERROR! Clean JSON to MD failed!!!!!!!');
console.assert(markdown.length === 3946, 'ERROR! Clean JSON to MD failed!!!!!!!');
17 changes: 14 additions & 3 deletions src/components/editor-editor/tools/tools.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,16 @@ import Raw from "@editorjs/raw";
import Header from "@editorjs/header";
import Quote from "@editorjs/quote";
import Marker from "@editorjs/marker";
import CheckList from "@editorjs/checklist";
import Delimiter from "@editorjs/delimiter";
import InlineCode from "@editorjs/inline-code";
import SimpleImage from "@editorjs/simple-image";
import ImageTool from '../../../../image/src/index';
import ImageTool from '@editorjs/image'
import RelatedArticle from "../../../../custom-blocks/related-article/src";
import Note from "../../../../custom-blocks/note/src";
import Checklist from "../../../../custom-blocks/checklist/src"

// import NestedList from "./NestedList";


export const createEditorTools = (uploadEndPoint) => ({
// NOTE: Paragraph is default tool. Declare only when you want to change paragraph option.
Expand Down Expand Up @@ -56,7 +61,6 @@ export const createEditorTools = (uploadEndPoint) => ({
header: Header,
// quote: Quote, // not in editorjs-renderer transforms
marker: Marker,
// checklist: CheckList, // not in editorjs-renderer transforms
// delimiter: Delimiter, // not in editorjs-renderer transforms
// inlineCode: InlineCode, // not in editorjs-renderer transforms
simpleImage: SimpleImage,
Expand All @@ -77,4 +81,11 @@ export const createEditorTools = (uploadEndPoint) => ({
messagePlaceholder: 'Message',
},
},
checklist: {
class: Checklist,
inlineToolbar: true,
config: {
titlePlaceholder: 'Title',
},
},
});