tiptapify 0.0.7 → 0.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/README.md +27 -3
  2. package/dist/tiptapify.css +1 -1
  3. package/dist/tiptapify.mjs +27785 -23593
  4. package/dist/tiptapify.umd.js +35 -35
  5. package/index.d.ts +49 -0
  6. package/package.json +8 -6
  7. package/src/components/Footer.vue +48 -6
  8. package/src/components/MenuBubble.vue +5 -12
  9. package/src/components/Tiptapify.vue +41 -31
  10. package/src/components/Toolbar/Group.vue +13 -14
  11. package/src/components/Toolbar/GroupBtn.vue +34 -0
  12. package/src/components/Toolbar/Index.vue +28 -79
  13. package/src/components/Toolbar/Items.vue +77 -0
  14. package/src/components/Toolbar/defaultExtensionComponents.ts +32 -0
  15. package/src/components/Toolbar/items/format.ts +0 -13
  16. package/src/components/Toolbar/items/media.ts +32 -23
  17. package/src/components/Toolbar/items/misc.ts +1 -1
  18. package/src/components/Toolbar/items/style.ts +43 -2
  19. package/src/components/Toolbar/items.ts +8 -7
  20. package/src/components/editorExtensions.ts +8 -10
  21. package/src/extensions/components/ImageDialog.vue +142 -0
  22. package/src/extensions/components/LinkDialog.vue +77 -36
  23. package/src/extensions/components/PreviewDialog.vue +0 -1
  24. package/src/extensions/components/ShowSourceDialog.vue +5 -3
  25. package/src/extensions/components/StyleColor.vue +177 -0
  26. package/src/extensions/components/TableBuilder.vue +4 -5
  27. package/src/extensions/image.ts +31 -0
  28. package/src/extensions/link.ts +24 -0
  29. package/src/extensions/preview.ts +2 -15
  30. package/src/extensions/view-source.ts +0 -3
  31. package/src/i18n/locales/de.json +46 -20
  32. package/src/i18n/locales/en.json +31 -5
  33. package/src/i18n/locales/es.json +38 -12
  34. package/src/i18n/locales/fr.json +49 -23
  35. package/src/i18n/locales/it.json +42 -16
  36. package/src/i18n/locales/pl.json +46 -19
  37. package/src/i18n/locales/ru.json +30 -4
  38. package/src/i18n/locales/ua.json +30 -4
  39. package/src/index.ts +0 -1
  40. package/src/types/overridable-extensions.ts +6 -0
@@ -4,78 +4,82 @@ import * as mdi from '@mdi/js'
4
4
  import { Editor } from "@tiptap/vue-3";
5
5
 
6
6
  import { useI18n } from 'vue-i18n'
7
- import { computed, inject, Ref, ref, watch } from 'vue'
7
+ import { computed, inject, onMounted, onUnmounted, Ref, ref } from 'vue'
8
8
 
9
9
  import helpers from '@tiptapify/utils/helpers'
10
10
 
11
- defineExpose({ open })
11
+ defineProps({
12
+ variantBtn: { type: String, default() { return 'elevated' }},
13
+ variantField: { type: String, default() { return 'solo' }}
14
+ })
12
15
 
13
16
  const { ucFirst } = helpers
14
17
 
15
- interface Props {
16
- value?: string
17
- target?: '_self' | '_blank'
18
- destroy?: () => void
19
- }
20
-
21
- const props = withDefaults(defineProps<Props>(), {
22
- value: undefined,
23
- target: '_blank',
24
- destroy: undefined
25
- })
26
-
27
18
  const editor = inject('tiptapifyEditor') as Ref<Editor>
28
-
29
19
  const { t } = useI18n()
30
20
 
31
21
  const generateLinkAttrs = () => ({
32
22
  href: '',
33
- target: '_blank'
23
+ target: '_blank',
24
+ cssClass: '',
25
+ rel: ''
34
26
  })
35
27
 
28
+ const relAttrs = ['alternate', 'author', 'bookmark', 'external', 'help', 'license', 'next', 'nofollow', 'noreferrer', 'noopener', 'prev', 'search', 'tag']
29
+
36
30
  const attrs = ref(generateLinkAttrs())
37
31
 
38
32
  const dialog = ref<boolean>(false)
39
33
 
40
34
  const isDisabled = computed(() => {
41
- const { href, target } = attrs.value
42
- if (!href) return true
43
-
44
- return props.value === href && props.target === target
35
+ const { href } = attrs.value
36
+ return !href
45
37
  })
