@live-change/survey-frontend 0.8.126

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 (42) hide show
  1. package/Dockerfile +71 -0
  2. package/LICENSE +21 -0
  3. package/data/.placeholder +0 -0
  4. package/dev.Dockerfile +35 -0
  5. package/docker/app.initd.sh +73 -0
  6. package/docker/build-and-upload.sh +30 -0
  7. package/docker/build-docker-and-upload.sh +39 -0
  8. package/docker/commit-new-version.sh +17 -0
  9. package/docker/k8s-rsync-helper.sh +4 -0
  10. package/docker/onlyDependencies.js +12 -0
  11. package/docker/parse-args-and-config.sh +20 -0
  12. package/docker/restore-backup-with-service.sh +14 -0
  13. package/docker/restore-backup.sh +22 -0
  14. package/docker/start-service.sh +4 -0
  15. package/docker/upload-backup-and-restore.sh +12 -0
  16. package/front/index.html +78 -0
  17. package/front/locales/en.js +29 -0
  18. package/front/locales/en.json +7 -0
  19. package/front/public/favicon.ico +0 -0
  20. package/front/public/images/empty-photo.svg +38 -0
  21. package/front/public/images/empty-user-photo.svg +33 -0
  22. package/front/public/images/logo.svg +34 -0
  23. package/front/public/images/logo128.png +0 -0
  24. package/front/src/App.vue +61 -0
  25. package/front/src/Index.vue +16 -0
  26. package/front/src/analytics/index.js +15 -0
  27. package/front/src/config.js +28 -0
  28. package/front/src/entry-client.js +8 -0
  29. package/front/src/entry-server.js +8 -0
  30. package/front/src/router.js +76 -0
  31. package/front/tsconfig.json +26 -0
  32. package/front/tsconfig.node.json +11 -0
  33. package/front/vite.config.ts +53 -0
  34. package/index.js +2 -0
  35. package/package.json +107 -0
  36. package/server/app.config.js +115 -0
  37. package/server/init.js +10 -0
  38. package/server/page.documentType.js +103 -0
  39. package/server/security.config.js +53 -0
  40. package/server/services.list.js +57 -0
  41. package/server/start.js +11 -0
  42. package/start-dev-docker.sh +4 -0
