@parallelworks/tandem-web 0.140.0 → 0.141.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.
- package/_virtual/_virtual_i18n/en/common.js +22 -0
- package/_virtual/_virtual_i18n/es/common.js +22 -0
- package/_virtual/_virtual_i18n/ja/common.js +22 -0
- package/_virtual/_virtual_i18n/ko/common.js +22 -0
- package/_virtual/_virtual_i18n/zh/common.js +22 -0
- package/components/DocButton.js +221 -0
- package/components/Editor.js +77 -75
- package/components/SlashMenu.js +2 -0
- package/lib/docs.js +158 -123
- package/package.json +1 -1
- package/styles.css +4 -0
|
@@ -1281,6 +1281,7 @@ var e = {
|
|
|
1281
1281
|
description: "A team has its own issues, workflow and members. Its key starts each issue ID, as in ENG-42."
|
|
1282
1282
|
},
|
|
1283
1283
|
docs: {
|
|
1284
|
+
spaceDefault: "Start new docs in this space from it",
|
|
1284
1285
|
duplicate: "Duplicate",
|
|
1285
1286
|
copyOf: "Copy of {title}",
|
|
1286
1287
|
subPages: "Sub-pages",
|
|
@@ -2239,6 +2240,22 @@ var e = {
|
|
|
2239
2240
|
copyLink: "Copy link to heading",
|
|
2240
2241
|
delete: "Delete"
|
|
2241
2242
|
},
|
|
2243
|
+
docButton: {
|
|
2244
|
+
untitled: "Button",
|
|
2245
|
+
edit: "Change the button",
|
|
2246
|
+
label: "Label",
|
|
2247
|
+
labelPlaceholder: "Add this week",
|
|
2248
|
+
does: "When pressed",
|
|
2249
|
+
insert: "Insert blocks",
|
|
2250
|
+
makeDoc: "Make a doc",
|
|
2251
|
+
blocks: "Blocks to insert, in Markdown",
|
|
2252
|
+
blocksPlaceholder: "## Week of '{{date}}'\n\n- [ ] ",
|
|
2253
|
+
placeholders: "'{{date}}', '{{time}}' and '{{author}}' are filled in when it's pressed.",
|
|
2254
|
+
template: "Template",
|
|
2255
|
+
chooseTemplate: "Choose a template",
|
|
2256
|
+
parent: "Under",
|
|
2257
|
+
thisDoc: "This doc"
|
|
2258
|
+
},
|
|
2242
2259
|
linkCard: {
|
|
2243
2260
|
address: "Address of the page",
|
|
2244
2261
|
make: "Make card",
|
|
@@ -2373,6 +2390,11 @@ var e = {
|
|
|
2373
2390
|
hint: "Rows and columns",
|
|
2374
2391
|
keywords: "grid columns rows"
|
|
2375
2392
|
},
|
|
2393
|
+
button: {
|
|
2394
|
+
label: "Button",
|
|
2395
|
+
hint: "A button that inserts blocks or makes a doc from a template",
|
|
2396
|
+
keywords: "button template insert repeat weekly"
|
|
2397
|
+
},
|
|
2376
2398
|
diagram: {
|
|
2377
2399
|
label: "Diagram",
|
|
2378
2400
|
hint: "A flowchart, sequence, state or Gantt diagram drawn from Mermaid text",
|
|
@@ -1281,6 +1281,7 @@ var e = {
|
|
|
1281
1281
|
description: "Un equipo tiene sus propias incidencias, flujo de trabajo y miembros. Su clave inicia el ID de cada incidencia, como en ENG-42."
|
|
1282
1282
|
},
|
|
1283
1283
|
docs: {
|
|
1284
|
+
spaceDefault: "Empezar los documentos nuevos de este espacio con ella",
|
|
1284
1285
|
duplicate: "Duplicar",
|
|
1285
1286
|
copyOf: "Copia de {title}",
|
|
1286
1287
|
subPages: "Subpáginas",
|
|
@@ -2239,6 +2240,22 @@ var e = {
|
|
|
2239
2240
|
copyLink: "Copiar enlace al encabezado",
|
|
2240
2241
|
delete: "Eliminar"
|
|
2241
2242
|
},
|
|
2243
|
+
docButton: {
|
|
2244
|
+
untitled: "Botón",
|
|
2245
|
+
edit: "Cambiar el botón",
|
|
2246
|
+
label: "Etiqueta",
|
|
2247
|
+
labelPlaceholder: "Añadir esta semana",
|
|
2248
|
+
does: "Al pulsarlo",
|
|
2249
|
+
insert: "Insertar bloques",
|
|
2250
|
+
makeDoc: "Crear un documento",
|
|
2251
|
+
blocks: "Bloques que inserta, en Markdown",
|
|
2252
|
+
blocksPlaceholder: "## Semana del '{{date}}'\n\n- [ ] ",
|
|
2253
|
+
placeholders: "'{{date}}', '{{time}}' y '{{author}}' se rellenan al pulsarlo.",
|
|
2254
|
+
template: "Plantilla",
|
|
2255
|
+
chooseTemplate: "Elige una plantilla",
|
|
2256
|
+
parent: "Dentro de",
|
|
2257
|
+
thisDoc: "Este documento"
|
|
2258
|
+
},
|
|
2242
2259
|
linkCard: {
|
|
2243
2260
|
address: "Dirección de la página",
|
|
2244
2261
|
make: "Crear tarjeta",
|
|
@@ -2373,6 +2390,11 @@ var e = {
|
|
|
2373
2390
|
hint: "Filas y columnas",
|
|
2374
2391
|
keywords: "cuadrícula columnas filas grid columns rows"
|
|
2375
2392
|
},
|
|
2393
|
+
button: {
|
|
2394
|
+
label: "Botón",
|
|
2395
|
+
hint: "Un botón que inserta bloques o crea un documento desde una plantilla",
|
|
2396
|
+
keywords: "botón plantilla insertar repetir button"
|
|
2397
|
+
},
|
|
2376
2398
|
diagram: {
|
|
2377
2399
|
label: "Diagrama",
|
|
2378
2400
|
hint: "Un diagrama de flujo, secuencia, estados o Gantt a partir de texto Mermaid",
|
|
@@ -1281,6 +1281,7 @@ var e = {
|
|
|
1281
1281
|
description: "チームには独自の課題、ワークフロー、メンバーがあります。チームのキーは ENG-42 のように各課題 ID の先頭に付きます。"
|
|
1282
1282
|
},
|
|
1283
1283
|
docs: {
|
|
1284
|
+
spaceDefault: "このスペースの新しいドキュメントに使う",
|
|
1284
1285
|
duplicate: "複製",
|
|
1285
1286
|
copyOf: "{title} のコピー",
|
|
1286
1287
|
subPages: "サブページ",
|
|
@@ -2239,6 +2240,22 @@ var e = {
|
|
|
2239
2240
|
copyLink: "見出しへのリンクをコピー",
|
|
2240
2241
|
delete: "削除"
|
|
2241
2242
|
},
|
|
2243
|
+
docButton: {
|
|
2244
|
+
untitled: "ボタン",
|
|
2245
|
+
edit: "ボタンを変更",
|
|
2246
|
+
label: "ラベル",
|
|
2247
|
+
labelPlaceholder: "今週を追加",
|
|
2248
|
+
does: "押したとき",
|
|
2249
|
+
insert: "ブロックを挿入",
|
|
2250
|
+
makeDoc: "ドキュメントを作成",
|
|
2251
|
+
blocks: "挿入するブロック(Markdown)",
|
|
2252
|
+
blocksPlaceholder: "## '{{date}}' の週\n\n- [ ] ",
|
|
2253
|
+
placeholders: "'{{date}}'、'{{time}}'、'{{author}}' は押したときに埋まります。",
|
|
2254
|
+
template: "テンプレート",
|
|
2255
|
+
chooseTemplate: "テンプレートを選択",
|
|
2256
|
+
parent: "親",
|
|
2257
|
+
thisDoc: "このドキュメント"
|
|
2258
|
+
},
|
|
2242
2259
|
linkCard: {
|
|
2243
2260
|
address: "ページのアドレス",
|
|
2244
2261
|
make: "カードを作成",
|
|
@@ -2373,6 +2390,11 @@ var e = {
|
|
|
2373
2390
|
hint: "行と列",
|
|
2374
2391
|
keywords: "grid columns rows 表 テーブル 行 列"
|
|
2375
2392
|
},
|
|
2393
|
+
button: {
|
|
2394
|
+
label: "ボタン",
|
|
2395
|
+
hint: "ブロックを挿入したりテンプレートからドキュメントを作るボタン",
|
|
2396
|
+
keywords: "ボタン テンプレート 挿入 button"
|
|
2397
|
+
},
|
|
2376
2398
|
diagram: {
|
|
2377
2399
|
label: "図",
|
|
2378
2400
|
hint: "Mermaid のテキストから描くフローチャート、シーケンス、状態、ガントの図",
|
|
@@ -1281,6 +1281,7 @@ var e = {
|
|
|
1281
1281
|
description: "팀마다 고유한 이슈, 워크플로, 멤버가 있습니다. 팀 키는 ENG-42처럼 각 이슈 ID의 앞부분이 됩니다."
|
|
1282
1282
|
},
|
|
1283
1283
|
docs: {
|
|
1284
|
+
spaceDefault: "이 스페이스의 새 문서에 사용",
|
|
1284
1285
|
duplicate: "복제",
|
|
1285
1286
|
copyOf: "{title} 사본",
|
|
1286
1287
|
subPages: "하위 페이지",
|
|
@@ -2239,6 +2240,22 @@ var e = {
|
|
|
2239
2240
|
copyLink: "제목 링크 복사",
|
|
2240
2241
|
delete: "삭제"
|
|
2241
2242
|
},
|
|
2243
|
+
docButton: {
|
|
2244
|
+
untitled: "버튼",
|
|
2245
|
+
edit: "버튼 변경",
|
|
2246
|
+
label: "레이블",
|
|
2247
|
+
labelPlaceholder: "이번 주 추가",
|
|
2248
|
+
does: "누르면",
|
|
2249
|
+
insert: "블록 넣기",
|
|
2250
|
+
makeDoc: "문서 만들기",
|
|
2251
|
+
blocks: "넣을 블록(Markdown)",
|
|
2252
|
+
blocksPlaceholder: "## '{{date}}' 주\n\n- [ ] ",
|
|
2253
|
+
placeholders: "'{{date}}', '{{time}}', '{{author}}'는 누를 때 채워집니다.",
|
|
2254
|
+
template: "템플릿",
|
|
2255
|
+
chooseTemplate: "템플릿 선택",
|
|
2256
|
+
parent: "상위",
|
|
2257
|
+
thisDoc: "이 문서"
|
|
2258
|
+
},
|
|
2242
2259
|
linkCard: {
|
|
2243
2260
|
address: "페이지 주소",
|
|
2244
2261
|
make: "카드 만들기",
|
|
@@ -2373,6 +2390,11 @@ var e = {
|
|
|
2373
2390
|
hint: "행과 열",
|
|
2374
2391
|
keywords: "표 테이블 그리드 열 행 grid columns rows"
|
|
2375
2392
|
},
|
|
2393
|
+
button: {
|
|
2394
|
+
label: "버튼",
|
|
2395
|
+
hint: "블록을 넣거나 템플릿으로 문서를 만드는 버튼",
|
|
2396
|
+
keywords: "버튼 템플릿 삽입 button"
|
|
2397
|
+
},
|
|
2376
2398
|
diagram: {
|
|
2377
2399
|
label: "다이어그램",
|
|
2378
2400
|
hint: "Mermaid 텍스트로 그리는 순서도, 시퀀스, 상태, 간트 다이어그램",
|
|
@@ -1281,6 +1281,7 @@ var e = {
|
|
|
1281
1281
|
description: "团队拥有自己的议题、工作流和成员。团队标识会作为每个议题 ID 的开头,例如 ENG-42。"
|
|
1282
1282
|
},
|
|
1283
1283
|
docs: {
|
|
1284
|
+
spaceDefault: "此空间的新文档从它开始",
|
|
1284
1285
|
duplicate: "复制一份",
|
|
1285
1286
|
copyOf: "{title} 的副本",
|
|
1286
1287
|
subPages: "子页面",
|
|
@@ -2239,6 +2240,22 @@ var e = {
|
|
|
2239
2240
|
copyLink: "复制标题链接",
|
|
2240
2241
|
delete: "删除"
|
|
2241
2242
|
},
|
|
2243
|
+
docButton: {
|
|
2244
|
+
untitled: "按钮",
|
|
2245
|
+
edit: "更改按钮",
|
|
2246
|
+
label: "标签",
|
|
2247
|
+
labelPlaceholder: "添加本周",
|
|
2248
|
+
does: "按下时",
|
|
2249
|
+
insert: "插入块",
|
|
2250
|
+
makeDoc: "创建文档",
|
|
2251
|
+
blocks: "要插入的块(Markdown)",
|
|
2252
|
+
blocksPlaceholder: "## '{{date}}' 当周\n\n- [ ] ",
|
|
2253
|
+
placeholders: "按下时会填入 '{{date}}'、'{{time}}' 和 '{{author}}'。",
|
|
2254
|
+
template: "模板",
|
|
2255
|
+
chooseTemplate: "选择模板",
|
|
2256
|
+
parent: "上级",
|
|
2257
|
+
thisDoc: "此文档"
|
|
2258
|
+
},
|
|
2242
2259
|
linkCard: {
|
|
2243
2260
|
address: "页面地址",
|
|
2244
2261
|
make: "创建卡片",
|
|
@@ -2373,6 +2390,11 @@ var e = {
|
|
|
2373
2390
|
hint: "行和列",
|
|
2374
2391
|
keywords: "表格 网格 列 行 grid columns rows"
|
|
2375
2392
|
},
|
|
2393
|
+
button: {
|
|
2394
|
+
label: "按钮",
|
|
2395
|
+
hint: "插入块或从模板创建文档的按钮",
|
|
2396
|
+
keywords: "按钮 模板 插入 button"
|
|
2397
|
+
},
|
|
2376
2398
|
diagram: {
|
|
2377
2399
|
label: "图表",
|
|
2378
2400
|
hint: "用 Mermaid 文本绘制的流程图、时序图、状态图或甘特图",
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
import { api as e, unwrap as t } from "../api/client.js";
|
|
2
|
+
import { docQuery as n, docTemplatesQuery as r, docsQuery as i } from "../api/queries.js";
|
|
3
|
+
import { EditIcon as a } from "./icons.js";
|
|
4
|
+
import { docKey as o, docRef as s, useTemplateValues as c } from "../lib/docs.js";
|
|
5
|
+
import { closingFence as l } from "./toggle.js";
|
|
6
|
+
import { Button as u, Combobox as d, IconButton as f, Input as p, Popover as m, SegmentedControl as h, Select as g, Textarea as _ } from "@parallelworks/ui";
|
|
7
|
+
import { useNavigate as v, useParams as y } from "@tanstack/react-router";
|
|
8
|
+
import { useState as b } from "react";
|
|
9
|
+
import { useTranslations as x } from "use-intl";
|
|
10
|
+
import { jsx as S, jsxs as C } from "react/jsx-runtime";
|
|
11
|
+
import { useQuery as w } from "@tanstack/react-query";
|
|
12
|
+
import { Node as T, NodeViewWrapper as E, ReactNodeViewRenderer as D, mergeAttributes as O } from "@tiptap/react";
|
|
13
|
+
// src/components/DocButton.tsx
|
|
14
|
+
var k = /^:::button[ \t]*([^\n]*)\n/, A = /\s+(template|parent)=([\w-]+)/g, j = T.create({
|
|
15
|
+
name: "docButton",
|
|
16
|
+
group: "block",
|
|
17
|
+
atom: !0,
|
|
18
|
+
draggable: !0,
|
|
19
|
+
addAttributes: () => ({
|
|
20
|
+
label: { default: "" },
|
|
21
|
+
action: { default: "insert" },
|
|
22
|
+
blocks: { default: "" },
|
|
23
|
+
template: { default: "" },
|
|
24
|
+
parent: { default: "" }
|
|
25
|
+
}),
|
|
26
|
+
parseHTML: () => [{ tag: "div[data-doc-button]" }],
|
|
27
|
+
renderHTML: ({ node: e, HTMLAttributes: t }) => [
|
|
28
|
+
"div",
|
|
29
|
+
O(t, { "data-doc-button": "" }),
|
|
30
|
+
String(e.attrs.label)
|
|
31
|
+
],
|
|
32
|
+
addNodeView: () => D(M, { stopEvent: ({ event: e }) => e.target instanceof Element && !!e.target.closest("[data-button-ui]") }),
|
|
33
|
+
markdownTokenName: "docButton",
|
|
34
|
+
markdownTokenizer: {
|
|
35
|
+
name: "docButton",
|
|
36
|
+
level: "block",
|
|
37
|
+
start: (e) => e.search(/^:::button/m),
|
|
38
|
+
tokenize: (e) => {
|
|
39
|
+
let t = k.exec(e);
|
|
40
|
+
if (!t) return;
|
|
41
|
+
let n = e.slice(t[0].length), r = l(n);
|
|
42
|
+
if (r) return {
|
|
43
|
+
type: "docButton",
|
|
44
|
+
raw: e.slice(0, t[0].length + r.index + r.length),
|
|
45
|
+
text: n.slice(0, r.index).trim(),
|
|
46
|
+
head: t[1] ?? ""
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
parseMarkdown: (e, t) => {
|
|
51
|
+
let n = String(e.head ?? ""), r = {};
|
|
52
|
+
for (let e of n.matchAll(A)) r[e[1] ?? ""] = e[2] ?? "";
|
|
53
|
+
return t.createNode("docButton", {
|
|
54
|
+
label: n.replace(A, "").trim(),
|
|
55
|
+
action: r.template ? "doc" : "insert",
|
|
56
|
+
blocks: e.text ?? "",
|
|
57
|
+
template: r.template ?? "",
|
|
58
|
+
parent: r.parent ?? ""
|
|
59
|
+
});
|
|
60
|
+
},
|
|
61
|
+
renderMarkdown: (e) => {
|
|
62
|
+
let t = e.attrs ?? {}, n = String(t.label ?? "").replace(/\n/g, " ");
|
|
63
|
+
if (t.action === "doc") {
|
|
64
|
+
let e = t.parent ? ` parent=${t.parent}` : "";
|
|
65
|
+
return `:::button ${n} template=${t.template ?? ""}${e}\n:::`;
|
|
66
|
+
}
|
|
67
|
+
return `:::button ${n}\n\n${String(t.blocks ?? "").trim()}\n\n:::`;
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
function M({ node: r, editor: i, getPos: l, updateAttributes: d }) {
|
|
71
|
+
let p = x("docButton"), h = v(), g = c(), { workspace: _ = "", doc: T = "" } = y({ strict: !1 }), { data: D } = w({
|
|
72
|
+
...n(_, T),
|
|
73
|
+
enabled: !!_ && !!T
|
|
74
|
+
}), [O, k] = b(!1), A = String(r.attrs.label ?? "") || p("untitled"), j = r.attrs.action, M = j === "doc" ? !!r.attrs.template : !!String(r.attrs.blocks ?? "").trim(), P = async () => {
|
|
75
|
+
if (j === "insert") {
|
|
76
|
+
let e = g(), t = Object.entries(e).reduce((e, [t, n]) => e.replaceAll(`{{${t}}}`, n), String(r.attrs.blocks ?? "")), n = l();
|
|
77
|
+
if (n === void 0) return;
|
|
78
|
+
i.chain().focus().insertContentAt(n + r.nodeSize, t, { contentType: "markdown" }).run();
|
|
79
|
+
} else {
|
|
80
|
+
k(!0);
|
|
81
|
+
try {
|
|
82
|
+
let n = String(r.attrs.parent ?? "") || D?.key, i = t(await e.POST("/api/v1/workspaces/{workspace}/docs", {
|
|
83
|
+
params: { path: { workspace: _ } },
|
|
84
|
+
body: {
|
|
85
|
+
template: String(r.attrs.template),
|
|
86
|
+
variables: g(),
|
|
87
|
+
...n && { parent: n }
|
|
88
|
+
}
|
|
89
|
+
}));
|
|
90
|
+
h({
|
|
91
|
+
to: "/$workspace/docs/$doc",
|
|
92
|
+
params: {
|
|
93
|
+
workspace: _,
|
|
94
|
+
doc: s(i)
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
} finally {
|
|
98
|
+
k(!1);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
return /* @__PURE__ */ S(E, {
|
|
103
|
+
className: "doc-button",
|
|
104
|
+
contentEditable: !1,
|
|
105
|
+
children: /* @__PURE__ */ C("div", {
|
|
106
|
+
"data-button-ui": !0,
|
|
107
|
+
className: "flex items-center gap-1",
|
|
108
|
+
children: [/* @__PURE__ */ S(u, {
|
|
109
|
+
size: "sm",
|
|
110
|
+
onClick: () => void P(),
|
|
111
|
+
disabled: !i.isEditable || !M,
|
|
112
|
+
loading: O,
|
|
113
|
+
children: A
|
|
114
|
+
}), i.isEditable && /* @__PURE__ */ S(m, {
|
|
115
|
+
trigger: /* @__PURE__ */ S(f, {
|
|
116
|
+
variant: "ghost",
|
|
117
|
+
size: "xs",
|
|
118
|
+
icon: /* @__PURE__ */ S(a, {}),
|
|
119
|
+
label: p("edit")
|
|
120
|
+
}),
|
|
121
|
+
align: "start",
|
|
122
|
+
className: "w-96",
|
|
123
|
+
initialFocus: "first-control",
|
|
124
|
+
"aria-label": p("edit"),
|
|
125
|
+
children: /* @__PURE__ */ S(N, {
|
|
126
|
+
workspace: _,
|
|
127
|
+
attrs: r.attrs,
|
|
128
|
+
thisDoc: D?.key ?? (T ? o(T) : ""),
|
|
129
|
+
onChange: d
|
|
130
|
+
})
|
|
131
|
+
})]
|
|
132
|
+
})
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
function N({ workspace: e, attrs: t, thisDoc: n, onChange: a }) {
|
|
136
|
+
let o = x("docButton"), { data: s = [] } = w(r(e)), { data: c = [] } = w(i(e)), l = t.action;
|
|
137
|
+
return /* @__PURE__ */ C("div", {
|
|
138
|
+
className: "space-y-3 text-sm",
|
|
139
|
+
children: [
|
|
140
|
+
/* @__PURE__ */ C("label", {
|
|
141
|
+
className: "block text-xs font-medium text-muted-foreground",
|
|
142
|
+
children: [o("label"), /* @__PURE__ */ S(p, {
|
|
143
|
+
value: String(t.label ?? ""),
|
|
144
|
+
onChange: (e) => a({ label: e.target.value }),
|
|
145
|
+
placeholder: o("labelPlaceholder"),
|
|
146
|
+
className: "mt-1"
|
|
147
|
+
})]
|
|
148
|
+
}),
|
|
149
|
+
/* @__PURE__ */ S(h, {
|
|
150
|
+
label: o("does"),
|
|
151
|
+
size: "sm",
|
|
152
|
+
value: l,
|
|
153
|
+
onValueChange: (e) => a({ action: e }),
|
|
154
|
+
options: [{
|
|
155
|
+
value: "insert",
|
|
156
|
+
label: o("insert")
|
|
157
|
+
}, {
|
|
158
|
+
value: "doc",
|
|
159
|
+
label: o("makeDoc")
|
|
160
|
+
}]
|
|
161
|
+
}),
|
|
162
|
+
l === "insert" ? /* @__PURE__ */ C("label", {
|
|
163
|
+
className: "block text-xs font-medium text-muted-foreground",
|
|
164
|
+
children: [
|
|
165
|
+
o("blocks"),
|
|
166
|
+
/* @__PURE__ */ S(_, {
|
|
167
|
+
value: String(t.blocks ?? ""),
|
|
168
|
+
onChange: (e) => a({ blocks: e.target.value }),
|
|
169
|
+
rows: 6,
|
|
170
|
+
placeholder: o("blocksPlaceholder"),
|
|
171
|
+
className: "mt-1 font-mono text-xs"
|
|
172
|
+
}),
|
|
173
|
+
/* @__PURE__ */ S("span", {
|
|
174
|
+
className: "mt-1 block font-normal",
|
|
175
|
+
children: o("placeholders")
|
|
176
|
+
})
|
|
177
|
+
]
|
|
178
|
+
}) : /* @__PURE__ */ C("div", {
|
|
179
|
+
className: "space-y-2",
|
|
180
|
+
children: [/* @__PURE__ */ C("div", {
|
|
181
|
+
className: "text-xs font-medium text-muted-foreground",
|
|
182
|
+
children: [o("template"), /* @__PURE__ */ S("div", {
|
|
183
|
+
className: "mt-1",
|
|
184
|
+
children: /* @__PURE__ */ S(g, {
|
|
185
|
+
value: String(t.template ?? ""),
|
|
186
|
+
items: [{
|
|
187
|
+
value: "",
|
|
188
|
+
label: o("chooseTemplate")
|
|
189
|
+
}, ...s.map((e) => ({
|
|
190
|
+
value: e.id,
|
|
191
|
+
label: e.title
|
|
192
|
+
}))],
|
|
193
|
+
onValueChange: (e) => a({ template: e }),
|
|
194
|
+
"aria-label": o("template"),
|
|
195
|
+
width: "content"
|
|
196
|
+
})
|
|
197
|
+
})]
|
|
198
|
+
}), /* @__PURE__ */ C("div", {
|
|
199
|
+
className: "text-xs font-medium text-muted-foreground",
|
|
200
|
+
children: [o("parent"), /* @__PURE__ */ S("div", {
|
|
201
|
+
className: "mt-1",
|
|
202
|
+
children: /* @__PURE__ */ S(d, {
|
|
203
|
+
items: [{
|
|
204
|
+
value: "",
|
|
205
|
+
label: o("thisDoc")
|
|
206
|
+
}, ...c.filter((e) => e.key !== n).map((e) => ({
|
|
207
|
+
value: e.key,
|
|
208
|
+
label: e.title
|
|
209
|
+
}))],
|
|
210
|
+
value: String(t.parent ?? ""),
|
|
211
|
+
onValueChange: (e) => e !== null && a({ parent: e }),
|
|
212
|
+
"aria-label": o("parent"),
|
|
213
|
+
placeholder: o("parent")
|
|
214
|
+
})
|
|
215
|
+
})]
|
|
216
|
+
})]
|
|
217
|
+
})
|
|
218
|
+
]
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
export { j as DocButton };
|
package/components/Editor.js
CHANGED
|
@@ -3,87 +3,88 @@ import { Callout as l } from "./callout.js";
|
|
|
3
3
|
import { DetailsContent as u, DetailsSummary as d, Toggle as f } from "./toggle.js";
|
|
4
4
|
import { Columns as p } from "./columns.js";
|
|
5
5
|
import { DateChip as m } from "./DateChip.js";
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
6
|
+
import { DocButton as h } from "./DocButton.js";
|
|
7
|
+
import { DocLinkPicker as g } from "./DocLinkPicker.js";
|
|
8
|
+
import { IssueListBlock as _ } from "./IssueListBlock.js";
|
|
9
|
+
import { LinkCard as ee } from "./LinkCard.js";
|
|
9
10
|
import { MentionPicker as v } from "./MentionPicker.js";
|
|
10
11
|
import { Diagrams as y, MathBlock as b, MathInline as x } from "./mathDiagrams.js";
|
|
11
12
|
import { SlashMenu as S } from "./SlashMenu.js";
|
|
12
|
-
import { SubPages as
|
|
13
|
-
import { MarkdownTable as
|
|
14
|
-
import { useEffect as
|
|
15
|
-
import { Fragment as
|
|
16
|
-
import { EditorContent as
|
|
17
|
-
import { CodeBlockLowlight as
|
|
18
|
-
import { TaskItem as
|
|
19
|
-
import { TableKit as
|
|
20
|
-
import { Placeholder as
|
|
21
|
-
import { Markdown as
|
|
22
|
-
import
|
|
23
|
-
import
|
|
24
|
-
import
|
|
25
|
-
import
|
|
26
|
-
import
|
|
27
|
-
import
|
|
28
|
-
import
|
|
29
|
-
import
|
|
30
|
-
import
|
|
31
|
-
import
|
|
32
|
-
import
|
|
33
|
-
import
|
|
34
|
-
import
|
|
35
|
-
import
|
|
36
|
-
import
|
|
37
|
-
import
|
|
38
|
-
import
|
|
39
|
-
import { createLowlight as
|
|
13
|
+
import { SubPages as te } from "./SubPages.js";
|
|
14
|
+
import { MarkdownTable as C } from "./table.js";
|
|
15
|
+
import { useEffect as w, useRef as T } from "react";
|
|
16
|
+
import { Fragment as E, jsx as D, jsxs as O } from "react/jsx-runtime";
|
|
17
|
+
import { EditorContent as k, useEditor as A } from "@tiptap/react";
|
|
18
|
+
import { CodeBlockLowlight as j } from "@tiptap/extension-code-block-lowlight";
|
|
19
|
+
import { TaskItem as M, TaskList as N } from "@tiptap/extension-list";
|
|
20
|
+
import { TableKit as P } from "@tiptap/extension-table";
|
|
21
|
+
import { Placeholder as F } from "@tiptap/extensions";
|
|
22
|
+
import { Markdown as I } from "@tiptap/markdown";
|
|
23
|
+
import L from "@tiptap/starter-kit";
|
|
24
|
+
import R from "highlight.js/lib/languages/bash";
|
|
25
|
+
import ne from "highlight.js/lib/languages/css";
|
|
26
|
+
import z from "highlight.js/lib/languages/diff";
|
|
27
|
+
import B from "highlight.js/lib/languages/dockerfile";
|
|
28
|
+
import V from "highlight.js/lib/languages/go";
|
|
29
|
+
import H from "highlight.js/lib/languages/ini";
|
|
30
|
+
import U from "highlight.js/lib/languages/javascript";
|
|
31
|
+
import W from "highlight.js/lib/languages/json";
|
|
32
|
+
import G from "highlight.js/lib/languages/markdown";
|
|
33
|
+
import K from "highlight.js/lib/languages/python";
|
|
34
|
+
import q from "highlight.js/lib/languages/rust";
|
|
35
|
+
import J from "highlight.js/lib/languages/shell";
|
|
36
|
+
import Y from "highlight.js/lib/languages/sql";
|
|
37
|
+
import X from "highlight.js/lib/languages/typescript";
|
|
38
|
+
import Z from "highlight.js/lib/languages/xml";
|
|
39
|
+
import re from "highlight.js/lib/languages/yaml";
|
|
40
|
+
import { createLowlight as ie } from "lowlight";
|
|
40
41
|
// src/components/Editor.tsx
|
|
41
|
-
var
|
|
42
|
-
bash:
|
|
43
|
-
css:
|
|
44
|
-
diff:
|
|
45
|
-
dockerfile:
|
|
46
|
-
go:
|
|
47
|
-
ini:
|
|
48
|
-
javascript:
|
|
49
|
-
json:
|
|
50
|
-
markdown:
|
|
51
|
-
python:
|
|
52
|
-
rust:
|
|
53
|
-
shell:
|
|
54
|
-
sql:
|
|
55
|
-
typescript:
|
|
56
|
-
xml:
|
|
57
|
-
yaml:
|
|
42
|
+
var ae = ie({
|
|
43
|
+
bash: R,
|
|
44
|
+
css: ne,
|
|
45
|
+
diff: z,
|
|
46
|
+
dockerfile: B,
|
|
47
|
+
go: V,
|
|
48
|
+
ini: H,
|
|
49
|
+
javascript: U,
|
|
50
|
+
json: W,
|
|
51
|
+
markdown: G,
|
|
52
|
+
python: K,
|
|
53
|
+
rust: q,
|
|
54
|
+
shell: J,
|
|
55
|
+
sql: Y,
|
|
56
|
+
typescript: X,
|
|
57
|
+
xml: Z,
|
|
58
|
+
yaml: re
|
|
58
59
|
});
|
|
59
|
-
function Q({ editable:
|
|
60
|
+
function Q({ editable: g = !0, placeholder: v = "", collaborative: S = !1 } = {}) {
|
|
60
61
|
return [
|
|
61
|
-
|
|
62
|
+
L.configure({
|
|
62
63
|
link: {
|
|
63
|
-
openOnClick: !
|
|
64
|
+
openOnClick: !g,
|
|
64
65
|
autolink: !0
|
|
65
66
|
},
|
|
66
67
|
codeBlock: !1,
|
|
67
68
|
blockquote: !1,
|
|
68
|
-
...
|
|
69
|
+
...g && !S ? {} : { trailingNode: !1 },
|
|
69
70
|
...S ? { undoRedo: !1 } : {}
|
|
70
71
|
}),
|
|
71
|
-
|
|
72
|
+
j.configure({ lowlight: ae }),
|
|
72
73
|
l,
|
|
73
|
-
|
|
74
|
-
|
|
74
|
+
N,
|
|
75
|
+
M.configure({ nested: !0 }),
|
|
75
76
|
f,
|
|
76
|
-
|
|
77
|
+
te,
|
|
77
78
|
d,
|
|
78
79
|
u,
|
|
79
80
|
p,
|
|
80
|
-
|
|
81
|
-
|
|
81
|
+
P.configure({ table: !1 }),
|
|
82
|
+
C.configure({
|
|
82
83
|
resizable: !1,
|
|
83
84
|
allowTableNodeSelection: !1
|
|
84
85
|
}),
|
|
85
|
-
|
|
86
|
-
|
|
86
|
+
F.configure({ placeholder: v }),
|
|
87
|
+
I,
|
|
87
88
|
a,
|
|
88
89
|
r,
|
|
89
90
|
n,
|
|
@@ -93,11 +94,12 @@ function Q({ editable: h = !0, placeholder: v = "", collaborative: S = !1 } = {}
|
|
|
93
94
|
s,
|
|
94
95
|
c,
|
|
95
96
|
i,
|
|
96
|
-
|
|
97
|
+
h,
|
|
98
|
+
ee,
|
|
97
99
|
x,
|
|
98
100
|
b,
|
|
99
101
|
y,
|
|
100
|
-
|
|
102
|
+
_,
|
|
101
103
|
m
|
|
102
104
|
];
|
|
103
105
|
}
|
|
@@ -116,8 +118,8 @@ function $(e) {
|
|
|
116
118
|
}
|
|
117
119
|
};
|
|
118
120
|
}
|
|
119
|
-
function
|
|
120
|
-
let f =
|
|
121
|
+
function oe({ value: e, onChange: t, onSubmit: n, onBlur: r, onFocus: i, placeholder: a, editable: o = !0, autofocus: s = !1, className: c = "", label: l, onFiles: u, onEditor: d }) {
|
|
122
|
+
let f = T({
|
|
121
123
|
onChange: t,
|
|
122
124
|
onSubmit: n,
|
|
123
125
|
onBlur: r,
|
|
@@ -129,9 +131,9 @@ function ae({ value: e, onChange: t, onSubmit: n, onBlur: r, onFocus: i, placeho
|
|
|
129
131
|
onBlur: r,
|
|
130
132
|
onFocus: i
|
|
131
133
|
};
|
|
132
|
-
let p =
|
|
134
|
+
let p = T(u);
|
|
133
135
|
p.current = u;
|
|
134
|
-
let m =
|
|
136
|
+
let m = A({
|
|
135
137
|
extensions: Q({
|
|
136
138
|
editable: o,
|
|
137
139
|
placeholder: a ?? ""
|
|
@@ -158,23 +160,23 @@ function ae({ value: e, onChange: t, onSubmit: n, onBlur: r, onFocus: i, placeho
|
|
|
158
160
|
onBlur: ({ editor: e }) => f.current.onBlur?.(e.getMarkdown()),
|
|
159
161
|
onFocus: () => f.current.onFocus?.()
|
|
160
162
|
});
|
|
161
|
-
|
|
163
|
+
w(() => {
|
|
162
164
|
m && !m.isFocused && m.getMarkdown() !== e && m.commands.setContent(e, {
|
|
163
165
|
contentType: "markdown",
|
|
164
166
|
emitUpdate: !1
|
|
165
167
|
});
|
|
166
|
-
}, [m, e]),
|
|
168
|
+
}, [m, e]), w(() => {
|
|
167
169
|
m?.setEditable(o);
|
|
168
170
|
}, [m, o]);
|
|
169
|
-
let
|
|
170
|
-
return
|
|
171
|
-
/* @__PURE__ */
|
|
172
|
-
o && /* @__PURE__ */
|
|
173
|
-
o && /* @__PURE__ */
|
|
171
|
+
let h = T(d);
|
|
172
|
+
return h.current = d, w(() => (h.current?.(m), () => h.current?.(null)), [m]), /* @__PURE__ */ O(E, { children: [
|
|
173
|
+
/* @__PURE__ */ D(k, { editor: m }),
|
|
174
|
+
o && /* @__PURE__ */ D(g, { editor: m }),
|
|
175
|
+
o && /* @__PURE__ */ D(S, {
|
|
174
176
|
editor: m,
|
|
175
177
|
onFiles: p
|
|
176
178
|
}),
|
|
177
|
-
o && /* @__PURE__ */
|
|
179
|
+
o && /* @__PURE__ */ D(v, { editor: m })
|
|
178
180
|
] });
|
|
179
181
|
}
|
|
180
|
-
export {
|
|
182
|
+
export { oe as Editor, Q as contentExtensions, $ as fileHandlers };
|
package/components/SlashMenu.js
CHANGED
|
@@ -58,6 +58,7 @@ var w = {
|
|
|
58
58
|
file: "↥",
|
|
59
59
|
table: "▦",
|
|
60
60
|
docLink: "[[",
|
|
61
|
+
button: "▭",
|
|
61
62
|
issueList: "☰",
|
|
62
63
|
date: "@",
|
|
63
64
|
page: "+",
|
|
@@ -103,6 +104,7 @@ var w = {
|
|
|
103
104
|
withHeaderRow: !0
|
|
104
105
|
}),
|
|
105
106
|
docLink: (e) => e.insertContent("[["),
|
|
107
|
+
button: (e) => e.insertContent({ type: "docButton" }),
|
|
106
108
|
issueList: (e) => e.insertContent({ type: "issueList" }),
|
|
107
109
|
date: (e) => e.insertContent([{
|
|
108
110
|
type: "dateChip",
|
package/lib/docs.js
CHANGED
|
@@ -1,99 +1,126 @@
|
|
|
1
1
|
import { appURL as e, basePath as t } from "./base.js";
|
|
2
2
|
import { api as n, unwrap as r } from "../api/client.js";
|
|
3
3
|
import { useNavigate as i } from "./router.js";
|
|
4
|
-
import {
|
|
5
|
-
import { useFavorites as
|
|
6
|
-
import { copyItem as
|
|
7
|
-
import { openShare as
|
|
8
|
-
import { menuDivider as
|
|
9
|
-
import { useCallback as
|
|
10
|
-
import { useTranslations as
|
|
11
|
-
import { useMutation as
|
|
4
|
+
import { docTemplatesQuery as a, docsQuery as o, meQuery as s, teamsQuery as c } from "../api/queries.js";
|
|
5
|
+
import { useFavorites as l } from "./favorites.js";
|
|
6
|
+
import { copyItem as u, useLinkItems as d } from "./menus.js";
|
|
7
|
+
import { openShare as f } from "./share.js";
|
|
8
|
+
import { menuDivider as p } from "@parallelworks/ui";
|
|
9
|
+
import { useCallback as m } from "react";
|
|
10
|
+
import { useFormatter as h, useTranslations as g } from "use-intl";
|
|
11
|
+
import { useMutation as _, useQuery as v, useQueryClient as y } from "@tanstack/react-query";
|
|
12
12
|
// src/lib/docs.tsx
|
|
13
|
-
function
|
|
13
|
+
function b(e) {
|
|
14
14
|
return e.ref || (e.slug ? `${e.slug}-${e.key}` : e.key);
|
|
15
15
|
}
|
|
16
|
-
function
|
|
16
|
+
function x(e) {
|
|
17
17
|
let t = (e.split("-").pop() ?? e).toLowerCase();
|
|
18
18
|
return /^[a-z2-7]{10}$/.test(t) ? t : e.toLowerCase();
|
|
19
19
|
}
|
|
20
|
-
function
|
|
21
|
-
|
|
20
|
+
function S() {
|
|
21
|
+
let e = h(), { data: t } = v(s);
|
|
22
|
+
return m(() => {
|
|
23
|
+
let n = /* @__PURE__ */ new Date();
|
|
24
|
+
return {
|
|
25
|
+
date: e.dateTime(n, { dateStyle: "long" }),
|
|
26
|
+
time: e.dateTime(n, { timeStyle: "short" }),
|
|
27
|
+
author: t?.user.name ?? ""
|
|
28
|
+
};
|
|
29
|
+
}, [e, t]);
|
|
22
30
|
}
|
|
23
|
-
function
|
|
24
|
-
|
|
31
|
+
function C(e, t) {
|
|
32
|
+
return `/${e}/docs/${b(t)}`;
|
|
33
|
+
}
|
|
34
|
+
function w(e) {
|
|
35
|
+
let t = y(), o = i(), s = g("docs"), l = () => t.invalidateQueries({ queryKey: [
|
|
25
36
|
"workspace",
|
|
26
37
|
e,
|
|
27
38
|
"docs"
|
|
28
|
-
] }),
|
|
39
|
+
] }), u = (t) => ({ path: {
|
|
29
40
|
workspace: e,
|
|
30
41
|
doc: t
|
|
31
|
-
} })
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
42
|
+
} }), d = S(), f = _({
|
|
43
|
+
mutationFn: async ({ team: t, parent: i, template: a }) => {
|
|
44
|
+
let o = a ?? await C(t, i);
|
|
45
|
+
return r(await n.POST("/api/v1/workspaces/{workspace}/docs", {
|
|
35
46
|
params: { path: { workspace: e } },
|
|
36
47
|
body: {
|
|
37
|
-
...
|
|
48
|
+
...o ? {
|
|
49
|
+
template: o,
|
|
50
|
+
variables: d()
|
|
51
|
+
} : { title: s("untitled") },
|
|
38
52
|
...t && { team: t },
|
|
39
53
|
...i && { parent: i.key }
|
|
40
54
|
}
|
|
41
|
-
}))
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
}
|
|
55
|
+
}));
|
|
56
|
+
},
|
|
57
|
+
onSuccess: (t) => {
|
|
58
|
+
l(), o({
|
|
59
|
+
to: "/$workspace/docs/$doc",
|
|
60
|
+
params: {
|
|
61
|
+
workspace: e,
|
|
62
|
+
doc: b(t)
|
|
63
|
+
},
|
|
64
|
+
search: { rename: !0 }
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
}), p = _({
|
|
68
|
+
mutationFn: async ({ doc: e, title: t }) => r(await n.PATCH("/api/v1/workspaces/{workspace}/docs/{doc}", {
|
|
69
|
+
params: u(e.key),
|
|
70
|
+
body: { title: t }
|
|
71
|
+
})),
|
|
72
|
+
onSettled: l
|
|
73
|
+
}), m = _({
|
|
74
|
+
mutationFn: async ({ doc: e, area: t }) => r(await n.PATCH("/api/v1/workspaces/{workspace}/docs/{doc}", {
|
|
75
|
+
params: u(e.key),
|
|
76
|
+
body: { area: t }
|
|
77
|
+
})),
|
|
78
|
+
onSettled: l
|
|
79
|
+
}), h = _({
|
|
80
|
+
mutationFn: async ({ doc: e, space: t, parent: i, after: a, before: o }) => r(await n.POST("/api/v1/workspaces/{workspace}/docs/{doc}/move", {
|
|
81
|
+
params: u(e.key),
|
|
82
|
+
body: {
|
|
83
|
+
...t && { space: t },
|
|
84
|
+
...i && { parent: i.key },
|
|
85
|
+
...a && { after: a.key },
|
|
86
|
+
...o && { before: o.key }
|
|
51
87
|
}
|
|
52
|
-
}),
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
}),
|
|
79
|
-
archive: m({
|
|
80
|
-
mutationFn: async (e) => r(await n.POST("/api/v1/workspaces/{workspace}/docs/{doc}/archive", { params: c(e.key) })),
|
|
81
|
-
onSettled: s
|
|
82
|
-
}),
|
|
83
|
-
restore: m({
|
|
84
|
-
mutationFn: async (e) => r(await n.POST("/api/v1/workspaces/{workspace}/docs/{doc}/restore", { params: c(e.key) })),
|
|
85
|
-
onSettled: s
|
|
86
|
-
}),
|
|
87
|
-
setTemplate: m({
|
|
88
|
+
})),
|
|
89
|
+
onSettled: l
|
|
90
|
+
}), v = _({
|
|
91
|
+
mutationFn: async (e) => r(await n.POST("/api/v1/workspaces/{workspace}/docs/{doc}/archive", { params: u(e.key) })),
|
|
92
|
+
onSettled: l
|
|
93
|
+
}), x = _({
|
|
94
|
+
mutationFn: async (e) => r(await n.POST("/api/v1/workspaces/{workspace}/docs/{doc}/restore", { params: u(e.key) })),
|
|
95
|
+
onSettled: l
|
|
96
|
+
}), C = async (n, r) => {
|
|
97
|
+
let [i, o] = await Promise.all([t.fetchQuery(a(e)), t.fetchQuery(c(e))]), s = r ? r.teamId ?? "" : o.find((e) => e.key === n)?.id ?? "";
|
|
98
|
+
return i.find((e) => e.spaceDefault && (e.teamId ?? "") === s)?.id;
|
|
99
|
+
}, w = _({
|
|
100
|
+
mutationFn: async ({ doc: e, spaceDefault: t }) => r(await n.PATCH("/api/v1/workspaces/{workspace}/docs/{doc}", {
|
|
101
|
+
params: u(e.key),
|
|
102
|
+
body: { spaceDefault: t }
|
|
103
|
+
})),
|
|
104
|
+
onSettled: l
|
|
105
|
+
});
|
|
106
|
+
return {
|
|
107
|
+
create: f,
|
|
108
|
+
rename: p,
|
|
109
|
+
fileUnder: m,
|
|
110
|
+
move: h,
|
|
111
|
+
archive: v,
|
|
112
|
+
restore: x,
|
|
113
|
+
setTemplate: _({
|
|
88
114
|
mutationFn: async ({ doc: e, template: t }) => r(await n.PATCH("/api/v1/workspaces/{workspace}/docs/{doc}", {
|
|
89
|
-
params:
|
|
115
|
+
params: u(e.key),
|
|
90
116
|
body: { template: t }
|
|
91
117
|
})),
|
|
92
|
-
onSettled:
|
|
118
|
+
onSettled: l
|
|
93
119
|
}),
|
|
94
|
-
|
|
120
|
+
setSpaceDefault: w,
|
|
121
|
+
setLook: _({
|
|
95
122
|
mutationFn: async ({ doc: e, ...t }) => r(await n.PATCH("/api/v1/workspaces/{workspace}/docs/{doc}", {
|
|
96
|
-
params:
|
|
123
|
+
params: u(e.key),
|
|
97
124
|
body: t
|
|
98
125
|
})),
|
|
99
126
|
onMutate: ({ doc: n, ...r }) => {
|
|
@@ -106,30 +133,30 @@ function b(e) {
|
|
|
106
133
|
...r
|
|
107
134
|
} : e);
|
|
108
135
|
},
|
|
109
|
-
onSettled:
|
|
136
|
+
onSettled: l
|
|
110
137
|
}),
|
|
111
|
-
duplicate:
|
|
138
|
+
duplicate: _({
|
|
112
139
|
mutationFn: async ({ doc: t, team: i }) => {
|
|
113
|
-
let a = r(await n.GET("/api/v1/workspaces/{workspace}/docs/{doc}", { params:
|
|
140
|
+
let a = r(await n.GET("/api/v1/workspaces/{workspace}/docs/{doc}", { params: u(t.key) })), o = a.ancestors?.at(-1)?.key, c = r(await n.POST("/api/v1/workspaces/{workspace}/docs", {
|
|
114
141
|
params: { path: { workspace: e } },
|
|
115
142
|
body: {
|
|
116
|
-
title:
|
|
143
|
+
title: s("copyOf", { title: a.title }),
|
|
117
144
|
body: a.body ?? "",
|
|
118
145
|
...i && { team: i },
|
|
119
|
-
...
|
|
146
|
+
...o && { parent: o }
|
|
120
147
|
}
|
|
121
148
|
}));
|
|
122
149
|
return a.icon ? r(await n.PATCH("/api/v1/workspaces/{workspace}/docs/{doc}", {
|
|
123
|
-
params: c
|
|
150
|
+
params: u(c.key),
|
|
124
151
|
body: { icon: a.icon }
|
|
125
|
-
})) :
|
|
152
|
+
})) : c;
|
|
126
153
|
},
|
|
127
154
|
onSuccess: (t) => {
|
|
128
|
-
|
|
155
|
+
l(), o({
|
|
129
156
|
to: "/$workspace/docs/$doc",
|
|
130
157
|
params: {
|
|
131
158
|
workspace: e,
|
|
132
|
-
doc:
|
|
159
|
+
doc: b(t)
|
|
133
160
|
},
|
|
134
161
|
search: { rename: !0 }
|
|
135
162
|
});
|
|
@@ -137,73 +164,73 @@ function b(e) {
|
|
|
137
164
|
})
|
|
138
165
|
};
|
|
139
166
|
}
|
|
140
|
-
function
|
|
141
|
-
let t = i(), n =
|
|
142
|
-
return
|
|
143
|
-
let
|
|
167
|
+
function T(e) {
|
|
168
|
+
let t = i(), n = g("docs"), r = g("common"), a = g("favorites"), s = d(), h = l(e), _ = w(e), { data: y = [] } = v(c(e)), { data: x = [] } = v(o(e, { top: !0 }));
|
|
169
|
+
return m((i, { onRename: o } = {}) => {
|
|
170
|
+
let c = y.find((e) => e.id === i.teamId), l = c?.key ?? "workspace", d = {
|
|
144
171
|
label: r("open"),
|
|
145
172
|
onClick: () => t({
|
|
146
173
|
to: "/$workspace/docs/$doc",
|
|
147
174
|
params: {
|
|
148
175
|
workspace: e,
|
|
149
|
-
doc:
|
|
176
|
+
doc: b(i)
|
|
150
177
|
}
|
|
151
178
|
})
|
|
152
|
-
},
|
|
179
|
+
}, m = [...s(C(e, i)), u(n("copyKey"), i.key)];
|
|
153
180
|
if (i.archivedAt) return [
|
|
154
|
-
|
|
181
|
+
d,
|
|
155
182
|
{
|
|
156
183
|
label: n("restore"),
|
|
157
|
-
onClick: () =>
|
|
184
|
+
onClick: () => _.restore.mutate(i)
|
|
158
185
|
},
|
|
159
|
-
|
|
160
|
-
...
|
|
186
|
+
p,
|
|
187
|
+
...m
|
|
161
188
|
];
|
|
162
|
-
let
|
|
189
|
+
let g = x.filter((e) => e.id !== i.id), v = [{
|
|
163
190
|
key: "workspace",
|
|
164
191
|
name: n("workspaceSpace")
|
|
165
|
-
}, ...
|
|
192
|
+
}, ...y.filter((e) => !e.archivedAt).map((e) => ({
|
|
166
193
|
key: e.key,
|
|
167
194
|
name: e.name
|
|
168
195
|
}))];
|
|
169
196
|
return [
|
|
170
|
-
|
|
197
|
+
d,
|
|
171
198
|
{
|
|
172
199
|
label: n("newInside"),
|
|
173
|
-
onClick: () =>
|
|
200
|
+
onClick: () => _.create.mutate({ parent: i })
|
|
174
201
|
},
|
|
175
202
|
{
|
|
176
203
|
label: n("duplicate"),
|
|
177
|
-
onClick: () =>
|
|
204
|
+
onClick: () => _.duplicate.mutate({
|
|
178
205
|
doc: i,
|
|
179
|
-
team:
|
|
206
|
+
team: c?.key
|
|
180
207
|
})
|
|
181
208
|
},
|
|
182
|
-
...
|
|
209
|
+
...o ? [{
|
|
183
210
|
label: n("rename"),
|
|
184
|
-
onClick:
|
|
211
|
+
onClick: o
|
|
185
212
|
}] : [],
|
|
186
213
|
{
|
|
187
214
|
label: n("moveTo"),
|
|
188
215
|
items: [
|
|
189
|
-
...
|
|
190
|
-
let t = !i.parentId && e.key ===
|
|
216
|
+
...v.map((e) => {
|
|
217
|
+
let t = !i.parentId && e.key === l;
|
|
191
218
|
return {
|
|
192
219
|
label: n("topOf", { space: e.name }),
|
|
193
220
|
checked: t,
|
|
194
221
|
disabled: t,
|
|
195
|
-
onClick: () =>
|
|
222
|
+
onClick: () => _.move.mutate({
|
|
196
223
|
doc: i,
|
|
197
224
|
space: e.key
|
|
198
225
|
})
|
|
199
226
|
};
|
|
200
227
|
}),
|
|
201
|
-
...
|
|
202
|
-
...
|
|
228
|
+
...g.length > 0 ? [p] : [],
|
|
229
|
+
...g.map((e) => ({
|
|
203
230
|
label: e.title,
|
|
204
231
|
checked: e.id === i.parentId,
|
|
205
232
|
disabled: e.id === i.parentId,
|
|
206
|
-
onClick: () =>
|
|
233
|
+
onClick: () => _.move.mutate({
|
|
207
234
|
doc: i,
|
|
208
235
|
parent: e
|
|
209
236
|
})
|
|
@@ -212,64 +239,72 @@ function x(e) {
|
|
|
212
239
|
},
|
|
213
240
|
{
|
|
214
241
|
label: n("share"),
|
|
215
|
-
onClick: () =>
|
|
242
|
+
onClick: () => f({
|
|
216
243
|
doc: i.key,
|
|
217
244
|
title: i.title
|
|
218
245
|
})
|
|
219
246
|
},
|
|
220
247
|
{
|
|
221
|
-
label:
|
|
222
|
-
onClick: () =>
|
|
248
|
+
label: h.find("doc", i.id) ? a("remove") : a("add"),
|
|
249
|
+
onClick: () => h.toggle("doc", i.id)
|
|
223
250
|
},
|
|
224
251
|
{
|
|
225
252
|
label: n("look.fullWidth"),
|
|
226
253
|
checked: !!i.fullWidth,
|
|
227
|
-
onClick: () =>
|
|
254
|
+
onClick: () => _.setLook.mutate({
|
|
228
255
|
doc: i,
|
|
229
256
|
fullWidth: !i.fullWidth
|
|
230
257
|
})
|
|
231
258
|
},
|
|
232
259
|
{
|
|
233
260
|
label: i.template ? n("stopTemplate") : n("useAsTemplate"),
|
|
234
|
-
onClick: () =>
|
|
261
|
+
onClick: () => _.setTemplate.mutate({
|
|
235
262
|
doc: i,
|
|
236
263
|
template: !i.template
|
|
237
264
|
})
|
|
238
265
|
},
|
|
266
|
+
...i.template ? [{
|
|
267
|
+
label: n("spaceDefault"),
|
|
268
|
+
checked: !!i.spaceDefault,
|
|
269
|
+
onClick: () => _.setSpaceDefault.mutate({
|
|
270
|
+
doc: i,
|
|
271
|
+
spaceDefault: !i.spaceDefault
|
|
272
|
+
})
|
|
273
|
+
}] : [],
|
|
239
274
|
{
|
|
240
275
|
label: n("exportMarkdown"),
|
|
241
|
-
onClick: () =>
|
|
276
|
+
onClick: () => D(e, { doc: i.key })
|
|
242
277
|
},
|
|
243
|
-
|
|
244
|
-
...
|
|
245
|
-
|
|
278
|
+
p,
|
|
279
|
+
...m,
|
|
280
|
+
p,
|
|
246
281
|
{
|
|
247
282
|
label: n("archive"),
|
|
248
283
|
destructive: !0,
|
|
249
|
-
onClick: () =>
|
|
284
|
+
onClick: () => _.archive.mutate(i)
|
|
250
285
|
}
|
|
251
286
|
];
|
|
252
287
|
}, [
|
|
253
|
-
|
|
254
|
-
|
|
288
|
+
y,
|
|
289
|
+
x,
|
|
255
290
|
e,
|
|
256
291
|
t,
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
292
|
+
s,
|
|
293
|
+
h,
|
|
294
|
+
_,
|
|
260
295
|
n,
|
|
261
296
|
r,
|
|
262
|
-
|
|
297
|
+
a
|
|
263
298
|
]);
|
|
264
299
|
}
|
|
265
|
-
function
|
|
266
|
-
return e(
|
|
300
|
+
function E(t, n) {
|
|
301
|
+
return e(C(t, n));
|
|
267
302
|
}
|
|
268
|
-
function
|
|
303
|
+
function D(e, n) {
|
|
269
304
|
let r = new URLSearchParams({
|
|
270
305
|
...n,
|
|
271
306
|
...n.space && { knowledge: "true" }
|
|
272
307
|
}), i = document.createElement("a");
|
|
273
308
|
i.href = `${t}/api/v1/workspaces/${encodeURIComponent(e)}/docs/export?${r}`, i.download = "", i.click();
|
|
274
309
|
}
|
|
275
|
-
export {
|
|
310
|
+
export { x as docKey, C as docPath, b as docRef, E as docURL, D as downloadMarkdown, w as useDocActions, T as useDocMenu, S as useTemplateValues };
|
package/package.json
CHANGED
package/styles.css
CHANGED
|
@@ -482,6 +482,10 @@ body[data-tandem] > :not(:has(.tandem)) {
|
|
|
482
482
|
display: none;
|
|
483
483
|
}
|
|
484
484
|
}
|
|
485
|
+
/* A button that inserts blocks or makes a doc (DocButton). */
|
|
486
|
+
.prose-issue .doc-button {
|
|
487
|
+
margin-block: 0.5em;
|
|
488
|
+
}
|
|
485
489
|
/* A live list of issues in a doc (IssueListBlock), out of the prose's own styles. */
|
|
486
490
|
.prose-issue .issue-list-block {
|
|
487
491
|
margin-block: 0.75em;
|