Skip to content

Commit

Permalink
feat: viewer & data controller
Browse files Browse the repository at this point in the history
  • Loading branch information
lovefields committed Aug 19, 2024
1 parent e48bee1 commit cd21319
Show file tree
Hide file tree
Showing 11 changed files with 297 additions and 28 deletions.
69 changes: 65 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
[npm-downloads-src]: https://img.shields.io/npm/dm/dragon-editor.svg?style=flat&colorA=18181B&colorB=28CF8D
[npm-downloads-href]: https://www.npmjs.com/package/dragon-editor
[license-src]: https://img.shields.io/npm/l/dragon-editor
[nuxt-src]: https://img.shields.io/badge/Nuxt-18181B?logo=nuxt.js
[nuxt-href]: https://nuxt.com

[![stars-src]](stars-href)
[![forks-src]](forks-href)
Expand All @@ -22,6 +24,7 @@
[![npm-version-src]][npm-version-href]
[![npm-downloads-src]][npm-downloads-href]
![NPM][license-src]
[![Nuxt][nuxt-src]][nuxt-href]

# DragonEditor

Expand All @@ -31,7 +34,7 @@ This module support Nuxt3 only.

# Dependencies

- @pinia/nuxt
- @pinia/nuxt

## Install

Expand Down Expand Up @@ -65,10 +68,68 @@ Second. Use Component
</template>

<script setup lang="ts">
const $editor = ref<any>();
const $editor = ref<any>();
</script>
```

Done!
Done!

<!-- More information is here [Document](123) -->
## View Page

```html
<template>
<div class="view-area">
<DragonEditorViewer :content="data" />
</div>
</template>

<script setup lang="ts">
const content = ref([]); // content data
</script>
```

## Method

### getContentData

```html
<template>
<div class="editor-area">
<ClientOnly>
<DragonEditor ref="$editor" />
</ClientOnly>
<button @click="getData()">Get Data</button>
</div>
</template>

<script setup lang="ts">
const $editor = ref<any>();
function getData() {
console.log($editor.value.getContentData());
}
</script>
```

### setContentData

```html
<template>
<div class="editor-area">
<ClientOnly>
<DragonEditor ref="$editor" />
</ClientOnly>
<button @click="setData()">Set Data</button>
</div>
</template>