@@ -0,0 +1,61 @@
1
+ <template>
2
+ <view-root>
3
+ <template #navbar>
4
+ <NavBar />
5
+ <UpdateBanner />
6
+ </template>
7
+ </view-root>
8
+ </template>
9
+
10
+ <script setup>
11
+ import 'primevue/resources/themes/saga-green/theme.css'
12
+ import "@fortawesome/fontawesome-free/css/all.min.css"
13
+
14
+ import { useLocale } from '@live-change/vue3-components'
15
+ const locale = useLocale()
16
+ locale.captureLocale()
17
+
18
+ import { ViewRoot, NavBar, UpdateBanner } from "@live-change/frontend-base"
19
+
20
+ import { computed } from 'vue'
21
+ import { useHead } from '@vueuse/head'
22
+
23
+ import { useI18n } from 'vue-i18n'
24
+ const i18n = useI18n()
25
+
26
+ useHead(computed(() => ({
27
+ title: ENV_BRAND_NAME,
28
+ meta: [
29
+ { charset: 'utf-8' },
30
+ { name: 'viewport',
31
+ content: "user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1," +
32
+ " width=device-width, viewport-fit=cover" }
33
+ ],
34
+ htmlAttrs: {
35
+ lang: i18n.locale.value,
36
+ amp: true
37
+ },
38
+ })))
39
+
40
+ import { watch } from 'vue'
41
+ import { client as useClient, useApi } from '@live-change/vue3-ssr'
42
+ const client = useClient()
43
+ watch(client, (newClient, oldClient) => {
44
+ console.log("WATCH CLIENT", oldClient, '=>', newClient)
45
+ })
46
+
47
+ const api = useApi()
48
+ import emailValidator from "@live-change/email-service/clientEmailValidator.js"
49
+ import passwordValidator from "@live-change/password-authentication-service/clientPasswordValidator.js"
50
+ api.validators.email = emailValidator
51
+ api.validators.password = passwordValidator
52
+
53
+ import { defaultHighlightStyle } from "@codemirror/language"
54
+ import { StyleModule } from "style-mod"
55
+ if(typeof window != 'undefined') {
56
+ StyleModule.mount(window.document, defaultHighlightStyle.module)
57
+ }
58
+
59
+ import "./analytics"
60
+
61
+ </script>
@@ -0,0 +1,16 @@
1
+ <template>
2
+ <div>
3
+ <h1>Hello world!</h1>
4
+ <p>{{ currentTime }}</p>
5
+ <Clock :time="currentTime" />
6
+ </div>
7
+ </template>
8
+
9
+ <script setup>
10
+ import { currentTime } from "@live-change/frontend-base";
11
+
12
+ </script>
13
+
14
+ <style scoped>
15
+
16
+ </style>
@@ -0,0 +1,15 @@
1
+ import { analytics } from "@live-change/vue3-components"
2
+
3
+ analytics.on('*', (type, e) => console.log('ANALYTICS EVENT', type, e) )
4
+
5
+ analytics.on('formDone', ({ service, action }) => {
6
+
7
+ })
8
+
9
+ analytics.on('menuOpen', e => {
10
+
11
+ })
12
+
13
+ analytics.on('pageView', ({ to, fullPath }) => {
14
+
15
+ })
@@ -0,0 +1,28 @@
1
+ import deepmerge from 'deepmerge';
2
+
3
+ import * as en from "../locales/en.js"
4
+ import { locales as autoFormLocales } from "@live-change/frontend-auto-form"
5
+ import { locales as userFrontendLocales } from "@live-change/user-frontend"
6
+
7
+ export default {
8
+ defaultLocale: 'en',
9
+ i18n: {
10
+ messages: {
11
+ en: deepmerge.all([
12
+ autoFormLocales.en,
13
+ userFrontendLocales.en,
14
+ en.messages
15
+ ])
16
+ },
17
+ numberFormats: {
18
+ en: deepmerge.all([
19
+ en.numberFormats
20
+ ])
21
+ },
22
+ datetimeFormats: {
23
+ en: deepmerge.all([
24
+ en.datetimeFormats
25
+ ])
26
+ }
27
+ }
28
+ }
@@ -0,0 +1,8 @@
1
+ import { clientEntry } from '@live-change/frontend-base/client-entry.js'
2
+ import App from './App.vue'
3
+ import { createRouter } from './router'
4
+ import config from './config.js'
5
+
6
+ clientEntry(App, createRouter, config)
7
+
8
+ window.appStarted = true
@@ -0,0 +1,8 @@
1
+ import { serverEntry, sitemapEntry } from '@live-change/frontend-base/server-entry.js'
2
+ import App from './App.vue'
3
+ import { createRouter, sitemap as routerSitemap } from './router'
4
+ import config from './config.js'
5
+
6
+ const render = serverEntry(App, createRouter, config)
7
+ const sitemap = sitemapEntry(App, createRouter, routerSitemap, config)
8
+ export { render, sitemap }
@@ -0,0 +1,76 @@
1
+ import {
2
+ createMemoryHistory,
3
+ createRouter as _createRouter,
4
+ createWebHistory
5
+ } from 'vue-router'
6
+
7
+ import {
8
+ installRouterAnalytics
9
+ } from '@live-change/vue3-components'
10
+
11
+ import { dbAdminRoutes } from "@live-change/db-admin"
12
+ import { userRoutes } from "@live-change/user-frontend"
13
+ import { catchAllPagesRoute, contentEditRoutes, pagesSitemap } from "@live-change/content-frontend"
14
+
15
+ import pagesRoutes from '~pages'
16
+
17
+ export function routes(config = {}) {
18
+ const { prefix = '/', route = (r) => r } = config
19
+ return [
20
+ ...userRoutes({ ...config, prefix: prefix + 'user/' }),
21
+
22
+ route({
23
+ name: 'index', path: prefix, meta: { },
24
+ component: () => import("./Index.vue")
25
+ }),
26
+
27
+ ...pagesRoutes,
28
+
29
+ ...contentEditRoutes({ ...config }),
30
+
31
+ ...dbAdminRoutes({ prefix: '/_db', route: r => ({ ...r, meta: { ...r.meta, raw: true }}) }),
32
+ ...catchAllPagesRoute({ ...config }),
33
+ ]
34
+ }
35
+
36
+ export async function sitemap(route, api) {
37
+ route({
38
+ name: 'index'
39
+ })
40
+ await pagesSitemap(route, api)
41
+ }
42
+
43
+ import { client as useClient } from '@live-change/vue3-ssr'
44
+
45
+ export function createRouter(app, config) {
46
+ const client = useClient(app._context)
47
+
48
+ const router = _createRouter({
49
+ // use appropriate history implementation for server/client
50
+ // import.meta.env.SSR is injected by Vite.
51
+ history: import.meta.env.SSR ? createMemoryHistory() : createWebHistory(),
52
+ routes: routes(config)
53
+ })
54
+ installRouterAnalytics(router)
55
+ router.beforeEach(async (to, from) => {
56
+ if(to?.matched.find(m => m?.meta.signedIn)) {
57
+ if(!client.value.user) {
58
+ console.log("REDIRECT TO LOGIN BECAUSE PAGE REQUIRES LOGIN!")
59
+ router.redirectAfterSignIn = to.fullPath
60
+ return { name: 'user:signInEmail' }
61
+ }
62
+ }
63
+ if(to?.matched.find(m => m?.meta.signedOut)) {
64
+ if(client.value.user) {
65
+ console.log("REDIRECT TO USER INDEX BECAUSE PAGE REQUIRES LOGOUT!")
66
+ return { name: 'user:settings' }
67
+ }
68
+ }
69
+ if(to && to.name === 'user:signInEmail' && from?.matched.find(m => m?.meta.saveForSignIn)) {
70
+ console.log("SAVE FOR LOGIN", from.fullPath)
71
+ localStorage.redirectAfterLogin = from.fullPath
72
+ }
73
+ })
74
+ return router
75
+ }
76
+
@@ -0,0 +1,26 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2020",
4
+ "useDefineForClassFields": true,
5
+ "module": "ESNext",
6
+ "lib": ["ES2020", "DOM", "DOM.Iterable"],
7
+ "skipLibCheck": true,
8
+
9
+ /* Bundler mode */
10
+ "moduleResolution": "bundler",
11
+ "allowImportingTsExtensions": true,
12
+ "resolveJsonModule": true,
13
+ "isolatedModules": true,
14
+ "noEmit": true,
15
+ "jsx": "preserve",
16
+
17
+ /* Linting */
18
+ "strict": true,
19
+ "noUnusedLocals": true,
20
+ "noUnusedParameters": true,
21
+ "noFallthroughCasesInSwitch": true
22
+ },
23
+ "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"],
24
+ "references": [{ "path": "./tsconfig.node.json" }]
25
+ }
26
+
@@ -0,0 +1,11 @@
1
+ {
2
+ "compilerOptions": {
3
+ "composite": true,
4
+ "skipLibCheck": true,
5
+ "module": "ESNext",
6
+ "moduleResolution": "bundler",
7
+ "allowSyntheticDefaultImports": true,
8
+ "strict": true
9
+ },
10
+ "include": ["vite.config.ts"]
11
+ }
@@ -0,0 +1,53 @@
1
+ import { defineConfig } from 'vite'
2
+ import Pages from 'vite-plugin-pages'
3
+
4
+ import { fileURLToPath } from 'url'
5
+ import { dirname, join } from 'path'
6
+ import { accessSync, readFileSync } from 'fs'
7
+ const currentModuleDir = dirname(fileURLToPath(import.meta.url))
8
+ const packageJsonPath = dirname(fileURLToPath(import.meta.url))
9
+ .split('/').map((part, i, arr) =>
10
+ join(arr.slice(0, arr.length - i).join('/'), 'package.json')
11
+ ).find(p => { try { accessSync(p); return true } catch(e) { return false }})
12
+ const packageJson = packageJsonPath ? JSON.parse(readFileSync(packageJsonPath, 'utf-8')) : {}
13
+ const name = packageJson.name ?? "Example"
14
+ const version = process.env.VERSION ?? packageJson.version ?? 'unknown'
15
+ const homepage = process.env.BASE_HREF ?? packageJson.homepage
16
+ const domain = process.env.BRAND_DOMAIN || (homepage && homepage.match(/https\:\/\/([^\/]+)/)?.[1]) || 'example.com'
17
+
18
+ // @ts-ignore
19
+ import baseViteConfig from '@live-change/frontend-base/vite-config.js'
20
+
21
+ export default defineConfig(async ({ command, mode }) => {
22
+ const baseConfig = (await baseViteConfig({ command, mode }))
23
+ return {
24
+ ...baseConfig,
25
+
26
+ define: {
27
+ ...baseConfig.define,
28
+ ENV_VERSION: JSON.stringify(version),
29
+ ENV_BRAND_NAME: JSON.stringify(process.env.BRAND_NAME || (name[0].toUpperCase() + name.slice(1))),
30
+ ENV_BRAND_DOMAIN: JSON.stringify(domain),
31
+ },
32
+
33
+ plugins: [
34
+ ...baseConfig.plugins,
35
+ Pages({
36
+ dirs: [
37
+ // basic
38
+ { dir: 'src/pages', baseRoute: '' },
39
+ // blog
40
+ // { dir: 'src/blog', baseRoute: 'blog' },
41
+ ],
42
+ extensions: ['vue', 'md'],
43
+ }),
44
+ ],
45
+
46
+ resolve: {
47
+ ...baseConfig.resolve,
48
+ alias: [
49
+ ...baseConfig.resolve.alias,
50
+ ]
51
+ }
52
+ }
53
+ })
package/index.js ADDED
@@ -0,0 +1,2 @@
1
+
2
+ export { }
package/package.json ADDED
@@ -0,0 +1,107 @@
1
+ {
2
+ "name": "@live-change/survey-frontend",
3
+ "version": "0.8.126",
4
+ "scripts": {
5
+ "memDev": "node server/start.js memDev --enableSessions --initScript ./init.js --dbAccess",
6
+ "localDevInit": "rm tmp.db; node server/start.js localDev --enableSessions --initScript ./init.js --dbAccess",
7
+ "localDev": "node server/start.js localDev --enableSessions --dbAccess",
8
+ "dev": "node server/start.js dev --enableSessions",
9
+ "ssrDev": "node server/start.js ssrDev --enableSessions",
10
+ "serveAllMem": "cross-env NODE_ENV=production node server/start.js ssrServer --withApi --withServices --updateServices --enableSessions --withDb --dbBackend mem --createDb",
11
+ "serveAll": "cross-env NODE_ENV=production node server/start.js ssrServer --withApi --withServices --updateServices --enableSessions",
12
+ "serve": "cross-env NODE_ENV=production node server/start.js ssrServer --enableSessions",
13
+ "memDev:spa": "node server/start.js memDev --enableSessions --initScript ./init.js --dbAccess --spa",
14
+ "localDevInit:spa": "rm tmp.db; node server/start.js localDev --enableSessions --initScript ./init.js --spa",
15
+ "localDev:spa": "node server/start.js localDev --enableSessions --spa",
16
+ "dev:spa": "node server/start.js dev --enableSessions --spa",
17
+ "ssrDev:spa": "node server/start.js ssrDev --enableSessions --spa",
18
+ "serveAllMem:spa": "cross-env NODE_ENV=production node server/start.js server --withApi --withServices --updateServices --enableSessions --withDb --dbBackend mem --createDb --spa",
19
+ "serveAll:spa": "cross-env NODE_ENV=production node server/start.js server --withApi --withServices --updateServices --enableSessions --spa",
20
+ "serve:spa": "cross-env NODE_ENV=production node server/start.js server --enableSessions --spa",
21
+ "apiServer": "node server/start.js apiServer --enableSessions",
22
+ "devApiServer": "node server/start.js devApiServer --enableSessions",
23
+ "memApiServer": "node server/start.js memApiServer --enableSessions",
24
+ "build": "cd front; yarn build:client && yarn build:server",
25
+ "build:client": "cd front; dotenvx run -f ../.env -- vite build --ssrManifest --outDir dist/client",
26
+ "build:server": "cd front; dotenvx run -f ../.env -- vite build --ssr src/entry-server.js --outDir dist/server",
27
+ "build:spa": "cd front; dotenvx run -f ../.env -- vite build --outDir dist/spa",
28
+ "generate": "vite build --ssrManifest --outDir dist/static && yarn build:server && node prerender",
29
+ "debug": "node --inspect-brk server",
30
+ "describe": "node server/start.js describe",
31
+ "changes": "node server/start.js changes"
32
+ },
33
+ "type": "module",
34
+ "dependencies": {
35
+ "@codemirror/language": "6.10.1",
36
+ "@dotenvx/dotenvx": "0.27.0",
37
+ "@fortawesome/fontawesome-free": "^6.5.2",
38
+ "@live-change/access-control-frontend": "^0.8.126",
39
+ "@live-change/access-control-service": "^0.8.126",
40
+ "@live-change/backup-service": "^0.8.126",
41
+ "@live-change/blog-frontend": "^0.8.126",
42
+ "@live-change/blog-service": "^0.8.126",
43
+ "@live-change/cli": "^0.8.126",
44
+ "@live-change/content-frontend": "^0.8.126",
45
+ "@live-change/content-service": "^0.8.126",
46
+ "@live-change/dao": "^0.8.126",
47
+ "@live-change/dao-vue3": "^0.8.126",
48
+ "@live-change/dao-websocket": "^0.8.126",
49
+ "@live-change/db-client": "^0.8.126",
50
+ "@live-change/email-service": "^0.8.126",
51
+ "@live-change/framework": "^0.8.126",
52
+ "@live-change/frontend-auto-form": "^0.8.126",
53
+ "@live-change/frontend-base": "^0.8.126",
54
+ "@live-change/geoip-service": "^0.8.126",
55
+ "@live-change/image-frontend": "^0.8.126",
56
+ "@live-change/locale-settings-service": "^0.8.126",
57
+ "@live-change/password-authentication-service": "^0.8.126",
58
+ "@live-change/prosemirror-service": "^0.8.126",
59
+ "@live-change/secret-code-service": "^0.8.126",
60
+ "@live-change/secret-link-service": "^0.8.126",
61
+ "@live-change/session-service": "^0.8.126",
62
+ "@live-change/survey-service": "^0.8.126",
63
+ "@live-change/task-service": "^0.8.126",
64
+ "@live-change/upload-frontend": "^0.8.126",
65
+ "@live-change/url-frontend": "^0.8.126",
66
+ "@live-change/url-service": "^0.8.126",
67
+ "@live-change/user-frontend": "^0.8.126",
68
+ "@live-change/user-identification-service": "^0.8.126",
69
+ "@live-change/user-service": "^0.8.126",
70
+ "@live-change/vote-service": "^0.8.126",
71
+ "@live-change/vue3-components": "^0.8.126",
72
+ "@live-change/vue3-ssr": "^0.8.126",
73
+ "@live-change/wysiwyg-frontend": "^0.8.126",
74
+ "@vueuse/core": "^10.11.0",
75
+ "codeceptjs-assert": "^0.0.5",
76
+ "compression": "^1.7.4",
77
+ "cross-env": "^7.0.3",
78
+ "get-port-sync": "1.0.1",
79
+ "pica": "^9.0.1",
80
+ "pretty-bytes": "^6.1.1",
81
+ "primeflex": "^3.3.1",
82
+ "primeicons": "^7.0.0",
83
+ "primevue": "^3.52.0",
84
+ "rollup-plugin-node-builtins": "^2.1.2",
85
+ "rollup-plugin-visualizer": "5.12.0",
86
+ "serialize-javascript": "^6.0.2",
87
+ "serve-static": "^1.15.0",
88
+ "v-shared-element": "3.1.1",
89
+ "vue": "^3.4.29",
90
+ "vue-i18n": "^9.10.1",
91
+ "vue-router": "^4.3.3",
92
+ "vue3-scroll-border": "0.1.6"
93
+ },
94
+ "devDependencies": {
95
+ "@live-change/codeceptjs-helper": "^0.8.126",
96
+ "codeceptjs": "^3.6.5",
97
+ "generate-password": "1.7.1",
98
+ "playwright": "^1.41.2",
99
+ "random-profile-generator": "^2.3.0",
100
+ "txtgen": "^3.0.6",
101
+ "webdriverio": "^8.40.2"
102
+ },
103
+ "author": "Michał Łaszczewski <michal@laszczewski.pl>",
104
+ "license": "ISC",
105
+ "description": "",
106
+ "gitHead": "2aa34c0589d115aeaa573bd2cae09bb43a66d162"
107
+ }
@@ -0,0 +1,115 @@
1
+ import dotenv from 'dotenv'
2
+ dotenv.config()
3
+
4
+ import App from "@live-change/framework"
5
+ const app = App.app()
6
+
7
+ const contactTypes = ['email']
8
+
9
+ import securityConfig from './security.config.js'
10
+ import documentTypePage from './page.documentType.js'
11
+
12
+ app.config = {
13
+ services: [
14
+ {
15
+ name: 'timer',
16
+ },
17
+ {
18
+ name: 'session',
19
+ createSessionOnUpdate: true
20
+ },
21
+ {
22
+ name: 'user',
23
+ },
24
+ {
25
+ name: 'email',
26
+ },
27
+ {
28
+ name: 'passwordAuthentication',
29
+ contactTypes,
30
+ signInWithoutPassword: true
31
+ },
32
+ {
33
+ name: 'userIdentification',
34
+ },
35
+ {
36
+ name: 'localeSettings',
37
+ },
38
+ {
39
+ name: 'identicon',
40
+ },
41
+ {
42
+ name: 'accessControl',
43
+ createSessionOnUpdate: true,
44
+ contactTypes,
45
+ },
46
+ {
47
+ name: 'security',
48
+ ...securityConfig,
49
+ },
50
+ {
51
+ name: 'notification',
52
+ contactTypes,
53
+ notificationTypes: ['example_TestNotification']
54
+ },
55
+ {
56
+ name: 'upload',
57
+ },
58
+ {
59
+ name: 'image',
60
+ },
61
+ {
62
+ name: 'secretCode',
63
+ },
64
+ {
65
+ name: 'secretLink',
66
+ },
67
+ {
68
+ name: 'messageAuthentication',
69
+ contactTypes,
70
+ signUp: true,
71
+ signIn: true,
72
+ connect: true
73
+ },
74
+ {
75
+ name: 'googleAuthentication',
76
+ },
77
+ {
78
+ name: 'linkedinAuthentication',
79
+ },
80
+ {
81
+ name: 'url',
82
+ },
83
+ {
84
+ name: 'prosemirror',
85
+ documentTypes: {
86
+ page: documentTypePage,
87
+ /*rich: require('./rich.documentType.js'),*/
88
+ },
89
+ testLatency: 2000
90
+ },
91
+ {
92
+ name: 'content',
93
+ },
94
+ {
95
+ name: 'geoIp',
96
+ geoIpCountryPath: "./data/GeoLite2-Country.mmdb",
97
+ //geoIpDefaultCountry: "pl"
98
+ },
99
+ {
100
+ name: 'vote',
101
+ },
102
+ {
103
+ name: 'task',
104
+ },
105
+ {
106
+ name: 'survey'
107
+ },
108
+ {
109
+ name: 'backup',
110
+ port: 8007
111
+ },
112
+ ]
113
+ }
114
+
115
+ export default app.config
package/server/init.js ADDED
@@ -0,0 +1,10 @@
1
+ import { createUser } from "@live-change/user-frontend/server/init-functions.js"
2
+ import App from '@live-change/framework'
3
+ const app = App.app()
4
+
5
+ export default async function(services) {
6
+
7
+ const testUser = await createUser(services,
8
+ 'Test User', 'test@test.com', 'Testy123', 'u1', ['writer'])
9
+
10
+ }
@@ -0,0 +1,103 @@
1
+ export default {
2
+ "marks": {
3
+ "bold": {},
4
+ "italic": {},
5
+ "underline": {},
6
+ "strike": {}
7
+ },
8
+ "nodes": {
9
+ "paragraph": {
10
+ "content": "inline*",
11
+ "group": "block"
12
+ },
13
+ "horizontalRule": {
14
+ "group": "block"
15
+ },
16
+ "heading": {
17
+ "content": "inline*",
18
+ "group": "block",
19
+ "defining": true,
20
+ "attrs": {
21
+ "level": {
22
+ "default": 1
23
+ }
24
+ }
25
+ },
26
+ "blockquote": {
27
+ "content": "block+",
28
+ "group": "block",
29
+ "defining": true
30
+ },
31
+ "codeBlock": {
32
+ "content": "text*",
33
+ "marks": "",
34
+ "group": "block",
35
+ "code": true,
36
+ "defining": true,
37
+ "attrs": {
38
+ "language": {
39
+ "default": null
40
+ }
41
+ }
42
+ },
43
+ "bulletList": {
44
+ "content": "listItem+",
45
+ "group": "block list"
46
+ },
47
+ "orderedList": {
48
+ "content": "listItem+",
49
+ "group": "block list",
50
+ "attrs": {
51
+ "start": {
52
+ "default": 1
53
+ }
54
+ }
55
+ },
56
+ "listItem": {
57
+ "content": "paragraph block*",
58
+ "defining": true
59
+ },
60
+ "image": {
61
+ "content": "",
62
+ "marks": "",
63
+ "group": "block",
64
+ "inline": false,
65
+ "atom": true,
66
+ "selectable": true,
67
+ "draggable": true,
68
+ "attrs": {
69
+ "image": {
70
+ "default": null
71
+ }
72
+ }
73
+ },
74
+ "doc": {
75
+ "content": "block+"
76
+ },
77
+ "text": {
78
+ "group": "inline"
79
+ },
80
+ "hardBreak": {
81
+ "group": "inline",
82
+ "inline": true,
83
+ "selectable": false
84
+ },
85
+ "component": {
86
+ "content": "block*",
87
+ "marks": "",
88
+ "group": "block",
89
+ "inline": false,
90
+ "selectable": true,
91
+ "draggable": true,
92
+ "attrs": {
93
+ "is": {
94
+ "default": "card"
95
+ },
96
+ "attrs": {
97
+ "default": {}
98
+ }
99
+ }
100
+ }
101
+ },
102
+ "topNode": "doc"
103
+ }