46
38
 
47
39
  function apply() {
48
- const { href, target } = attrs.value
40
+ let { href, target, rel, cssClass } = attrs.value
41
+ target = target ? '_blank' : '_self'
42
+ rel = rel.join(' ')
49
43
 
50
44
  if (href) {
51
- editor.value.chain().focus().extendMarkRange('link').setLink({ href, target }).run()
45
+ editor.value.chain().focus().extendMarkRange('link').setLink({ href, target, rel, class: cssClass }).run()
52
46
  }
47
+
53
48
  close()
54
49
  }
55
50
 
56
- function open() {
57
- dialog.value = true
51
+ function clear() {
52
+ editor.value.chain().focus().extendMarkRange('link').unsetLink().run()
53
+
54
+ close()
58
55
  }
59
56
 
60
57
  function close() {
61
58
  dialog.value = false
59
+
62
60
  attrs.value = generateLinkAttrs()
61
+ }
63
62
 
64
- setTimeout(() => props.destroy?.(), 300)
63
+ const showLink = (event: CustomEvent) => {
64
+ attrs.value.href = event.detail.link?.href
65
+ attrs.value.target = event.detail.link?.target === '_blank'
66
+ attrs.value.rel = event.detail.link?.rel?.split(' ')
67
+ attrs.value.cssClass = event.detail.link?.class
68
+
69
+ dialog.value = true;
65
70
  }
66
71
 
67
- watch(dialog, val => {
68
- if (!val) return
72
+ onMounted(() => {
73
+ window.addEventListener('tiptapify-show-link', showLink as EventListener)
74
+ })
69
75
 
70
- attrs.value = {
71
- href: props.value,
72
- target: props.target
73
- }
76
+ onUnmounted(() => {
77
+ window.removeEventListener('tiptapify-show-link', showLink as EventListener)
74
78
  })
75
79
  </script>
76
80
 
77
81
  <template>
78
- <VDialog v-model="dialog" max-width="400" absolute @click:outside="close">
82
+ <VDialog v-model="dialog" max-width="800" absolute @click:outside="close">
79
83
  <VCard>
80
84
  <VToolbar class="px-6" density="compact">
81
85
  <span class="headline">{{ ucFirst(t('dialog.link.title')) }}</span>
@@ -88,13 +92,50 @@ watch(dialog, val => {
88
92
  </VToolbar>
89
93
 
90
94
  <VCardText>
91
- <VTextField v-model="attrs.href" :label="ucFirst(t('dialog.link.placeholder'))" autofocus />
95
+ <VRow>
96
+ <VCol cols="12" md="9">
97
+ <VTextField v-model="attrs.href" :variant="variantField" :label="ucFirst(t('dialog.link.href'))" autofocus />
98
+ </VCol>
99
+
100
+ <VCol cols="12" md="3">
101
+ <VCheckbox v-model="attrs.target" color="primary" :label="ucFirst(t('dialog.link.target'))" />
102
+ </VCol>
103
+
104
+ <VCol cols="12">
105
+ <VSelect
106
+ v-model="attrs.rel"
107
+ :items="relAttrs"
108
+ :label="ucFirst(t('dialog.link.rel'))"
109
+ :variant="variantField"
110
+ multiple
111
+ chips
112
+ closable-chips
113
+ clearable
114
+ />
115
+ </VCol>
116
+
117
+ <VCol cols="12">
118
+ <VTextField v-model="attrs.cssClass" :variant="variantField" :label="ucFirst(t('dialog.link.class'))" />
119
+ </VCol>
120
+ </VRow>
92
121
  </VCardText>
93
122
 
94
123
  <VCardActions>
95
- <VBtn :disabled="isDisabled" @click="apply">
96
- {{ ucFirst(t('dialog.apply')) }}
97
- </VBtn>
124
+ <VRow>
125
+ <VCol class="d-flex justify-start">
126
+ <VBtn color="warning" v-if="editor.isActive('link')" :variant="variantBtn" :disabled="isDisabled" @click="clear">
127
+ {{ ucFirst(t('dialog.clear')) }}
128
+ </VBtn>
129
+ </VCol>
130
+ <VCol class="d-flex justify-end">
131
+ <VBtn :variant="variantBtn" @click="close" class="mr-2">
132
+ {{ ucFirst(t('dialog.close')) }}
133
+ </VBtn>
134
+ <VBtn color="primary" :variant="variantBtn" :disabled="isDisabled" @click="apply">
135
+ {{ ucFirst(t('dialog.apply')) }}
136
+ </VBtn>
137
+ </VCol>
138
+ </VRow>
98
139
  </VCardActions>
99
140
  </VCard>
100
141
  </VDialog>
@@ -10,7 +10,6 @@ const content = ref()
10
10
  const dialog = ref(false)
11
11
 
12
12
  const showDialog = (event: CustomEvent) => {
13
- console.log('preview event', event)
14
13
  content.value = event.detail.html
15
14
  dialog.value = true;
16
15
  }
@@ -7,6 +7,8 @@ import helpers from "@tiptapify/utils/helpers";
7
7
 
8
8
  const props = defineProps({
9
9
  indent: { type: Number, default: 2 },
10
+ variantBtn: { type: String, default: 'elevated' },
11
+ variantField: { type: String, default: 'solo' }
10
12
  })
11
13
 
12
14
  const { ucFirst } = helpers;
@@ -97,17 +99,17 @@ watch(() => formatted.value, () => {
97
99
  v-model="sourceCode"
98
100
  no-resize
99
101
  rows="100"
100
- variant="outlined"
102
+ :variant="variantField"
101
103
  class="source-code-area"
102
104
  />
103
105
  </VCardText>
104
106
 
105
107
  <VCardActions>
106
108
  <VSpacer></VSpacer>
107
- <VBtn color="primary" @click="dialog = false">
109
+ <VBtn :variant="variantBtn" @click="dialog = false">
108
110
  {{ ucFirst(t('dialog.close')) }}
109
111
  </VBtn>
110
- <VBtn color="primary" @click="saveChanges">
112
+ <VBtn :variant="variantBtn" color="primary" @click="saveChanges">
111
113
  {{ ucFirst(t('dialog.apply')) }}
112
114
  </VBtn>
113
115
  </VCardActions>
@@ -0,0 +1,177 @@
1
+ <script setup lang="ts">
2
+
3
+ import { Editor } from "@tiptap/vue-3";
4
+ import { useI18n } from 'vue-i18n'
5
+
6
+ import { computed, inject, Ref, ref } from 'vue'
7
+
8
+ const { t } = useI18n()
9
+
10
+ defineExpose({ open })
11
+
12
+ const props = defineProps({
13
+ show: { type: Boolean, default: true },
14
+ fontColor: { type: Boolean, default: false },
15
+ backgroundColor: { type: Boolean, default: false },
16
+ color: { type: String, default: '' },
17
+ })
18
+
19
+ const emit = defineEmits(['close'])
20
+
21
+ const editor = inject('tiptapifyEditor') as Ref<Editor>
22
+
23
+ const colorPicker = ref(false)
24
+ const customColor = ref(computed(() => props.color).value)
25
+
26
+ const colors = {
27
+ black: '#000',
28
+ darkgray: '#444',
29
+ gray: '#888',
30
+ lightgray: '#ccc',
31
+ white: '#fff',
32
+ cyan: '#00FFFF',
33
+ light: '#0088ff',
34
+ blue: '#0000ff',
35
+ indigo: '#4b0082',
36
+ purple: '#800080',
37
+ pink: '#ff00ff',
38
+ red: '#ff0000',
39
+ orange: '#ff9900',
40
+ yellow: '#ffff00',
41
+ green: '#00ff00',
42
+ }
43
+
44
+ type Color = { r: number, g: number, b: number, a?: number }
45
+
46
+ function calculateShadowColor(color: string): string {
47
+ const rgb: Color = hexToRgb(color)
48
+
49
+ for (const channel of Object.keys(rgb)) {
50
+ rgb[channel] = Math.round(rgb[channel] * .35)
51
+ }
52
+
53
+ return Object.values(rgb).join(', ')
54
+ }
55
+
56
+ function hexToRgb(hex: string): Color {
57
+ const shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
58
+ hex = hex.replace(shorthandRegex, function(m, r, g, b) {
59
+ return r + r + g + g + b + b;
60
+ });
61
+
62
+ const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
63
+ return {
64
+ r: result ? parseInt(result[1], 16) : 0,
65
+ g: result ? parseInt(result[2], 16) : 0,
66
+ b: result ? parseInt(result[3], 16) : 0
67
+ };
68
+ }
69
+
70
+ function setColor(color: string) {
71
+ if (props.fontColor) {
72
+ editor.value.chain().focus().setColor(color).run()
73
+ }
74
+
75
+ if (props.backgroundColor) {
76
+ editor.value.chain().focus().setHighlight({ color }).run()
77
+ }
78
+
79
+ emit('close')
80
+ }
81
+
82
+ function unsetColor() {
83
+ if (props.fontColor) {
84
+ editor.value.chain().focus().unsetColor().run()
85
+ }
86
+
87
+ if (props.backgroundColor) {
88
+ editor.value.chain().focus().unsetHighlight().run()
89
+ }
90
+
91
+ emit('close')
92
+ }
93
+
94
+ function isColorActive(color: string): boolean {
95
+ return props.color === color
96
+ }
97
+ </script>
98
+
99
+ <template>
100
+ <VSheet class="pa-2">
101
+ <div class="tiptapify-style-color-container">
102
+ <template v-for="colorCode in colors">
103
+ <div
104
+ class="tiptapify-style-color-item"
105
+ :class="isColorActive(colorCode) ? 'tiptapify-style-color-item-active' : ''"
106
+ @click="setColor(colorCode)"
107
+ >
108
+ <div
109
+ class="tiptapify-style-color-picker"
110
+ :style="`background-color: ${colorCode}; box-shadow: 1px 1px 4px rgb(${calculateShadowColor(colorCode)});`"
111
+ ></div>
112
+ </div>
113
+ </template>
114
+ </div>
115
+
116
+ <VDivider class="mt-2 mb-2" />
117
+
118
+ <VMenu v-model="colorPicker" :close-on-content-click="false">
119
+ <template #activator="{ props: menuProps }">
120
+ <VBtn v-bind="menuProps" variant="flat" block>
121
+ <template #prepend>
122
+ <div
123
+ class="tiptapify-style-color-picker"
124
+ :style="`background-color: ${customColor}; box-shadow: 1px 1px 4px rgb(0, 0, 0, .35);`"
125
+ >
126
+ </div>
127
+ </template>
128
+ <template #default>
129
+ {{ t('style.color.custom') }}
130
+ </template>
131
+ </VBtn>
132
+ </template>
133
+
134
+ <VCard>
135
+ <VCardItem>
136
+ <VColorPicker v-model="customColor" elevated elevation="24" hide-inputs />
137
+ </VCardItem>
138
+
139
+ <VCardActions>
140
+ <VBtn variant="flat" color="primary" @click="setColor(customColor)">OK</VBtn>
141
+ <VBtn variant="flat" color="grey-400" @click="colorPicker = !colorPicker; customColor = color">Cancel</VBtn>
142
+ </VCardActions>
143
+ </VCard>
144
+ </VMenu>
145
+
146
+ <VDivider class="mt-2 mb-2" />
147
+
148
+ <VBtn @click="unsetColor" block variant="flat">
149
+ {{ t('style.color.unset') }}
150
+ </VBtn>
151
+ </VSheet>
152
+ </template>
153
+
154
+ <style lang="scss" scoped>
155
+ .tiptapify-style-color-container {
156
+ display: grid;
157
+ grid-template-columns: repeat(5, 1fr);
158
+ }
159
+
160
+ .tiptapify-style-color-item {
161
+ cursor: pointer;
162
+ border-radius: 8px;
163
+ padding: 5px;
164
+ transition: background-color .2s;
165
+ }
166
+
167
+ .tiptapify-style-color-item:hover, .tiptapify-style-color-item-active {
168
+ background-color: #dedede;
169
+ }
170
+
171
+ .tiptapify-style-color-picker {
172
+ width: 24px;
173
+ height: 24px;
174
+ margin: 2px;
175
+ border-radius: 4px;
176
+ }
177
+ </style>
@@ -13,7 +13,6 @@ const { ucFirst } = helpers
13
13
  defineExpose({ open })
14
14
 
15
15
  defineProps({
16
- show: { type: Boolean, default: false },
17
16
  maxCols: { type: Number, default: 10 },
18
17
  maxRows: { type: Number, default: 10 },
19
18
  })
@@ -56,7 +55,7 @@ function printSelection() {
56
55
  v-model="withHeaderRow"
57
56
  density="compact"
58
57
  color="primary"
59
- :label="ucFirst(t('format.tables.insertWithHeaderRow'))" hide-details
58
+ :label="ucFirst(t('media.tables.insertWithHeaderRow'))" hide-details
60
59
  />
61
60
 
62
61
  <div v-for="rowNum in maxRows" :key="`row-${rowNum}`" class="tiptapify-insert-table-row">
@@ -74,8 +73,8 @@ function printSelection() {
74
73
 
75
74
  <div class="tiptapify-table-builder-info">
76
75
  <span>
77
- {{ ucFirst(t('format.tables.rows')) }}: {{ rowHover }}
78
- {{ ucFirst(t('format.tables.cols')) }}: {{ colHover }}
76
+ {{ ucFirst(t('media.tables.rows')) }}: {{ rowHover }}
77
+ {{ ucFirst(t('media.tables.cols')) }}: {{ colHover }}
79
78
  </span>
80
79
  <span>
81
80
  {{ printSelection() }}
@@ -111,7 +110,7 @@ $mutedColor: var(--v-theme-muted-color, #888888);
111
110
  margin: 2px;
112
111
  width: 100%;
113
112
  height: 100%;
114
- border: 1px solid #888;
113
+ border: 1px solid #bbb;
115
114
  background: #fff;
116
115
  border-radius: 4px;
117
116
  filter: drop-shadow(2px 2px 4px #88888888);
@@ -0,0 +1,31 @@
1
+ import { Extension } from '@tiptap/core'
2
+
3
+ const name: string = 'tiptapifyImage'
4
+
5
+ declare module '@tiptap/core' {
6
+ interface Commands<ReturnType> {
7
+ tiptapifyImage: {
8
+ showTiptapifyImage: () => ReturnType
9
+ }
10
+ }
11
+ }
12
+
13
+ export const TiptapifyImage = Extension.create({
14
+ name,
15
+
16
+ addCommands() {
17
+ return {
18
+ showTiptapifyImage: () => ({ editor }) => {
19
+ const event = new CustomEvent(`tiptapify-show-${name}`, {
20
+ detail: {
21
+ image: editor.getAttributes('image')
22
+ }
23
+ })
24
+
25
+ window.dispatchEvent(event)
26
+
27
+ return true
28
+ },
29
+ }
30
+ },
31
+ })
@@ -0,0 +1,24 @@
1
+ import Link from "@tiptap/extension-link";
2
+
3
+ const name: string = 'link'
4
+
5
+ export const TiptapifyLink = Link.extend({
6
+ name,
7
+
8
+ addCommands() {
9
+ return {
10
+ ...this.parent?.(),
11
+ showLink: () => ({ editor }) => {
12
+ const event = new CustomEvent(`tiptapify-show-${name}`, {
13
+ detail: {
14
+ link: editor.getAttributes('link')
15
+ }
16
+ })
17
+
18
+ window.dispatchEvent(event)
19
+
20
+ return true
21
+ },
22
+ }
23
+ },
24
+ })
@@ -3,34 +3,21 @@ import { Plugin, PluginKey } from '@tiptap/pm/state'
3
3
 
4
4
  const name: string = 'preview'
5
5
 
6
- export interface ViewSourceOptions {
7
- HTMLAttributes: Record<string, any>
8
- }
9
-
10
6
  declare module '@tiptap/core' {
11
7
  interface Commands<ReturnType> {
12
8
  preview: {
13
- /**
14
- * Показать исходный HTML-код
15
- */
16
9
  showPreview: () => ReturnType
17
10
  }
18
11
  }
19
12
  }
20
13
 
21
- export const Preview = Extension.create<ViewSourceOptions>({
14
+ export const Preview = Extension.create({
22
15
  name,
23
16
 
24
- addOptions() {
25
- return {
26
- HTMLAttributes: {},
27
- }
28
- },
29
-
30
17
  addCommands() {
31
18
  return {
32
19
  showPreview: () => ({ editor }) => {
33
- const event = new CustomEvent('tiptapify-show-preview', {
20
+ const event = new CustomEvent(`tiptapify-show-${name}`, {
34
21
  detail: {
35
22
  html: editor.getHTML()
36
23
  }
@@ -8,9 +8,6 @@ export interface ViewSourceOptions {
8
8
  declare module '@tiptap/core' {
9
9
  interface Commands<ReturnType> {
10
10
  viewSource: {
11
- /**
12
- * Показать исходный HTML-код
13
- */
14
11
  showSource: () => ReturnType
15
12
  }
16
13
  }
@@ -1,4 +1,7 @@
1
1
  {
2
+ "content": {
3
+ "placeholder": "schreib hier etwas..."
4
+ },
2
5
  "style": {
3
6
  "paragraph": "absatz",
4
7
  "heading": "überschrift",
@@ -12,7 +15,13 @@
12
15
  },
13
16
  "fontFamily": "schriftart",
14
17
  "fontSize": "schriftgröße",
15
- "lineHeight": "zeilenhöhe"
18
+ "lineHeight": "zeilenhöhe",
19
+ "color": {
20
+ "highlight": "hervorhebungsfarbe",
21
+ "text": "textfarbe",
22
+ "unset": "farbe zurücksetzen",
23
+ "custom": "benutzerdefinierte farbe"
24
+ }
16
25
  },
17
26
  "format": {
18
27
  "bold": "fett",
@@ -21,14 +30,16 @@
21
30
  "underline": "unterstrichen",
22
31
  "sup": "hochgestellt",
23
32
  "sub": "tiefgestellt",
24
- "break": "zeilenumbruch",
25
- "highlight": "hervorheben",
33
+ "break": "harter umbruch",
26
34
  "line": "horizontale linie",
27
35
  "blockquote": "zitat",
28
36
  "code": "code",
29
- "codeblock": "codeblock",
37
+ "codeblock": "code block",
38
+ "formatClear": "formatierung löschen"
39
+ },
40
+ "media": {
30
41
  "link": "externer link",
31
- "formatClear": "formatierung löschen",
42
+ "image": "bild",
32
43
  "tables": {
33
44
  "table": "tabelle",
34
45
  "insertTable": "tabelle einfügen",
@@ -36,13 +47,13 @@
36
47
  "insertWithHeaderRow": "tabelle mit kopfzeile einfügen",
37
48
  "rows": "zeilen",
38
49
  "row": "zeile",
39
- "insertRowBefore": "zeile oberhalb einfügen",
40
- "insertRowAfter": "zeile unterhalb einfügen",
50
+ "insertRowBefore": "zeile davor einfügen",
51
+ "insertRowAfter": "zeile danach einfügen",
41
52
  "deleteRow": "zeile löschen",
42
53
  "cols": "spalten",
43
54
  "col": "spalte",
44
- "insertColBefore": "spalte links einfügen",
45
- "insertColAfter": "spalte rechts einfügen",
55
+ "insertColBefore": "spalte davor einfügen",
56
+ "insertColAfter": "spalte danach einfügen",
46
57
  "deleteCol": "spalte löschen",
47
58
  "mergeCells": "zellen verbinden",
48
59
  "splitCell": "zelle teilen"
@@ -50,37 +61,52 @@
50
61
  },
51
62
  "action": {
52
63
  "undo": "rückgängig",
53
- "redo": "wiederherstellen"
64
+ "redo": "wiederholen"
54
65
  },
55
66
  "alignment": "ausrichtung",
56
67
  "alignments": {
57
- "left": "linksbündig",
58
- "center": "zentriert",
59
- "right": "rechtsbündig",
68
+ "left": "links ausrichten",
69
+ "center": "zentriert ausrichten",
70
+ "right": "rechts ausrichten",
60
71
  "justify": "blocksatz"
61
72
  },
62
73
  "list": "liste",
63
74
  "lists": {
64
- "bullet": "aufzählungsliste",
65
- "numbered": "nummerierte liste",
75
+ "bullet": "ungeordnete liste",
76
+ "numbered": "geordnete liste",
66
77
  "task": "aufgabenliste",
67
- "indent": "einzug vergrößern",
68
- "outdent": "einzug verkleinern"
78
+ "indent": "listenelement einrücken",
79
+ "outdent": "listenelement ausrücken"
69
80
  },
70
81
  "dialog": {
71
- "close": "schließen",
72
82
  "apply": "anwenden",
83
+ "clear": "löschen",
84
+ "close": "schließen",
85
+ "image": {
86
+ "title": "bild hinzufügen/bearbeiten",
87
+ "src": "quelle",
88
+ "alt": "alt",
89
+ "width": "breite",
90
+ "height": "höhe"
91
+ },
73
92
  "link": {
74
93
  "title": "link hinzufügen/bearbeiten",
75
- "placeholder": "linkadresse"
94
+ "href": "link-adresse",
95
+ "target": "in neuem fenster öffnen",
96
+ "rel": "rel",
97
+ "class": "css-klasse"
76
98
  },
77
99
  "source": {
78
100
  "title": "quellcode anzeigen",
79
- "prettify": "formatieren"
101
+ "prettify": "verschönern"
80
102
  }
81
103
  },
82
104
  "misc": {
83
105
  "source": "quellcode anzeigen",
84
106
  "preview": "vorschau"
107
+ },
108
+ "footer": {
109
+ "words": "wörter",
110
+ "chars": "zeichen"
85
111
  }
86
112
  }