diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index 523865fe..00000000 --- a/.eslintignore +++ /dev/null @@ -1 +0,0 @@ -src/consts/code \ No newline at end of file diff --git a/.eslintrc.js b/.eslintrc.js deleted file mode 100644 index 34d198cb..00000000 --- a/.eslintrc.js +++ /dev/null @@ -1,38 +0,0 @@ -module.exports = { - root: true, - env: { - node: true, - 'vue/setup-compiler-macros': true, - }, - extends: [ - 'plugin:vue/vue3-essential', - '@vue/airbnb', - '@vue/typescript/recommended', - '@vue/eslint-config-typescript', - ], - parserOptions: { - sourceType: 'module', - ecmaVersion: 2022, - }, - rules: { - 'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off', - 'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off', - 'import/prefer-default-export': 'off', - '@typescript-eslint/no-empty-function': 'off', - 'class-methods-use-this': 'off', - 'no-mixed-operators': 'off', - 'no-plusplus': 'off', - 'no-param-reassign': 'off', - 'import/no-unresolved': 'off', - 'max-len': 'off', - 'vue/multi-word-component-names': 'off', - 'import/no-webpack-loader-syntax': 'off', - 'import/no-named-as-default': 'off', - 'max-classes-per-file': 'off', - 'import/no-extraneous-dependencies': 'off', - 'import/no-cycle': 'off', - 'import/extensions': 'off', - 'vue/no-reserved-component-names': 'warn', - 'vue/require-default-prop': 'warn', - }, -}; diff --git a/components/FetchNav.vue b/components/FetchNav.vue deleted file mode 100644 index a7eaeace..00000000 --- a/components/FetchNav.vue +++ /dev/null @@ -1,20 +0,0 @@ - - - diff --git a/components/Intro.vue b/components/Intro.vue deleted file mode 100644 index 10b2fad6..00000000 --- a/components/Intro.vue +++ /dev/null @@ -1,24 +0,0 @@ - - - diff --git a/components/content/ExamplesOverview.vue b/components/content/ExamplesOverview.vue deleted file mode 100644 index a06bb30b..00000000 --- a/components/content/ExamplesOverview.vue +++ /dev/null @@ -1,94 +0,0 @@ - - - - - diff --git a/components/content/FrameExample.vue b/components/content/FrameExample.vue deleted file mode 100644 index 4a154091..00000000 --- a/components/content/FrameExample.vue +++ /dev/null @@ -1,53 +0,0 @@ - - - - - diff --git a/error.vue b/error.vue index 74b6cd83..6e98495f 100644 --- a/error.vue +++ b/error.vue @@ -2,7 +2,7 @@ NotFound - - - diff --git a/plugins/main.js b/plugins/main.js deleted file mode 100644 index 26ad60e2..00000000 --- a/plugins/main.js +++ /dev/null @@ -1,48 +0,0 @@ -import { - Menu, MenuItem, Select, Submenu, Dropdown, Option, - Drawer, Button, Alert, Tag, Tooltip, Collapse, Panel, - Card, Spin, Modal, SkeletonItem, -} from 'view-ui-plus-es'; - -// eslint-disable-next-line no-undef -export default defineNuxtPlugin((nuxtApp) => { - const app = nuxtApp.vueApp; - - app.component('Menu', Menu); - app.component('MenuItem', MenuItem); - app.component('Submenu', Submenu); - app.component('Select', Select); - app.component('Dropdown', Dropdown); - app.component('Option', Option); - app.component('Drawer', Drawer); - app.component('Button', Button); - app.component('IViewAlert', Alert); - app.component('Tag', Tag); - app.component('Tooltip', Tooltip); - app.component('Collapse', Collapse); - app.component('Panel', Panel); - app.component('Card', Card); - app.component('Spin', Spin); - app.component('Modal', Modal); - app.component('SkeletonItem', SkeletonItem); - - nuxtApp.$router.options.scrollBehavior = (to, from, savedPosition) => { - if (savedPosition) return savedPosition; - return new Promise((resolve) => { - setTimeout(() => { - const elem = to.hash && document.querySelector(to.hash); - - if (elem) { - const offset = parseFloat(getComputedStyle(elem).scrollMarginTop); - - resolve({ - el: to.hash, - top: offset, - }); - return; - } - resolve({ top: 0, left: 0 }); - }, 200); - }); - }; -}); diff --git a/plugins/sentry.client.js b/plugins/sentry.client.js deleted file mode 100644 index 8969aeae..00000000 --- a/plugins/sentry.client.js +++ /dev/null @@ -1,27 +0,0 @@ -import { - init, browserTracingIntegration, BrowserProfilingIntegration, replayIntegration, -} from '@sentry/vue'; -import { dsn } from '../config/sentry'; - -// eslint-disable-next-line no-undef -export default defineNuxtPlugin(async (nuxtApp) => { - const app = nuxtApp.vueApp; - - init({ - app, - dsn, - environment: window.location.hostname === 'localhost' ? 'localhost' : 'production', - integrations: [ - browserTracingIntegration({ - router: nuxtApp.$router, - tracePropagationTargets: ['localhost', 'rete.js.org', /^\//], - }), - new BrowserProfilingIntegration(), - replayIntegration(), - ], - replaysSessionSampleRate: 0.5, - replaysOnErrorSampleRate: 1.0, - tracesSampleRate: 1.0, - profilesSampleRate: 1.0, - }); -}); diff --git a/server/plugins/cleanup_prefetch.js b/server/plugins/cleanup_prefetch.js deleted file mode 100644 index dc8bed9f..00000000 --- a/server/plugins/cleanup_prefetch.js +++ /dev/null @@ -1,16 +0,0 @@ -// remove unnecessary script and assets from /preview/ pages - -// eslint-disable-next-line no-undef -export default defineNitroPlugin((nitroApp) => { - nitroApp.hooks.hook('render:html', (html) => { - html.head = html.head.map((chunk) => { - const lines = chunk.split('\n'); - const preloadRegexp = /^/; - const iconsRegexp = /^/)); - html.bodyAppend = html.bodyAppend.filter((line) => !line.match(//)); - } - }); -}); diff --git a/shared/content.ts b/shared/content.ts deleted file mode 100644 index 8b34790a..00000000 --- a/shared/content.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { useRoute } from 'vue-router'; -import { useI18n } from 'vue-i18n'; -import { computed } from 'vue'; -import { omitLocale } from './route'; - -export function useContentPath() { - const route = useRoute(); - const i18n = useI18n(); - - return computed(() => `/${i18n.locale.value}${omitLocale(route.path, i18n.locale.value)}`); -} diff --git a/shared/drawer.ts b/shared/drawer.ts deleted file mode 100644 index c30d802a..00000000 --- a/shared/drawer.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { ref } from 'vue'; -import { useRouter } from 'vue-router'; - -export function useDrawer() { - const router = useRouter(); - const active = ref(false); - - router.beforeEach(() => { - active.value = false; - }); - - return { - active, - }; -} diff --git a/shared/editor.ts b/shared/editor.ts deleted file mode 100644 index e7e99177..00000000 --- a/shared/editor.ts +++ /dev/null @@ -1,284 +0,0 @@ -import { - NodeEditor, ClassicPreset, GetSchemes, NodeId, -} from 'rete'; -import { AreaPlugin, AreaExtensions } from 'rete-area-plugin'; -import { VuePlugin, Presets, VueArea2D } from 'rete-vue-plugin'; -import { DataflowEngine } from 'rete-engine'; - -import { structures } from 'rete-structures'; -import { SelectorEntity } from 'rete-area-plugin/_types/extensions/selectable'; - -const socket = new ClassicPreset.Socket('Number'); - -class NumberNode extends ClassicPreset.Node { - constructor(initial, change) { - super('Number'); - - this.addControl('value', new ClassicPreset.InputControl('number', { initial, change })); - this.addOutput('value', new ClassicPreset.Output(socket, 'Number')); - } - - data() { - return { - value: (this.controls.value as ClassicPreset.InputControl<'number'>).value, - }; - } -} - -class AddNode extends ClassicPreset.Node { - constructor() { - super('Add'); - - this.addControl('value', new ClassicPreset.InputControl('number', { readonly: true })); - this.addInput('a', new ClassicPreset.Input(socket, 'Left')); - this.addInput('b', new ClassicPreset.Input(socket, 'Right')); - this.addOutput('value', new ClassicPreset.Output(socket, 'Number')); - } - - data(inputs) { - const value = (inputs.a || [0])[0] + (inputs.b || [0])[0]; - - (this.controls.value as ClassicPreset.InputControl<'number'>).setValue(value); - - return { - value, - }; - } -} - -class NamelessNode extends ClassicPreset.Node { - parent?: string; - - constructor(public width = 180, public height = 100) { - super(''); - - this.addInput('port', new ClassicPreset.Input(socket)); - this.addOutput('port', new ClassicPreset.Output(socket)); - } - - data() { - return {}; - } -} - -type OnSelect = (label: string, id: string, accumulate: boolean) => void -class Selector extends AreaExtensions.Selector { - constructor(private onSelect?: OnSelect) { - super(); - } - - add(entity: SelectorEntity, accumulate: boolean): void { - super.add(entity, accumulate); - if (this.onSelect) this.onSelect(entity.label, entity.id, accumulate); - } -} - -type NodeProps = NumberNode | AddNode | NamelessNode - -class Connection extends ClassicPreset.Connection { } - -type Schemes = GetSchemes> -type AreaExtra = VueArea2D - -export async function createEditor(container: HTMLElement, props: { - multiselect: boolean, order: boolean, onSelect?: OnSelect -}) { - const editor = new NodeEditor(); - const area = new AreaPlugin(container); - const render = new VuePlugin(); - const engine = new DataflowEngine(); - - area.area.setZoomHandler(null); - area.container.style.overflow = 'initial'; - - render.addPreset(Presets.classic.setup()); - - editor.use(area); - editor.use(engine); - area.use(render); - - const selector = new Selector(props.onSelect); - const nodeSelector = AreaExtensions.selectableNodes(area, selector, { - accumulating: props.multiselect ? AreaExtensions.accumulateOnCtrl() : { active: () => false }, - }); - if (props.order) { - AreaExtensions.simpleNodesOrder(area); - } - - return { - editor, - area, - engine, - nodeSelector, - resize(width: number, graphWidth: number) { - area.area.zoom(width / graphWidth); - }, - }; -} - -type EditorInstance = Awaited> - -export async function introductionGraph({ editor, area, engine }: EditorInstance) { - const add = new AddNode(); - - async function process() { - engine.reset(); - await engine.fetch(add.id); - area.update('control', (add.controls.value as ClassicPreset.InputControl<'number'>).id); - } - - editor.addPipe((context) => { - if (context.type === 'connectioncreated' || context.type === 'connectionremoved') { - process(); - } - - return context; - }); - - const a = new NumberNode(1, process); - const b = new NumberNode(1, process); - - await editor.addNode(a); - await editor.addNode(b); - await editor.addNode(add); - - await editor.addConnection(new ClassicPreset.Connection(a, 'value', add, 'a')); - await editor.addConnection(new ClassicPreset.Connection(b, 'value', add, 'b')); - - await area.translate(a.id, { x: 50, y: 20 }); - await area.translate(b.id, { x: 45, y: 240 }); - await area.translate(add.id, { x: 435, y: 20 }); - - return { - nodes: { a, b, add }, - }; -} - -export async function structuresGraph({ editor, area }: EditorInstance) { - const a = new NamelessNode(); - const b = new NamelessNode(); - const c = new NamelessNode(); - const d = new NamelessNode(); - const e = new NamelessNode(); - const f = new NamelessNode(); - const g = new NamelessNode(); - - await editor.addNode(a); - await editor.addNode(b); - await editor.addNode(c); - await editor.addNode(d); - await editor.addNode(e); - await editor.addNode(f); - await editor.addNode(g); - - await area.translate(a.id, { x: 0, y: 70 }); - await area.translate(b.id, { x: 0, y: 200 }); - await area.translate(c.id, { x: 230, y: 10 }); - await area.translate(d.id, { x: 230, y: 140 }); - await area.translate(e.id, { x: 460, y: 40 }); - await area.translate(f.id, { x: 710, y: 0 }); - await area.translate(g.id, { x: 710, y: 130 }); - - await editor.addConnection(new ClassicPreset.Connection(a, 'port', c, 'port')); - await editor.addConnection(new ClassicPreset.Connection(b, 'port', d, 'port')); - await editor.addConnection(new ClassicPreset.Connection(a, 'port', d, 'port')); - await editor.addConnection(new ClassicPreset.Connection(c, 'port', e, 'port')); - await editor.addConnection(new ClassicPreset.Connection(d, 'port', e, 'port')); - await editor.addConnection(new ClassicPreset.Connection(e, 'port', f, 'port')); - await editor.addConnection(new ClassicPreset.Connection(e, 'port', g, 'port')); - - return { - nodes: { - a, - b, - c, - d, - e, - f, - g, - }, - }; -} - -export async function structuresSubGraph({ editor, area }: EditorInstance) { - const rootParent = new NamelessNode(550, 290); - const nestedParent = new NamelessNode(470, 140); - const a = new NamelessNode(); - const b = new NamelessNode(); - const c = new NamelessNode(); - const d = new NamelessNode(); - - nestedParent.parent = rootParent.id; - a.parent = nestedParent.id; - b.parent = nestedParent.id; - c.parent = rootParent.id; - - await editor.addNode(rootParent); - await editor.addNode(nestedParent); - await editor.addNode(a); - await editor.addNode(b); - await editor.addNode(c); - await editor.addNode(d); - - await area.translate(rootParent.id, { x: 0, y: 0 }); - await area.translate(nestedParent.id, { x: 20, y: 20 }); - await area.translate(a.id, { x: 50, y: 40 }); - await area.translate(b.id, { x: 280, y: 40 }); - await area.translate(c.id, { x: 350, y: 175 }); - await area.translate(d.id, { x: 650, y: 50 }); - - await editor.addConnection(new ClassicPreset.Connection(rootParent, 'port', d, 'port')); - await editor.addConnection(new ClassicPreset.Connection(c, 'port', d, 'port')); - await editor.addConnection(new ClassicPreset.Connection(a, 'port', b, 'port')); - - return { - nodes: { - rootParent, - nestedParent, - a, - b, - c, - d, - }, - }; -} - -export function methodApplicant(editor: NodeEditor, id: string) { - const graphType = ['children', 'parent', 'descendants', 'ancestors', 'orphans', 'siblings'].includes(id) - ? 'subgraph' as const - : 'default' as const; - - return { - graphType, - execute: (pickedNodeId: null | NodeId = null) => { - if (id === 'roots') return structures(editor).roots(); - if (id === 'leaves') return structures(editor).leaves(); - if (id === 'filter') return structures(editor).filter(Boolean, ({ source, target }) => source === pickedNodeId || target === pickedNodeId); - if (id === 'orphans') return structures(editor).orphans(); - - if (!pickedNodeId) throw new Error('pickedNode required'); - - if (id === 'incomers') return structures(editor).incomers(pickedNodeId); - if (id === 'outgoers') return structures(editor).outgoers(pickedNodeId); - if (id === 'successors') return structures(editor).successors(pickedNodeId); - if (id === 'predecessors') return structures(editor).predecessors(pickedNodeId); - - const context = { - nodes: [editor.getNode(pickedNodeId)], - connections: [], - }; - - if (id === 'union') return structures(editor).union(context); - if (id === 'difference') return structures(editor).difference(context); - if (id === 'intersection') return structures(editor).intersection(context); - - if (id === 'children') return structures(editor).children((n) => n.id === pickedNodeId); - if (id === 'parent') return structures(editor).parents((n) => n.id === pickedNodeId); - if (id === 'descendants') return structures(editor).descendants((n) => n.id === pickedNodeId); - if (id === 'ancestors') return structures(editor).ancestors((n) => n.id === pickedNodeId); - if (id === 'siblings') return structures(editor).siblings((n) => n.id === pickedNodeId); - - return structures(editor); - }, - }; -} diff --git a/shared/navigation.ts b/shared/navigation.ts deleted file mode 100644 index ec803dd4..00000000 --- a/shared/navigation.ts +++ /dev/null @@ -1,7 +0,0 @@ -// eslint-disable-next-line @typescript-eslint/no-explicit-any -export function flat(list: { children?: any[] }[]) { - return list.map((item) => (item.children && item.children.length - ? flat(item.children) - : item - )).flat(); -} diff --git a/shared/route.ts b/shared/route.ts deleted file mode 100644 index f3831f81..00000000 --- a/shared/route.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { useI18n } from 'vue-i18n'; - -export function omitLocale(path: string, locale: string) { - return path.replace(new RegExp(`^/${locale}`), ''); -} - -export function usePathSanitizer() { - const { locale } = useI18n(); - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - const localePath = useLocalePath(); - - return { - sanitize(path: string) { - return localePath(omitLocale(path, locale.value)); - }, - }; -} diff --git a/shared/sharethis.ts b/shared/sharethis.ts deleted file mode 100644 index c3c68654..00000000 --- a/shared/sharethis.ts +++ /dev/null @@ -1,64 +0,0 @@ -import { - reactive, provide, inject, onUnmounted, onMounted, ref, computed, Ref, -} from 'vue'; -import { useRoute, useRouter } from 'vue-router'; -import host from '../consts/host.json'; - -declare let process: NodeJS.Process & { client: boolean }; - -type Context = { - consumers: number - title: string | null - visible: boolean - data: Record -} - -export const key = Symbol('sharethis-di-key'); - -export function provideShareThis(): undefined | Context { - if (!process.client) return undefined; - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - useHead({ - script: [ - { - src: 'https://platform-api.sharethis.com/js/sharethis.js#property=644c11c3ac242f001bf9c4da', - async: true, - }, - ], - }); - const route = useRoute(); - const router = useRouter(); - - const consumers = ref(0); - const title = ref(null); - - const data: Context = reactive({ - consumers, - title, - visible: computed(() => consumers.value > 0), - data: { - 'data-title': title, - 'data-url': computed(() => `${host.url}${router.resolve(route).href}`), - }, - }); - - provide(key, data); - - return data; -} - -export function useShareThis(title: string | Ref) { - if (!process.client) return; - const sharethis: Context | undefined = inject(key); - - if (!sharethis) throw new Error('cannot inject sharethis'); - - onMounted(() => { - sharethis.title = typeof title === 'string' ? title : title.value; - sharethis.consumers++; - }); - onUnmounted(() => { - sharethis.consumers--; - }); -} diff --git a/assets/diagrams/.gitignore b/src/assets/diagrams/.gitignore similarity index 100% rename from assets/diagrams/.gitignore rename to src/assets/diagrams/.gitignore diff --git a/assets/diagrams/cli/index.drawio b/src/assets/diagrams/cli/index.drawio similarity index 100% rename from assets/diagrams/cli/index.drawio rename to src/assets/diagrams/cli/index.drawio diff --git a/assets/diagrams/contribution/package.drawio b/src/assets/diagrams/contribution/package.drawio similarity index 100% rename from assets/diagrams/contribution/package.drawio rename to src/assets/diagrams/contribution/package.drawio diff --git a/assets/diagrams/contribution/validate-changes.drawio b/src/assets/diagrams/contribution/validate-changes.drawio similarity index 100% rename from assets/diagrams/contribution/validate-changes.drawio rename to src/assets/diagrams/contribution/validate-changes.drawio diff --git a/assets/diagrams/editor/area.drawio b/src/assets/diagrams/editor/area.drawio similarity index 100% rename from assets/diagrams/editor/area.drawio rename to src/assets/diagrams/editor/area.drawio diff --git a/assets/diagrams/editor/classic-preset.drawio b/src/assets/diagrams/editor/classic-preset.drawio similarity index 100% rename from assets/diagrams/editor/classic-preset.drawio rename to src/assets/diagrams/editor/classic-preset.drawio diff --git a/assets/diagrams/editor/connection.drawio b/src/assets/diagrams/editor/connection.drawio similarity index 100% rename from assets/diagrams/editor/connection.drawio rename to src/assets/diagrams/editor/connection.drawio diff --git a/assets/diagrams/editor/node-editor.drawio b/src/assets/diagrams/editor/node-editor.drawio similarity index 100% rename from assets/diagrams/editor/node-editor.drawio rename to src/assets/diagrams/editor/node-editor.drawio diff --git a/assets/diagrams/editor/rendering.drawio b/src/assets/diagrams/editor/rendering.drawio similarity index 100% rename from assets/diagrams/editor/rendering.drawio rename to src/assets/diagrams/editor/rendering.drawio diff --git a/assets/diagrams/engine/architecture.drawio b/src/assets/diagrams/engine/architecture.drawio similarity index 100% rename from assets/diagrams/engine/architecture.drawio rename to src/assets/diagrams/engine/architecture.drawio diff --git a/assets/diagrams/engine/control-flow.drawio b/src/assets/diagrams/engine/control-flow.drawio similarity index 100% rename from assets/diagrams/engine/control-flow.drawio rename to src/assets/diagrams/engine/control-flow.drawio diff --git a/assets/diagrams/engine/dataflow.drawio b/src/assets/diagrams/engine/dataflow.drawio similarity index 100% rename from assets/diagrams/engine/dataflow.drawio rename to src/assets/diagrams/engine/dataflow.drawio diff --git a/assets/diagrams/guides/3d/index.drawio b/src/assets/diagrams/guides/3d/index.drawio similarity index 100% rename from assets/diagrams/guides/3d/index.drawio rename to src/assets/diagrams/guides/3d/index.drawio diff --git a/assets/diagrams/guides/3d/scene.drawio b/src/assets/diagrams/guides/3d/scene.drawio similarity index 100% rename from assets/diagrams/guides/3d/scene.drawio rename to src/assets/diagrams/guides/3d/scene.drawio diff --git a/assets/diagrams/guides/arrange/index.drawio b/src/assets/diagrams/guides/arrange/index.drawio similarity index 100% rename from assets/diagrams/guides/arrange/index.drawio rename to src/assets/diagrams/guides/arrange/index.drawio diff --git a/assets/diagrams/guides/data-structures/connections.drawio b/src/assets/diagrams/guides/data-structures/connections.drawio similarity index 100% rename from assets/diagrams/guides/data-structures/connections.drawio rename to src/assets/diagrams/guides/data-structures/connections.drawio diff --git a/assets/diagrams/guides/data-structures/nodes.drawio b/src/assets/diagrams/guides/data-structures/nodes.drawio similarity index 100% rename from assets/diagrams/guides/data-structures/nodes.drawio rename to src/assets/diagrams/guides/data-structures/nodes.drawio diff --git a/assets/diagrams/guides/data-structures/structures.drawio b/src/assets/diagrams/guides/data-structures/structures.drawio similarity index 100% rename from assets/diagrams/guides/data-structures/structures.drawio rename to src/assets/diagrams/guides/data-structures/structures.drawio diff --git a/assets/diagrams/guides/readonly/index.drawio b/src/assets/diagrams/guides/readonly/index.drawio similarity index 100% rename from assets/diagrams/guides/readonly/index.drawio rename to src/assets/diagrams/guides/readonly/index.drawio diff --git a/assets/diagrams/integration/architecture.drawio b/src/assets/diagrams/integration/architecture.drawio similarity index 100% rename from assets/diagrams/integration/architecture.drawio rename to src/assets/diagrams/integration/architecture.drawio diff --git a/assets/diagrams/integration/combine.drawio b/src/assets/diagrams/integration/combine.drawio similarity index 100% rename from assets/diagrams/integration/combine.drawio rename to src/assets/diagrams/integration/combine.drawio diff --git a/assets/diagrams/integration/presets.drawio b/src/assets/diagrams/integration/presets.drawio similarity index 100% rename from assets/diagrams/integration/presets.drawio rename to src/assets/diagrams/integration/presets.drawio diff --git a/assets/diagrams/kit/index.drawio b/src/assets/diagrams/kit/index.drawio similarity index 100% rename from assets/diagrams/kit/index.drawio rename to src/assets/diagrams/kit/index.drawio diff --git a/assets/diagrams/plugin-system/addPipe.drawio b/src/assets/diagrams/plugin-system/addPipe.drawio similarity index 100% rename from assets/diagrams/plugin-system/addPipe.drawio rename to src/assets/diagrams/plugin-system/addPipe.drawio diff --git a/assets/diagrams/plugin-system/architecture.drawio b/src/assets/diagrams/plugin-system/architecture.drawio similarity index 100% rename from assets/diagrams/plugin-system/architecture.drawio rename to src/assets/diagrams/plugin-system/architecture.drawio diff --git a/assets/diagrams/presets/architecture.drawio b/src/assets/diagrams/presets/architecture.drawio similarity index 100% rename from assets/diagrams/presets/architecture.drawio rename to src/assets/diagrams/presets/architecture.drawio diff --git a/assets/diagrams/qa/index.drawio b/src/assets/diagrams/qa/index.drawio similarity index 100% rename from assets/diagrams/qa/index.drawio rename to src/assets/diagrams/qa/index.drawio diff --git a/assets/icon.png b/src/assets/icon.png similarity index 100% rename from assets/icon.png rename to src/assets/icon.png diff --git a/assets/images/introduction.png b/src/assets/images/introduction.png similarity index 100% rename from assets/images/introduction.png rename to src/assets/images/introduction.png diff --git a/assets/images/patreon.png b/src/assets/images/patreon.png similarity index 100% rename from assets/images/patreon.png rename to src/assets/images/patreon.png diff --git a/assets/styles/common.sass b/src/assets/styles/common.sass similarity index 100% rename from assets/styles/common.sass rename to src/assets/styles/common.sass diff --git a/assets/styles/global.css b/src/assets/styles/global.css similarity index 100% rename from assets/styles/global.css rename to src/assets/styles/global.css diff --git a/assets/styles/media.sass b/src/assets/styles/media.sass similarity index 100% rename from assets/styles/media.sass rename to src/assets/styles/media.sass diff --git a/assets/styles/vars.sass b/src/assets/styles/vars.sass similarity index 100% rename from assets/styles/vars.sass rename to src/assets/styles/vars.sass diff --git a/components/Content.vue b/src/components/Content.vue similarity index 70% rename from components/Content.vue rename to src/components/Content.vue index 5cbfb8ff..6f5e5f00 100644 --- a/components/Content.vue +++ b/src/components/Content.vue @@ -3,14 +3,14 @@ IViewContent.content slot - diff --git a/components/Nav.vue b/src/components/Nav.vue similarity index 71% rename from components/Nav.vue rename to src/components/Nav.vue index 2cf6df4e..d96531cb 100644 --- a/components/Nav.vue +++ b/src/components/Nav.vue @@ -20,39 +20,41 @@ client-only .title {{ data.title }} - diff --git a/src/components/content/FrameExample.vue b/src/components/content/FrameExample.vue new file mode 100644 index 00000000..9cad8b01 --- /dev/null +++ b/src/components/content/FrameExample.vue @@ -0,0 +1,59 @@ + + + + + diff --git a/components/content/Introduction.vue b/src/components/content/Introduction.vue similarity index 64% rename from components/content/Introduction.vue rename to src/components/content/Introduction.vue index 3f18deee..a19a3499 100644 --- a/components/content/Introduction.vue +++ b/src/components/content/Introduction.vue @@ -16,103 +16,108 @@ ) - diff --git a/components/content/ProExample.vue b/src/components/content/ProExample.vue similarity index 85% rename from components/content/ProExample.vue rename to src/components/content/ProExample.vue index 2bf9cd6d..2c1d2aa8 100644 --- a/components/content/ProExample.vue +++ b/src/components/content/ProExample.vue @@ -17,23 +17,23 @@ BaseExample ) - diff --git a/pages/sponsor/index.vue b/src/pages/sponsor/index.vue similarity index 86% rename from pages/sponsor/index.vue rename to src/pages/sponsor/index.vue index 23e92e04..95c10d70 100644 --- a/pages/sponsor/index.vue +++ b/src/pages/sponsor/index.vue @@ -33,18 +33,18 @@ a(href="mailto:info@retejs.org") info@retejs.org - - `, - ); - }); -}); + `) + }) +}) diff --git a/shared/assets.ts b/src/shared/assets.ts similarity index 60% rename from shared/assets.ts rename to src/shared/assets.ts index aa16dc4a..81bb2368 100644 --- a/shared/assets.ts +++ b/src/shared/assets.ts @@ -1,9 +1,9 @@ export function getAsset(path: string) { - return `https://raw.githubusercontent.com/retejs/retejs.org/assets/${path}`; + return `https://raw.githubusercontent.com/retejs/retejs.org/assets/${path}` } export function getPreview(path: string) { - return getAsset(`preview/${path}`); + return getAsset(`preview/${path}`) } -export const mainPreview = getAsset('main.png'); +export const mainPreview = getAsset('main.png') diff --git a/src/shared/content.ts b/src/shared/content.ts new file mode 100644 index 00000000..6ad8b9fb --- /dev/null +++ b/src/shared/content.ts @@ -0,0 +1,12 @@ +import { computed } from 'vue' +import { useI18n } from 'vue-i18n' +import { useRoute } from 'vue-router' + +import { omitLocale } from './route' + +export function useContentPath() { + const route = useRoute() + const i18n = useI18n() + + return computed(() => `/${i18n.locale.value}${omitLocale(route.path, i18n.locale.value)}`) +} diff --git a/src/shared/drawer.ts b/src/shared/drawer.ts new file mode 100644 index 00000000..f80b228d --- /dev/null +++ b/src/shared/drawer.ts @@ -0,0 +1,15 @@ +import { ref } from 'vue' +import { useRouter } from 'vue-router' + +export function useDrawer() { + const router = useRouter() + const active = ref(false) + + router.beforeEach(() => { + active.value = false + }) + + return { + active + } +} diff --git a/src/shared/editor.ts b/src/shared/editor.ts new file mode 100644 index 00000000..ae3ddc62 --- /dev/null +++ b/src/shared/editor.ts @@ -0,0 +1,292 @@ +/* eslint-disable max-statements */ +/* eslint-disable complexity */ +import { + ClassicPreset, type GetSchemes, NodeEditor, type NodeId +} from 'rete' +import { AreaExtensions, AreaPlugin } from 'rete-area-plugin' +import type { SelectorEntity } from 'rete-area-plugin/_types/extensions/selectable' +import { DataflowEngine } from 'rete-engine' +import { structures } from 'rete-structures' +import { Presets, type VueArea2D, VuePlugin } from 'rete-vue-plugin' + +const socket = new ClassicPreset.Socket('Number') + +class NumberNode extends ClassicPreset.Node { + constructor(initial: any, change: any) { + super('Number') + + this.addControl('value', new ClassicPreset.InputControl('number', { initial, change })) + this.addOutput('value', new ClassicPreset.Output(socket, 'Number')) + } + + data() { + return { + value: (this.controls.value as ClassicPreset.InputControl<'number'>).value + } + } +} + +class AddNode extends ClassicPreset.Node { + constructor() { + super('Add') + + this.addControl('value', new ClassicPreset.InputControl('number', { readonly: true })) + this.addInput('a', new ClassicPreset.Input(socket, 'Left')) + this.addInput('b', new ClassicPreset.Input(socket, 'Right')) + this.addOutput('value', new ClassicPreset.Output(socket, 'Number')) + } + + data(inputs: any) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/restrict-plus-operands + const value = (inputs.a || [0])[0] + (inputs.b || [0])[0]; + + (this.controls.value as ClassicPreset.InputControl<'number'>).setValue(value) + + return { + value + } + } +} + +class NamelessNode extends ClassicPreset.Node { + parent?: string + + constructor(public width = 180, public height = 100) { + super('') + + this.addInput('port', new ClassicPreset.Input(socket)) + this.addOutput('port', new ClassicPreset.Output(socket)) + } + + data() { + return {} + } +} + +type OnSelect = (label: string, id: string, accumulate: boolean) => void +class Selector extends AreaExtensions.Selector { + constructor(private onSelect?: OnSelect) { + super() + } + + override add(entity: SelectorEntity, accumulate: boolean): void { + super.add(entity, accumulate) + if (this.onSelect) this.onSelect(entity.label, entity.id, accumulate) + } +} + +type NodeProps = NumberNode | AddNode | NamelessNode + +class Connection extends ClassicPreset.Connection { } + +type Schemes = GetSchemes> +type AreaExtra = VueArea2D + +// eslint-disable-next-line @typescript-eslint/require-await +export async function createEditor(container: HTMLElement, props: { + multiselect: boolean + order: boolean + onSelect?: OnSelect +}) { + const editor = new NodeEditor() + const area = new AreaPlugin(container) + const render = new VuePlugin() + const engine = new DataflowEngine() + + area.area.setZoomHandler(null) + area.container.style.overflow = 'initial' + + render.addPreset(Presets.classic.setup()) + + editor.use(area) + editor.use(engine) + area.use(render) + + const selector = new Selector(props.onSelect) + const nodeSelector = AreaExtensions.selectableNodes(area, selector, { + accumulating: props.multiselect + ? AreaExtensions.accumulateOnCtrl() + : { active: () => false } + }) + + if (props.order) { + AreaExtensions.simpleNodesOrder(area) + } + + return { + editor, + area, + engine, + nodeSelector, + resize(width: number, graphWidth: number) { + void area.area.zoom(width / graphWidth) + } + } +} + +type EditorInstance = Awaited> + +export async function introductionGraph({ editor, area, engine }: EditorInstance) { + const add = new AddNode() + + async function process() { + engine.reset() + await engine.fetch(add.id) + void area.update('control', (add.controls.value as ClassicPreset.InputControl<'number'>).id) + } + + editor.addPipe(context => { + if (context.type === 'connectioncreated' || context.type === 'connectionremoved') { + void process() + } + + return context + }) + + const a = new NumberNode(1, process) + const b = new NumberNode(1, process) + + await editor.addNode(a) + await editor.addNode(b) + await editor.addNode(add) + + await editor.addConnection(new ClassicPreset.Connection(a, 'value', add, 'a')) + await editor.addConnection(new ClassicPreset.Connection(b, 'value', add, 'b')) + + await area.translate(a.id, { x: 50, y: 20 }) + await area.translate(b.id, { x: 45, y: 240 }) + await area.translate(add.id, { x: 435, y: 20 }) + + return { + nodes: { a, b, add } + } +} + +export async function structuresGraph({ editor, area }: EditorInstance) { + const a = new NamelessNode() + const b = new NamelessNode() + const c = new NamelessNode() + const d = new NamelessNode() + const e = new NamelessNode() + const f = new NamelessNode() + const g = new NamelessNode() + + await editor.addNode(a) + await editor.addNode(b) + await editor.addNode(c) + await editor.addNode(d) + await editor.addNode(e) + await editor.addNode(f) + await editor.addNode(g) + + await area.translate(a.id, { x: 0, y: 70 }) + await area.translate(b.id, { x: 0, y: 200 }) + await area.translate(c.id, { x: 230, y: 10 }) + await area.translate(d.id, { x: 230, y: 140 }) + await area.translate(e.id, { x: 460, y: 40 }) + await area.translate(f.id, { x: 710, y: 0 }) + await area.translate(g.id, { x: 710, y: 130 }) + + await editor.addConnection(new ClassicPreset.Connection(a, 'port', c, 'port')) + await editor.addConnection(new ClassicPreset.Connection(b, 'port', d, 'port')) + await editor.addConnection(new ClassicPreset.Connection(a, 'port', d, 'port')) + await editor.addConnection(new ClassicPreset.Connection(c, 'port', e, 'port')) + await editor.addConnection(new ClassicPreset.Connection(d, 'port', e, 'port')) + await editor.addConnection(new ClassicPreset.Connection(e, 'port', f, 'port')) + await editor.addConnection(new ClassicPreset.Connection(e, 'port', g, 'port')) + + return { + nodes: { + a, + b, + c, + d, + e, + f, + g + } + } +} + +export async function structuresSubGraph({ editor, area }: EditorInstance) { + const rootParent = new NamelessNode(550, 290) + const nestedParent = new NamelessNode(470, 140) + const a = new NamelessNode() + const b = new NamelessNode() + const c = new NamelessNode() + const d = new NamelessNode() + + nestedParent.parent = rootParent.id + a.parent = nestedParent.id + b.parent = nestedParent.id + c.parent = rootParent.id + + await editor.addNode(rootParent) + await editor.addNode(nestedParent) + await editor.addNode(a) + await editor.addNode(b) + await editor.addNode(c) + await editor.addNode(d) + + await area.translate(rootParent.id, { x: 0, y: 0 }) + await area.translate(nestedParent.id, { x: 20, y: 20 }) + await area.translate(a.id, { x: 50, y: 40 }) + await area.translate(b.id, { x: 280, y: 40 }) + await area.translate(c.id, { x: 350, y: 175 }) + await area.translate(d.id, { x: 650, y: 50 }) + + await editor.addConnection(new ClassicPreset.Connection(rootParent, 'port', d, 'port')) + await editor.addConnection(new ClassicPreset.Connection(c, 'port', d, 'port')) + await editor.addConnection(new ClassicPreset.Connection(a, 'port', b, 'port')) + + return { + nodes: { + rootParent, + nestedParent, + a, + b, + c, + d + } + } +} + +export function methodApplicant(editor: NodeEditor, id: string) { + const graphType = ['children', 'parent', 'descendants', 'ancestors', 'orphans', 'siblings'].includes(id) + ? 'subgraph' as const + : 'default' as const + + return { + graphType, + execute: (pickedNodeId: null | NodeId = null) => { + if (id === 'roots') return structures(editor).roots() + if (id === 'leaves') return structures(editor).leaves() + if (id === 'filter') return structures(editor).filter(Boolean, ({ source, target }) => source === pickedNodeId || target === pickedNodeId) + if (id === 'orphans') return structures(editor).orphans() + + if (!pickedNodeId) throw new Error('pickedNode required') + + if (id === 'incomers') return structures(editor).incomers(pickedNodeId) + if (id === 'outgoers') return structures(editor).outgoers(pickedNodeId) + if (id === 'successors') return structures(editor).successors(pickedNodeId) + if (id === 'predecessors') return structures(editor).predecessors(pickedNodeId) + + const context = { + nodes: [editor.getNode(pickedNodeId)!], + connections: [] + } + + if (id === 'union') return structures(editor).union(context) + if (id === 'difference') return structures(editor).difference(context) + if (id === 'intersection') return structures(editor).intersection(context) + + if (id === 'children') return structures(editor).children(n => n.id === pickedNodeId) + if (id === 'parent') return structures(editor).parents(n => n.id === pickedNodeId) + if (id === 'descendants') return structures(editor).descendants(n => n.id === pickedNodeId) + if (id === 'ancestors') return structures(editor).ancestors(n => n.id === pickedNodeId) + if (id === 'siblings') return structures(editor).siblings(n => n.id === pickedNodeId) + + return structures(editor) + } + } +} diff --git a/src/shared/navigation.ts b/src/shared/navigation.ts new file mode 100644 index 00000000..dd84f4df --- /dev/null +++ b/src/shared/navigation.ts @@ -0,0 +1,6 @@ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export function flat(list: { children?: any[] }[]): any { + return list.map(item => item.children?.length + ? flat(item.children) + : item).flat() +} diff --git a/src/shared/route.ts b/src/shared/route.ts new file mode 100644 index 00000000..b91b3b6e --- /dev/null +++ b/src/shared/route.ts @@ -0,0 +1,18 @@ +import { useI18n } from 'vue-i18n' + +export function omitLocale(path: string, locale: string) { + return path.replace(new RegExp(`^/${locale}`), '') +} + +export function usePathSanitizer() { + const { locale } = useI18n() + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + const localePath = useLocalePath() + + return { + sanitize(path: string) { + return localePath(omitLocale(path, locale.value)) + } + } +} diff --git a/shared/seoLang.ts b/src/shared/seoLang.ts similarity index 58% rename from shared/seoLang.ts rename to src/shared/seoLang.ts index 00f51411..8c9cd537 100644 --- a/shared/seoLang.ts +++ b/src/shared/seoLang.ts @@ -1,13 +1,13 @@ -import { useI18n } from 'vue-i18n'; +import { useI18n } from 'vue-i18n' export function seoLang() { - const { locale } = useI18n(); + const { locale } = useI18n() // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore useHead({ htmlAttrs: { - lang: locale, - }, - }); + lang: locale + } + }) } diff --git a/src/shared/sharethis.ts b/src/shared/sharethis.ts new file mode 100644 index 00000000..14644ece --- /dev/null +++ b/src/shared/sharethis.ts @@ -0,0 +1,68 @@ +/* eslint-disable @typescript-eslint/naming-convention */ +/* eslint-disable init-declarations */ +/* eslint-disable no-undefined */ +import { computed, inject, onMounted, onUnmounted, provide, reactive, type Ref, ref } from 'vue' +import { useRoute, useRouter } from 'vue-router' + +import host from '../consts/host.json' + +declare let process: NodeJS.Process & { client: boolean } + +type Context = { + consumers: number + title: string | null + visible: boolean + data: Record +} + +export const key = Symbol('sharethis-di-key') + +export function provideShareThis(): undefined | Context { + if (!process.client) return undefined + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + useHead({ + script: [ + { + src: 'https://platform-api.sharethis.com/js/sharethis.js#property=644c11c3ac242f001bf9c4da', + async: true + } + ] + }) + const route = useRoute() + const router = useRouter() + + const consumers = ref(0) + const title = ref(null) + + const data: Context = reactive({ + consumers, + title, + visible: computed(() => consumers.value > 0), + data: { + 'data-title': title, + 'data-url': computed(() => `${host.url}${router.resolve(route).href}`) + } + }) + + provide(key, data) + + return data +} + +export function useShareThis(title: string | Ref) { + if (!process.client) return + const sharethis: Context | undefined = inject(key) + + if (!sharethis) throw new Error('cannot inject sharethis') + + onMounted(() => { + sharethis.title = typeof title === 'string' + ? title + : title.value + sharethis.consumers++ + }) + onUnmounted(() => { + sharethis.consumers-- + }) +} diff --git a/src/sw.ts b/src/sw.ts index 3b488106..3e2a9e82 100644 --- a/src/sw.ts +++ b/src/sw.ts @@ -1,42 +1,39 @@ -/* eslint-disable no-underscore-dangle */ -/* eslint-disable no-restricted-globals */ -import { cacheNames, clientsClaim } from 'workbox-core'; -import { registerRoute } from 'workbox-routing'; -import { NetworkFirst } from 'workbox-strategies'; +import { cacheNames, clientsClaim } from 'workbox-core' +import { registerRoute } from 'workbox-routing' +import { NetworkFirst } from 'workbox-strategies' +// eslint-disable-next-line init-declarations declare const self: Window & typeof globalThis & { location: string + // eslint-disable-next-line @typescript-eslint/naming-convention __WB_MANIFEST: { url: string, href: string }[] - skipWaiting(): void; -}; - -const credentials = 'same-origin' as const; -const manifest = self.__WB_MANIFEST; - -const cacheName = cacheNames.runtime; -const cacheEntries: RequestInfo[] = []; - -const manifestURLs = manifest.map( - (entry) => { - const url = new URL(entry.url, self.location); - cacheEntries.push(new Request(url.href, { - credentials, - })); - return url.href; - }, -); - -self.addEventListener('install', (event) => { + skipWaiting(): void +} + +const credentials = 'same-origin' +const manifest = self.__WB_MANIFEST + +const cacheName = cacheNames.runtime +const cacheEntries: RequestInfo[] = [] + +const manifestURLs = manifest.map(entry => { + const url = new URL(entry.url, self.location) + + cacheEntries.push(new Request(url.href, { + credentials + })) + return url.href +}) + +self.addEventListener('install', event => { // eslint-disable-next-line @typescript-eslint/no-explicit-any - (event as any).waitUntil( - caches.open(cacheName).then((cache) => cache.addAll(cacheEntries)), - ); -}); + (event as any).waitUntil(caches.open(cacheName).then(cache => cache.addAll(cacheEntries))) +}) registerRoute( ({ url }) => manifestURLs.includes(url.href), - new NetworkFirst(), -); + new NetworkFirst() +) -self.skipWaiting(); -clientsClaim(); +self.skipWaiting() +clientsClaim()