@adminforth/markdown 1.0.0

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.
@@ -0,0 +1,13 @@
1
+
2
+ #!/bin/bash
3
+
4
+ # write npm run output both to console and to build.log
5
+ npm run build 2>&1 | tee build.log
6
+ build_status=${PIPESTATUS[0]}
7
+
8
+ # if exist status from the npm run build is not 0
9
+ # then exit with the status code from the npm run build
10
+ if [ $build_status -ne 0 ]; then
11
+ echo "Build failed. Exiting with status code $build_status"
12
+ exit $build_status
13
+ fi
@@ -0,0 +1,44 @@
1
+ #!/bin/sh
2
+
3
+ set -x
4
+
5
+ COMMIT_SHORT_SHA=$(echo $CI_COMMIT_SHA | cut -c1-8)
6
+
7
+
8
+ if [ "$CI_STEP_STATUS" = "success" ]; then
9
+ MESSAGE="Did a build without issues on \`$CI_REPO_NAME/$CI_COMMIT_BRANCH\`. Commit: _${CI_COMMIT_MESSAGE}_ (<$CI_COMMIT_URL|$COMMIT_SHORT_SHA>)"
10
+
11
+ curl -s -X POST -H "Content-Type: application/json" -d '{
12
+ "username": "'"$CI_COMMIT_AUTHOR"'",
13
+ "icon_url": "'"$CI_COMMIT_AUTHOR_AVATAR"'",
14
+ "attachments": [
15
+ {
16
+ "mrkdwn_in": ["text", "pretext"],
17
+ "color": "#36a64f",
18
+ "text": "'"$MESSAGE"'"
19
+ }
20
+ ]
21
+ }' "$DEVELOPERS_SLACK_WEBHOOK"
22
+ exit 0
23
+ fi
24
+ export BUILD_LOG=$(cat ./build.log)
25
+
26
+ BUILD_LOG=$(echo $BUILD_LOG | sed 's/"/\\"/g')
27
+
28
+ MESSAGE="Broke \`$CI_REPO_NAME/$CI_COMMIT_BRANCH\` with commit _${CI_COMMIT_MESSAGE}_ (<$CI_COMMIT_URL|$COMMIT_SHORT_SHA>)"
29
+ CODE_BLOCK="\`\`\`$BUILD_LOG\n\`\`\`"
30
+
31
+ echo "Sending slack message to developers $MESSAGE"
32
+ # Send the message
33
+ curl -sS -X POST -H "Content-Type: application/json" -d '{
34
+ "username": "'"$CI_COMMIT_AUTHOR"'",
35
+ "icon_url": "'"$CI_COMMIT_AUTHOR_AVATAR"'",
36
+ "attachments": [
37
+ {
38
+ "mrkdwn_in": ["text", "pretext"],
39
+ "color": "#8A1C12",
40
+ "text": "'"$CODE_BLOCK"'",
41
+ "pretext": "'"$MESSAGE"'"
42
+ }
43
+ ]
44
+ }' "$DEVELOPERS_SLACK_WEBHOOK" 2>&1
@@ -0,0 +1,44 @@
1
+ clone:
2
+ git:
3
+ image: woodpeckerci/plugin-git
4
+ settings:
5
+ partial: false
6
+ depth: 5
7
+
8
+ steps:
9
+ init-secrets:
10
+ when:
11
+ - event: push
12
+ image: infisical/cli
13
+ environment:
14
+ INFISICAL_TOKEN:
15
+ from_secret: VAULT_TOKEN
16
+ commands:
17
+ - infisical export --domain https://vault.devforth.io/api --format=dotenv-export --env="prod" > /woodpecker/deploy.vault.env
18
+ secrets:
19
+ - VAULT_TOKEN
20
+
21
+ release:
22
+ image: node:20
23
+ when:
24
+ - event: push
25
+ volumes:
26
+ - /var/run/docker.sock:/var/run/docker.sock
27
+ commands:
28
+ - apt update && apt install -y rsync
29
+ - export $(cat /woodpecker/deploy.vault.env | xargs)
30
+ - npm clean-install
31
+ - /bin/bash ./.woodpecker/buildRelease.sh
32
+ - npm audit signatures
33
+ - npx semantic-release
34
+
35
+ slack-on-failure:
36
+ when:
37
+ - event: push
38
+ status: [failure, success]
39
+ - event: push
40
+ image: curlimages/curl
41
+ commands:
42
+ - export $(cat /woodpecker/deploy.vault.env | xargs)
43
+ - /bin/sh ./.woodpecker/buildSlackNotify.sh
44
+
package/build.log ADDED
@@ -0,0 +1,14 @@
1
+
2
+ > @adminforth/markdown@1.0.0 build
3
+ > tsc && rsync -av --exclude 'node_modules' custom dist/
4
+
5
+ sending incremental file list
6
+ custom/
7
+ custom/MarkdownEditor.vue
8
+ custom/MarkdownRenderer.vue
9
+ custom/package-lock.json
10
+ custom/package.json
11
+ custom/tsconfig.json
12
+
13
+ sent 169,522 bytes received 115 bytes 339,274.00 bytes/sec
14
+ total size is 169,062 speedup is 1.00
@@ -0,0 +1,137 @@
1
+ <template>
2
+ <div class="mb-2"></div>
3
+ <div ref="editorContainer" id="editor" :class="[
4
+ 'text-sm rounded-lg block w-full transition-all box-border',
5
+ isFocused
6
+ ? 'ring-1 ring-lightPrimary border ring-lightPrimary border-lightPrimary dark:ring-darkPrimary dark:border-darkPrimary bg-white dark:bg-gray-700 text-gray-900 dark:text-white'
7
+ : 'bg-gray-50 border border-gray-300 text-gray-900 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white',
8
+ ]"></div>
9
+ </template>
10
+
11
+ <script setup lang="ts">
12
+ import { ref, watch, onMounted, onBeforeUnmount } from 'vue';
13
+
14
+ import { Editor, rootCtx, defaultValueCtx } from '@milkdown/core';
15
+ import { gfm } from '@milkdown/kit/preset/gfm';
16
+ import { commonmark } from '@milkdown/preset-commonmark';
17
+ import { listener, listenerCtx } from '@milkdown/plugin-listener';
18
+ import { Crepe } from '@milkdown/crepe';
19
+
20
+ import '@milkdown/crepe/theme/common/style.css';
21
+ import '@milkdown/crepe/theme/frame-dark.css';
22
+
23
+ const props = defineProps<{ column: any; record: any }>();
24
+ const emit = defineEmits(['update:value']);
25
+ const editorContainer = ref<HTMLElement | null>(null);
26
+ const content = ref(props.record[props.column.name] || '');
27
+
28
+ const isFocused = ref(false);
29
+
30
+ let milkdownInstance: Editor | null = null;
31
+ let crepeInstance: Crepe | null = null;
32
+
33
+ onMounted(async () => {
34
+ if (!editorContainer.value) return;
35
+ try {
36
+ // Milkdown
37
+ // console.log('props.cole', props.column)
38
+ // if (props.column.components.edit.meta.pluginType === 'milkdown' || props.column.components.create.meta.pluginType === 'milkdown') {
39
+ // milkdownInstance = await Editor.make()
40
+ // .config((ctx) => {
41
+ // ctx.set(rootCtx, editorContainer.value!);
42
+ // ctx.set(defaultValueCtx, content.value);
43
+ // ctx.get(listenerCtx).markdownUpdated((_ctx, markdown) => {
44
+ // content.value = markdown;
45
+ // emit('update:value', markdown);
46
+ // });
47
+ // ctx.get(listenerCtx).focus(() => {
48
+ // isFocused.value = true;
49
+ // });
50
+
51
+ // ctx.get(listenerCtx).blur(() => {
52
+ // isFocused.value = false;
53
+ // });
54
+ // })
55
+ // .use(commonmark)
56
+ // .use(gfm)
57
+ // .use(listener)
58
+ // .create();
59
+
60
+ // console.log('Milkdown editor created');
61
+ // }
62
+
63
+ // Crepe
64
+ if (props.column.components.edit.meta.pluginType === 'crepe' || props.column.components.create.meta.pluginType === 'crepe') {
65
+ crepeInstance = await new Crepe({
66
+ root: editorContainer.value,
67
+ defaultValue: content.value,
68
+ });
69
+
70
+ crepeInstance.on((listener) => {
71
+ listener.markdownUpdated(() => {
72
+ const markdownContent = crepeInstance.getMarkdown();
73
+ emit('update:value', markdownContent);
74
+ });
75
+
76
+ listener.focus(() => {
77
+ isFocused.value = true;
78
+ });
79
+ listener.blur(() => {
80
+ isFocused.value = false;
81
+ });
82
+ });
83
+
84
+ await crepeInstance.create();
85
+ console.log('Crepe editor created');
86
+ }
87
+ } catch (error) {
88
+ console.error('Failed to initialize editor:', error);
89
+ }
90
+ });
91
+
92
+ onBeforeUnmount(() => {
93
+ milkdownInstance?.destroy();
94
+ crepeInstance?.destroy();
95
+ console.log('Editor destroyed');
96
+ });
97
+ </script>
98
+
99
+ <style>
100
+ #editor [contenteditable="true"] {
101
+ @apply bg-transparent outline-none border-none shadow-none transition-none min-h-10 p-2 bg-gray-700 dark:placeholder-gray-400;
102
+ }
103
+
104
+ #editor [contenteditable="true"].is-focused {
105
+ @apply ring-1 ring-lightPrimary border ring-lightPrimary border-lightPrimary bg-white text-gray-900 dark:ring-darkPrimary dark:border-darkPrimary dark:bg-gray-700 dark:text-white;
106
+ }
107
+
108
+ #editor [contenteditable="true"]:not(.is-focused) {
109
+ @apply bg-gray-50 border border-gray-300 text-gray-900 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white;
110
+ }
111
+
112
+ .milkdown milkdown-slash-menu {
113
+ @apply bg-gray-50 border border-gray-300 text-gray-900 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white z-10;
114
+ }
115
+
116
+ .milkdown milkdown-slash-menu .menu-groups .menu-group li.hover {
117
+ @apply bg-gray-50 border border-gray-300 text-gray-900 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white;
118
+ }
119
+
120
+ .milkdown milkdown-slash-menu .tab-group ul li.selected {
121
+ @apply bg-gray-50 border border-gray-300 text-gray-900 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white;
122
+ }
123
+
124
+ .milkdown-slash-menu .tab-group ul li.selected:hover {
125
+ @apply bg-gray-50 border-gray-300 text-gray-900 dark:bg-gray-700 dark:border-gray-600 dark:text-white;
126
+ }
127
+
128
+ .milkdown milkdown-code-block {
129
+ @apply bg-gray-50 border border-gray-300 text-gray-900 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white;
130
+ }
131
+
132
+ .milkdown milkdown-code-block .cm-gutters {
133
+ @apply bg-gray-50 border border-gray-300 text-gray-900 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white;
134
+ }
135
+
136
+
137
+ </style>
@@ -0,0 +1,110 @@
1
+ <template>
2
+ <div v-html="purifiedHtml" class="mdwn"></div>
3
+ </template>
4
+
5
+ <script setup lang="ts">
6
+ import { computed } from 'vue';
7
+ import { marked } from "marked";
8
+ import DOMPurify from "dompurify";
9
+
10
+ const props = defineProps<{ column: any; record: any }>();
11
+
12
+ const purifiedHtml = computed(() => {
13
+
14
+ if (!props.record[props.column.name]) return '-';
15
+ const html = marked(String(props.record[props.column.name]));
16
+ if (html instanceof Promise) {
17
+ console.error("Async rendering is not supported in this setup.");
18
+ return '';
19
+ }
20
+ return DOMPurify.sanitize(html);
21
+ });
22
+ </script>
23
+
24
+ <style lang="scss">
25
+
26
+ .mdwn h1 {
27
+ @apply text-2xl font-bold mt-2 mb-2;
28
+ }
29
+
30
+ .mdwn h2 {
31
+ @apply text-xl font-bold mt-2 mb-2;
32
+ }
33
+
34
+ .mdwn h3 {
35
+ @apply text-lg font-bold mt-2 mb-2;
36
+ }
37
+
38
+ .mdwn h4 {
39
+ @apply text-base font-bold mt-2 mb-2;
40
+ }
41
+
42
+ .mdwn h5 {
43
+ @apply text-sm font-bold mt-2 mb-2;
44
+ }
45
+
46
+ .mdwn h6 {
47
+ @apply text-xs font-bold mt-2 mb-2;
48
+ }
49
+
50
+ .mdwn p {
51
+ @apply mb-2 leading-relaxed;
52
+ }
53
+
54
+ .mdwn ul {
55
+ @apply list-disc pl-5 mb-2;
56
+ }
57
+
58
+ .mdwn ol {
59
+ @apply list-decimal pl-5 mb-2;
60
+ }
61
+
62
+ .mdwn li {
63
+ @apply mb-1;
64
+ }
65
+
66
+ .mdwn blockquote {
67
+ @apply border-l-4 border-gray-300 dark:border-gray-600 pl-4 italic text-gray-600 dark:text-gray-400 mb-2;
68
+ }
69
+
70
+ .mdwn code {
71
+ @apply bg-gray-100 dark:bg-gray-800 text-red-600 dark:text-red-400 font-mono px-1 py-0.5 rounded;
72
+ }
73
+
74
+ .mdwn pre {
75
+ @apply bg-gray-100 dark:bg-gray-900 text-sm font-mono p-4 rounded overflow-x-auto mb-2;
76
+ }
77
+ .mdwn pre code {
78
+ @apply bg-transparent p-0 text-inherit;
79
+ }
80
+
81
+ .mdwn table {
82
+ @apply w-full border-collapse text-left text-sm mb-2;
83
+ }
84
+
85
+ .mdwn thead {
86
+ @apply bg-gray-100 dark:bg-gray-700;
87
+ }
88
+
89
+ .mdwn th,
90
+ .mdwn td {
91
+ @apply border border-gray-300 dark:border-gray-700 px-4 py-2;
92
+ }
93
+
94
+ .mdwn th {
95
+ @apply font-semibold;
96
+ }
97
+
98
+ .mdwn hr {
99
+ @apply border-t border-gray-300 dark:border-gray-700 my-6;
100
+ }
101
+
102
+ .mdwn img {
103
+ @apply max-w-full h-auto rounded;
104
+ }
105
+
106
+ .mdwn a {
107
+ @apply text-blue-600 hover:underline dark:text-blue-400;
108
+ }
109
+
110
+ </style>