<script setup lang="ts">
const $editor = ref<any>();
function setData() {
$editor.value.getContentData([...]);
}
</script>
```

<!-- More information is here [Document](123) -->
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "dragon-editor",
"version": "3.0.0-beta",
"description": "Javascript WYSIWYG editor!",
"version": "3.0.0",
"description": "Javascript WYSIWYG editor in Nuxt3!",
"repository": {
"type": "git",
"url": "git+https://github.com/lovefields/dragonEditor.git"
Expand Down
22 changes: 20 additions & 2 deletions playground/pages/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,34 @@
editor!
<div class="editor-area">
<ClientOnly>
<DragonEditor />
<DragonEditor ref="$editor" />
</ClientOnly>
</div>
<button @click="getContent">get data</button>
<button @click="setContent">set data</button>
</div>
</template>

<script setup lang="ts">
import { ref, onMounted } from "#imports";
const test = ref<MyModuleNitroRulesss>({});
const $editor = ref();
function getContent() {
console.log("data", $editor.value.getContentData());
}
function setContent() {
$editor.value.setContentData([
{ type: "text", textContent: "123" },
{ type: "text", textContent: "123" },
{ type: "heading", level: 1, id: "Sgdaow", textContent: "123" },
{ type: "heading", level: 2, id: "zlfm8i", textContent: "123" },
{ type: "heading", level: 3, id: "D0ZRSP", textContent: "123" },
{ type: "ul", child: ["123"] },
{ type: "ol", pattern: "1", child: ["123"] },
]);
}
</script>

<style lang="scss">
Expand Down
26 changes: 26 additions & 0 deletions playground/pages/view.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<template>
<div class="view-area">
<DragonEditorViewer :content="data" />
</div>
</template>

<script setup lang="ts">
import { ref, onMounted } from "#imports";
const data = ref([
{ type: "text", textContent: "123" },
{ type: "text", textContent: "123" },
{ type: "heading", level: 1, id: "Sgdaow", textContent: "123" },
{ type: "heading", level: 2, id: "zlfm8i", textContent: "123" },
{ type: "heading", level: 3, id: "D0ZRSP", textContent: "123" },
{ type: "ul", child: ["123"] },
{ type: "ol", pattern: "1", child: ["123"] },
]);
</script>

<style lang="scss">
.view-area {
max-width: 800px;
margin: 0 auto;
}
</style>
21 changes: 19 additions & 2 deletions src/runtime/components/DragonEditor.vue
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ import { _elementKeyEvent, _hotKeyEvent } from "../utils/keyboardEvent";
import { _createTextBlock, _createHeadingBlock, _createListBlock } from "../utils/block";
import { _setNodeStyle } from "../utils/style";
import { _setCursorData, _clenupCursor } from "../utils/cursor";
import { _getContentData, _setContentData } from "../utils/convertor";
import "../type.d.ts";
const props = defineProps({
Expand Down Expand Up @@ -105,7 +106,6 @@ function updateCursorData(e: MouseEvent) {
*/
function addBlock(type: string) {
_clenupCursor(editorStore);
isActiveAddBlockMenu.value = false;
let blockStructure: HTMLElement | null = null;
Expand All @@ -129,6 +129,7 @@ function addBlock(type: string) {
if (editorStore.cursorData === null) {
(editorStore.$content as HTMLDivElement).insertAdjacentElement("beforeend", blockStructure);
} else {
_clenupCursor(editorStore);
let $target = editorStore.cursorData.startNode;
if ($target.constructor.name === "Text") {
Expand All @@ -155,6 +156,18 @@ function setDecoration(type: string) {
_setNodeStyle(`de-${type}`, editorStore);
}
function getContentData() {
if (editorStore.$content !== null) {
return _getContentData(editorStore.$content);
} else {
console.error("[DragonEditor] Con't find content Element.");
}
}
function setContentData(data: any[]) {
_setContentData(data, editorStore);
}
onMounted(() => {
if ($editor.value !== undefined) {
editorStore.setWrapElement($editor.value);
Expand All @@ -168,10 +181,14 @@ onMounted(() => {
// TODO : set scroll event
});
onUnmounted(() => {});
onUnmounted(() => {
// TODO : remove scroll event
});
defineExpose({
addBlock,
getContentData,
setContentData,
});
</script>

Expand Down
31 changes: 31 additions & 0 deletions src/runtime/components/DragonEditorViewer.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<template>
<div class="dragon-editor-viewer">
<template v-for="item in props.content">
<p v-if="item.type === 'text'" class="de-block de-text-block" v-html="item.textContent"></p>

<template v-if="item.type === 'heading'">
<h1 v-if="item.level === 1" class="de-block de-heading-block" :data-level="item.level" v-html="item.textContent"></h1>
<h2 v-if="item.level === 2" class="de-block de-heading-block" :data-level="item.level" v-html="item.textContent"></h2>
<h3 v-if="item.level === 3" class="de-block de-heading-block" :data-level="item.level" v-html="item.textContent"></h3>
</template>

<ul v-if="item.type === 'ul'" class="de-block de-list-block">
<li v-for="li in item.child" class="de-item" v-html="li"></li>
</ul>

<ol v-if="item.type === 'ol'" class="de-block de-list-block" :type="item.pattern">
<li v-for="li in item.child" class="de-item" v-html="li"></li>
</ol>
</template>
</div>
</template>

<script setup lang="ts">
const props = defineProps<{
content: any[];
}>();
</script>

<style lang="scss">
@import "../scss/viewer.scss";
</style>
4 changes: 1 addition & 3 deletions src/runtime/scss/_block.scss
Original file line number Diff line number Diff line change
Expand Up @@ -17,21 +17,19 @@

// 해딩 블럭
.de-heading-block {
min-height: 1.6em;
outline: 0;

&[data-level="1"] {
font-size: 2em;
min-height: 2em;
}

&[data-level="2"] {
font-size: 1.5em;
min-height: 1.5em;
}

&[data-level="3"] {
font-size: 1.17em;
min-height: 1.17em;
}

@if $isEdit == "true" {
Expand Down
1 change: 1 addition & 0 deletions src/runtime/scss/editor.scss
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
display: grid;
gap: 4px;
padding: 20px;
line-height: 1.6;
}

// 컨트롤 메뉴 스타일
Expand Down
14 changes: 14 additions & 0 deletions src/runtime/scss/viewer.scss
Original file line number Diff line number Diff line change
@@ -1 +1,15 @@
@import "./base";
@import "./block";
@import "./style";

.dragon-editor-viewer {
display: grid;
gap: 4px;
width: 100%;
height: 100%;
padding: 20px;
line-height: 1.6;

@include blockStyle("false");
@include NodeStyle;
}
30 changes: 15 additions & 15 deletions src/runtime/utils/block.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,11 @@ export function _getBlockType(element: HTMLElement) {
}

// 문단 블럭 생성
export function _createTextBlock(content: string = "", isEdit: boolean = true): HTMLParagraphElement {
export function _createTextBlock(content: string = ""): HTMLParagraphElement {
const $paragraph = document.createElement("p");

$paragraph.classList.add("de-block", "de-text-block");

if (isEdit === true) {
$paragraph.setAttribute("contenteditable", "true");
}
$paragraph.setAttribute("contenteditable", "true");

if (content !== "") {
$paragraph.innerHTML = content;
Expand All @@ -41,17 +38,14 @@ export function _createTextBlock(content: string = "", isEdit: boolean = true):
}

// 해딩 블럭 생성
export function _createHeadingBlock(type: string, content: string = "", isEdit: boolean = true): HTMLElement {
export function _createHeadingBlock(type: string, content: string = ""): HTMLElement {
const level: number = parseInt(type.replace("heading", ""));
const $headingBlock = document.createElement(`h${level}`);

$headingBlock.classList.add("de-block", "de-heading-block");
$headingBlock.id = generateId();
$headingBlock.dataset["level"] = String(level);

if (isEdit === true) {
$headingBlock.setAttribute("contenteditable", "true");
}
$headingBlock.setAttribute("contenteditable", "true");

if (content !== "") {
$headingBlock.innerHTML = content;
Expand All @@ -61,25 +55,31 @@ export function _createHeadingBlock(type: string, content: string = "", isEdit:
}

// 리스트 블럭 생성
export function _createListBlock(type: string, content: string[] = [""], isEdit: boolean = true): HTMLElement {
export function _createListBlock(type: string, content: string[] = [""], pattern?: string): HTMLElement {
const $block = document.createElement(type);

$block.classList.add("de-block", "de-list-block");

if (type === "ol") {
($block as HTMLOListElement).type = pattern ?? "1";
}

content.forEach((text: string) => {
$block.appendChild(_createListItemBlock(text, isEdit));
$block.appendChild(_createListItemBlock(text));
});

return $block;
}

// 리스트 아이템 블럭 생성
export function _createListItemBlock(content: string = "", isEdit: boolean = true): HTMLLIElement {
export function _createListItemBlock(content: string = ""): HTMLLIElement {
const $li = document.createElement("li");

$li.classList.add("de-item");
$li.setAttribute("contenteditable", "true");

if (isEdit === true) {
$li.setAttribute("contenteditable", "true");
if (content !== "") {
$li.innerHTML = content;
}

return $li;
Expand Down
Loading

0 comments on commit cd21319

Please sign in to comment.