@dxos/plugin-github 0.6.8-main.046e6cf

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 (106) hide show
  1. package/LICENSE +8 -0
  2. package/README.md +15 -0
  3. package/dist/lib/browser/chunk-NJP5BGD2.mjs +24 -0
  4. package/dist/lib/browser/chunk-NJP5BGD2.mjs.map +7 -0
  5. package/dist/lib/browser/index.css +7 -0
  6. package/dist/lib/browser/index.css.map +7 -0
  7. package/dist/lib/browser/index.mjs +1531 -0
  8. package/dist/lib/browser/index.mjs.map +7 -0
  9. package/dist/lib/browser/meta.json +1 -0
  10. package/dist/lib/browser/meta.mjs +11 -0
  11. package/dist/lib/browser/meta.mjs.map +7 -0
  12. package/dist/types/src/GithubPlugin.d.ts +4 -0
  13. package/dist/types/src/GithubPlugin.d.ts.map +1 -0
  14. package/dist/types/src/components/EmbeddedMain/EmbeddedMain.d.ts +4 -0
  15. package/dist/types/src/components/EmbeddedMain/EmbeddedMain.d.ts.map +1 -0
  16. package/dist/types/src/components/EmbeddedMain/GfmPreview.d.ts +9 -0
  17. package/dist/types/src/components/EmbeddedMain/GfmPreview.d.ts.map +1 -0
  18. package/dist/types/src/components/EmbeddedMain/index.d.ts +2 -0
  19. package/dist/types/src/components/EmbeddedMain/index.d.ts.map +1 -0
  20. package/dist/types/src/components/ExportDialog.d.ts +8 -0
  21. package/dist/types/src/components/ExportDialog.d.ts.map +1 -0
  22. package/dist/types/src/components/GithubApiProviders/GitHubSettings.d.ts +3 -0
  23. package/dist/types/src/components/GithubApiProviders/GitHubSettings.d.ts.map +1 -0
  24. package/dist/types/src/components/GithubApiProviders/OctokitProvider.d.ts +15 -0
  25. package/dist/types/src/components/GithubApiProviders/OctokitProvider.d.ts.map +1 -0
  26. package/dist/types/src/components/GithubApiProviders/index.d.ts +3 -0
  27. package/dist/types/src/components/GithubApiProviders/index.d.ts.map +1 -0
  28. package/dist/types/src/components/GithubEchoResolverProviders/DocumentTreeItem.d.ts +6 -0
  29. package/dist/types/src/components/GithubEchoResolverProviders/DocumentTreeItem.d.ts.map +1 -0
  30. package/dist/types/src/components/GithubEchoResolverProviders/ResolverContext.d.ts +7 -0
  31. package/dist/types/src/components/GithubEchoResolverProviders/ResolverContext.d.ts.map +1 -0
  32. package/dist/types/src/components/GithubEchoResolverProviders/ResolverDialog.d.ts +6 -0
  33. package/dist/types/src/components/GithubEchoResolverProviders/ResolverDialog.d.ts.map +1 -0
  34. package/dist/types/src/components/GithubEchoResolverProviders/ResolverProps.d.ts +16 -0
  35. package/dist/types/src/components/GithubEchoResolverProviders/ResolverProps.d.ts.map +1 -0
  36. package/dist/types/src/components/GithubEchoResolverProviders/ResolverTree.d.ts +3 -0
  37. package/dist/types/src/components/GithubEchoResolverProviders/ResolverTree.d.ts.map +1 -0
  38. package/dist/types/src/components/GithubEchoResolverProviders/SpacePickerTreeItem.d.ts +11 -0
  39. package/dist/types/src/components/GithubEchoResolverProviders/SpacePickerTreeItem.d.ts.map +1 -0
  40. package/dist/types/src/components/GithubEchoResolverProviders/index.d.ts +3 -0
  41. package/dist/types/src/components/GithubEchoResolverProviders/index.d.ts.map +1 -0
  42. package/dist/types/src/components/GithubEchoResolverProviders/spaceResolvers.d.ts +6 -0
  43. package/dist/types/src/components/GithubEchoResolverProviders/spaceResolvers.d.ts.map +1 -0
  44. package/dist/types/src/components/ImportDialog.d.ts +7 -0
  45. package/dist/types/src/components/ImportDialog.d.ts.map +1 -0
  46. package/dist/types/src/components/Issue.d.ts +5 -0
  47. package/dist/types/src/components/Issue.d.ts.map +1 -0
  48. package/dist/types/src/components/Loading/Loading.d.ts +15 -0
  49. package/dist/types/src/components/Loading/Loading.d.ts.map +1 -0
  50. package/dist/types/src/components/Loading/Loading.stories.d.ts +52 -0
  51. package/dist/types/src/components/Loading/Loading.stories.d.ts.map +1 -0
  52. package/dist/types/src/components/Loading/index.d.ts +2 -0
  53. package/dist/types/src/components/Loading/index.d.ts.map +1 -0
  54. package/dist/types/src/components/MarkdownActions.d.ts +7 -0
  55. package/dist/types/src/components/MarkdownActions.d.ts.map +1 -0
  56. package/dist/types/src/components/UrlDialog.d.ts +6 -0
  57. package/dist/types/src/components/UrlDialog.d.ts.map +1 -0
  58. package/dist/types/src/components/index.d.ts +9 -0
  59. package/dist/types/src/components/index.d.ts.map +1 -0
  60. package/dist/types/src/hooks/index.d.ts +3 -0
  61. package/dist/types/src/hooks/index.d.ts.map +1 -0
  62. package/dist/types/src/hooks/useDocGhId.d.ts +6 -0
  63. package/dist/types/src/hooks/useDocGhId.d.ts.map +1 -0
  64. package/dist/types/src/hooks/useGhIdFromUrl.d.ts +2 -0
  65. package/dist/types/src/hooks/useGhIdFromUrl.d.ts.map +1 -0
  66. package/dist/types/src/index.d.ts +4 -0
  67. package/dist/types/src/index.d.ts.map +1 -0
  68. package/dist/types/src/meta.d.ts +16 -0
  69. package/dist/types/src/meta.d.ts.map +1 -0
  70. package/dist/types/src/translations.d.ts +56 -0
  71. package/dist/types/src/translations.d.ts.map +1 -0
  72. package/dist/types/src/types.d.ts +30 -0
  73. package/dist/types/src/types.d.ts.map +1 -0
  74. package/package.json +76 -0
  75. package/src/GithubPlugin.tsx +129 -0
  76. package/src/components/EmbeddedMain/EmbeddedMain.tsx +296 -0
  77. package/src/components/EmbeddedMain/GfmPreview.tsx +110 -0
  78. package/src/components/EmbeddedMain/embedded.css +3 -0
  79. package/src/components/EmbeddedMain/index.ts +5 -0
  80. package/src/components/ExportDialog.tsx +157 -0
  81. package/src/components/GithubApiProviders/GitHubSettings.tsx +72 -0
  82. package/src/components/GithubApiProviders/OctokitProvider.tsx +60 -0
  83. package/src/components/GithubApiProviders/index.ts +6 -0
  84. package/src/components/GithubEchoResolverProviders/DocumentTreeItem.tsx +26 -0
  85. package/src/components/GithubEchoResolverProviders/ResolverContext.tsx +140 -0
  86. package/src/components/GithubEchoResolverProviders/ResolverDialog.tsx +34 -0
  87. package/src/components/GithubEchoResolverProviders/ResolverProps.ts +23 -0
  88. package/src/components/GithubEchoResolverProviders/ResolverTree.tsx +86 -0
  89. package/src/components/GithubEchoResolverProviders/SpacePickerTreeItem.tsx +105 -0
  90. package/src/components/GithubEchoResolverProviders/index.ts +6 -0
  91. package/src/components/GithubEchoResolverProviders/spaceResolvers.ts +86 -0
  92. package/src/components/ImportDialog.tsx +72 -0
  93. package/src/components/Issue.tsx +62 -0
  94. package/src/components/Loading/Loading.stories.tsx +28 -0
  95. package/src/components/Loading/Loading.tsx +70 -0
  96. package/src/components/Loading/index.ts +5 -0
  97. package/src/components/MarkdownActions.tsx +136 -0
  98. package/src/components/UrlDialog.tsx +52 -0
  99. package/src/components/index.ts +12 -0
  100. package/src/hooks/index.ts +6 -0
  101. package/src/hooks/useDocGhId.ts +38 -0
  102. package/src/hooks/useGhIdFromUrl.ts +26 -0
  103. package/src/index.ts +9 -0
  104. package/src/meta.tsx +21 -0
  105. package/src/translations.ts +72 -0
  106. package/src/types.ts +51 -0
@@ -0,0 +1,62 @@
1
+ //
2
+ // Copyright 2023 DXOS.org
3
+ //
4
+
5
+ import { type IconWeight, IconBase, type IconProps } from '@phosphor-icons/react';
6
+ import React, { forwardRef, type ReactElement } from 'react';
7
+
8
+ // TODO(wittjosiah): This is a workaround until we have utilities to compose icons.
9
+ // This is a combination of the Circle and Dot icons.
10
+
11
+ const weights = new Map<IconWeight, ReactElement>([
12
+ [
13
+ 'bold',
14
+ <>
15
+ <path d='M128,20A108,108,0,1,0,236,128,108.12,108.12,0,0,0,128,20Zm0,192a84,84,0,1,1,84-84A84.09,84.09,0,0,1,128,212Z' />
16
+ <path d='M144,128a16,16,0,1,1-16-16A16,16,0,0,1,144,128Z' />
17
+ </>,
18
+ ],
19
+ [
20
+ 'duotone',
21
+ <>
22
+ <path d='M224,128a96,96,0,1,1-96-96A96,96,0,0,1,224,128Z' opacity='0.2' />
23
+ <path d='M128,24A104,104,0,1,0,232,128,104.11,104.11,0,0,0,128,24Zm0,192a88,88,0,1,1,88-88A88.1,88.1,0,0,1,128,216Z' />
24
+ <path d='M176,128a48,48,0,1,1-48-48A48,48,0,0,1,176,128Z' opacity='0.2' />
25
+ <path d='M140,128a12,12,0,1,1-12-12A12,12,0,0,1,140,128Z' />
26
+ </>,
27
+ ],
28
+ [
29
+ 'fill',
30
+ <>
31
+ <path d='M128,24A104,104,0,1,0,232,128,104.11,104.11,0,0,0,128,24Zm0,192a88,88,0,1,1,88-88A88.1,88.1,0,0,1,128,216Z' />
32
+ <path d='M128,80a48,48,0,1,0,48,48A48,48,0,0,0,128,80Zm0,60a12,12,0,1,1,12-12A12,12,0,0,1,128,140Z' />
33
+ </>,
34
+ ],
35
+ [
36
+ 'light',
37
+ <>
38
+ <path d='M128,26A102,102,0,1,0,230,128,102.12,102.12,0,0,0,128,26Zm0,192a90,90,0,1,1,90-90A90.1,90.1,0,0,1,128,218Z' />
39
+ <path d='M138,128a10,10,0,1,1-10-10A10,10,0,0,1,138,128Z' />
40
+ </>,
41
+ ],
42
+ [
43
+ 'regular',
44
+ <>
45
+ <path d='M128,24A104,104,0,1,0,232,128,104.11,104.11,0,0,0,128,24Zm0,192a88,88,0,1,1,88-88A88.1,88.1,0,0,1,128,216Z' />
46
+ <path d='M140,128a12,12,0,1,1-12-12A12,12,0,0,1,140,128Z' />
47
+ </>,
48
+ ],
49
+ [
50
+ 'thin',
51
+ <>
52
+ <path d='M128,28A100,100,0,1,0,228,128,100.11,100.11,0,0,0,128,28Zm0,192a92,92,0,1,1,92-92A92.1,92.1,0,0,1,128,220Z' />
53
+ <path d='M136,128a8,8,0,1,1-8-8A8,8,0,0,1,136,128Z' />
54
+ </>,
55
+ ],
56
+ ]);
57
+
58
+ const Issue = forwardRef<SVGSVGElement, IconProps>((props, ref) => <IconBase ref={ref} {...props} weights={weights} />);
59
+
60
+ Issue.displayName = 'Issue';
61
+
62
+ export { Issue };
@@ -0,0 +1,28 @@
1
+ //
2
+ // Copyright 2022 DXOS.org
3
+ //
4
+
5
+ import '@dxosTheme';
6
+
7
+ import { Loading } from './Loading';
8
+
9
+ export default {
10
+ title: 'plugin-github/Loading',
11
+ component: Loading,
12
+ argTypes: {
13
+ size: {
14
+ control: 'select',
15
+ options: ['sm', 'md', 'lg', 'xl'],
16
+ },
17
+ color: {
18
+ control: 'select',
19
+ options: ['primary', 'neutral'],
20
+ },
21
+ },
22
+ };
23
+
24
+ export const Default = { args: { label: 'Loading', size: 'md', color: 'primary' } };
25
+ export const Small = { args: { ...Default.args, size: 'sm' } };
26
+ export const Neutral = { args: { ...Default.args, color: 'neutral' } };
27
+ export const Large = { args: { ...Default.args, size: 'lg' } };
28
+ export const ExtraLarge = { args: { ...Default.args, size: 'xl' } };
@@ -0,0 +1,70 @@
1
+ //
2
+ // Copyright 2022 DXOS.org
3
+ //
4
+
5
+ import React, { type ComponentProps } from 'react';
6
+
7
+ import { useId } from '@dxos/react-ui';
8
+ import { mx } from '@dxos/react-ui-theme';
9
+
10
+ export type LoadingSize = 'sm' | 'md' | 'lg' | 'xl';
11
+
12
+ export type LoadingColor = 'primary' | 'neutral';
13
+
14
+ export interface LoadingSlots {
15
+ root?: Omit<ComponentProps<'div'>, 'children'>;
16
+ svg?: Pick<ComponentProps<'svg'>, 'className'>;
17
+ }
18
+
19
+ export interface LoadingProps {
20
+ label: string;
21
+ size?: LoadingSize;
22
+ color?: LoadingColor;
23
+ slots?: LoadingSlots;
24
+ }
25
+
26
+ const sizeMap = new Map<LoadingSize, string>([
27
+ ['sm', 'w-4 h-4'],
28
+ ['md', 'w-8 h-8'],
29
+ ['lg', 'w-12 h-12'],
30
+ ['xl', 'w-16 h-16'],
31
+ ]);
32
+
33
+ // TODO(wittjosiah): Factor out.
34
+ export const Loading = ({ size, color, label, slots = {} }: LoadingProps) => {
35
+ const labelId = useId('loading-label');
36
+ const sizeClassName = sizeMap.get(size ?? 'md');
37
+ return (
38
+ <div
39
+ {...slots.root}
40
+ className={mx('flex justify-center p-4', slots.root?.className)}
41
+ role='status'
42
+ aria-labelledby={labelId}
43
+ >
44
+ <svg
45
+ role='none'
46
+ className={mx(
47
+ sizeClassName,
48
+ 'text-neutral-200/50 animate-spin dark:text-neutral-600/50',
49
+ color === 'neutral' ? 'fill-neutral-400' : 'fill-primary-400',
50
+ slots.svg?.className,
51
+ )}
52
+ viewBox='0 0 100 101'
53
+ fill='none'
54
+ xmlns='http://www.w3.org/2000/svg'
55
+ >
56
+ <path
57
+ d='M100 50.5908C100 78.2051 77.6142 100.591 50 100.591C22.3858 100.591 0 78.2051 0 50.5908C0 22.9766 22.3858 0.59082 50 0.59082C77.6142 0.59082 100 22.9766 100 50.5908ZM9.08144 50.5908C9.08144 73.1895 27.4013 91.5094 50 91.5094C72.5987 91.5094 90.9186 73.1895 90.9186 50.5908C90.9186 27.9921 72.5987 9.67226 50 9.67226C27.4013 9.67226 9.08144 27.9921 9.08144 50.5908Z'
58
+ fill='currentColor'
59
+ />
60
+ <path
61
+ d='M93.9676 39.0409C96.393 38.4038 97.8624 35.9116 97.0079 33.5539C95.2932 28.8227 92.871 24.3692 89.8167 20.348C85.8452 15.1192 80.8826 10.7238 75.2124 7.41289C69.5422 4.10194 63.2754 1.94025 56.7698 1.05124C51.7666 0.367541 46.6976 0.446843 41.7345 1.27873C39.2613 1.69328 37.813 4.19778 38.4501 6.62326C39.0873 9.04874 41.5694 10.4717 44.0505 10.1071C47.8511 9.54855 51.7191 9.52689 55.5402 10.0491C60.8642 10.7766 65.9928 12.5457 70.6331 15.2552C75.2735 17.9648 79.3347 21.5619 82.5849 25.841C84.9175 28.9121 86.7997 32.2913 88.1811 35.8758C89.083 38.2158 91.5421 39.6781 93.9676 39.0409Z'
62
+ fill='currentFill'
63
+ />
64
+ </svg>
65
+ <span className='sr-only' id={labelId}>
66
+ {label}
67
+ </span>
68
+ </div>
69
+ );
70
+ };
@@ -0,0 +1,5 @@
1
+ //
2
+ // Copyright 2022 DXOS.org
3
+ //
4
+
5
+ export * from './Loading';
@@ -0,0 +1,136 @@
1
+ //
2
+ // Copyright 2023 DXOS.org
3
+ //
4
+
5
+ import { ArrowSquareOut, FileArrowDown, FileArrowUp, Link, LinkBreak } from '@phosphor-icons/react';
6
+ import React, { useCallback } from 'react';
7
+
8
+ import { LayoutAction, useIntent } from '@dxos/app-framework';
9
+ import { log } from '@dxos/log';
10
+ import { type MarkdownProperties } from '@dxos/plugin-markdown';
11
+ import { getMeta } from '@dxos/react-client/echo';
12
+ import { DropdownMenu, useTranslation } from '@dxos/react-ui';
13
+ import { getSize } from '@dxos/react-ui-theme';
14
+
15
+ import { useOctokitContext } from './GithubApiProviders';
16
+ import { useDocGhId } from '../hooks';
17
+ import { GITHUB_PLUGIN } from '../meta';
18
+ import { type GhIssueIdentifier } from '../types';
19
+
20
+ // TODO(burdon): Requires test; very likely out of date.
21
+ // TODO(burdon): Where do "properties" come from? Is this the graph node datum?
22
+ export const MarkdownActions = ({ content, properties }: { content: string; properties: MarkdownProperties }) => {
23
+ // TODO(burdon): Ad hoc assumption that underlying object is ECHO?
24
+ const ghId = getMeta(properties)?.keys?.find((key) => key.source === 'github.com')?.id;
25
+ const { octokit } = useOctokitContext();
26
+ const { t } = useTranslation(GITHUB_PLUGIN);
27
+ const { dispatch } = useIntent();
28
+
29
+ const docGhId = useDocGhId(properties.__meta?.keys ?? []);
30
+
31
+ const updateIssueContent = useCallback(() => {
32
+ const { owner, repo, issueNumber } = docGhId as GhIssueIdentifier;
33
+ return octokit!.rest.issues.update({
34
+ owner,
35
+ repo,
36
+ issue_number: issueNumber,
37
+ body: content,
38
+ });
39
+ }, [octokit, docGhId, content]);
40
+
41
+ const exportGhIssueContent = useCallback(async () => {
42
+ if (octokit && docGhId && 'issueNumber' in docGhId && content) {
43
+ try {
44
+ const {
45
+ data: { html_url: issueUrl },
46
+ } = await updateIssueContent();
47
+ await dispatch({
48
+ action: LayoutAction.SET_LAYOUT,
49
+ data: {
50
+ element: 'dialog',
51
+ component: 'dxos.org/plugin/github/ExportDialog',
52
+ subject: { type: 'response', target: issueUrl, docGhId, content },
53
+ },
54
+ });
55
+ } catch (err) {
56
+ log.error('Failed to export to Github issue');
57
+ }
58
+ } else {
59
+ log.error('Not prepared to export to Github issue when requested.');
60
+ }
61
+ }, [octokit, docGhId, content]);
62
+
63
+ const handleGhExport = useCallback(() => {
64
+ if ('issueNumber' in docGhId!) {
65
+ void exportGhIssueContent();
66
+ } else if ('path' in docGhId!) {
67
+ void dispatch({
68
+ action: LayoutAction.SET_LAYOUT,
69
+ data: {
70
+ element: 'dialog',
71
+ component: 'dxos.org/plugin/github/ExportDialog',
72
+ subject: { type: 'create-pr', content, docGhId },
73
+ },
74
+ });
75
+ }
76
+ }, [exportGhIssueContent, docGhId]);
77
+
78
+ return (
79
+ <>
80
+ <DropdownMenu.GroupLabel>{t('markdown actions label')}</DropdownMenu.GroupLabel>
81
+ {docGhId ? (
82
+ <>
83
+ <DropdownMenu.Item
84
+ classNames='gap-2'
85
+ disabled={!docGhId}
86
+ onClick={() =>
87
+ // TODO(burdon): Intent should return content value from dialog.
88
+ dispatch({
89
+ action: LayoutAction.SET_LAYOUT,
90
+ data: { element: 'dialog', component: 'dxos.org/plugin/github/ImportDialog', subject: { docGhId } },
91
+ })
92
+ }
93
+ >
94
+ <FileArrowDown className={getSize(4)} />
95
+ <span className='grow'>{t('import from github label')}</span>
96
+ </DropdownMenu.Item>
97
+ <DropdownMenu.Item classNames='gap-2' disabled={!docGhId} onClick={() => docGhId && handleGhExport()}>
98
+ <FileArrowUp className={getSize(4)} />
99
+ <span className='grow'>{t('export to github label')}</span>
100
+ </DropdownMenu.Item>
101
+ <DropdownMenu.Item asChild classNames='gap-2' disabled={!ghId}>
102
+ <a
103
+ {...(ghId ? { href: `https://github.com/${ghId}`, target: '_blank', rel: 'noreferrer' } : { href: '#' })}
104
+ >
105
+ <ArrowSquareOut className={getSize(4)} />
106
+ <span className='grow'>{t('open in github label')}</span>
107
+ </a>
108
+ </DropdownMenu.Item>
109
+ <DropdownMenu.Item
110
+ classNames='gap-2'
111
+ onClick={() => {
112
+ const index = getMeta(properties)?.keys?.findIndex((key) => key.source === 'github.com');
113
+ typeof index !== 'undefined' && index >= 0 && properties.__meta?.keys?.splice(index, 1);
114
+ }}
115
+ >
116
+ <LinkBreak className={getSize(4)} />
117
+ <span className='grow'>{t('unbind to file in github label')}</span>
118
+ </DropdownMenu.Item>
119
+ </>
120
+ ) : (
121
+ <DropdownMenu.Item
122
+ classNames='gap-2'
123
+ onClick={() =>
124
+ dispatch({
125
+ action: LayoutAction.SET_LAYOUT,
126
+ data: { element: 'dialog', component: 'dxos.org/plugin/github/BindDialog', subject: properties },
127
+ })
128
+ }
129
+ >
130
+ <Link className={getSize(4)} />
131
+ <span className='grow'>{t('bind to file in github label')}</span>
132
+ </DropdownMenu.Item>
133
+ )}
134
+ </>
135
+ );
136
+ };
@@ -0,0 +1,52 @@
1
+ //
2
+ // Copyright 2023 DXOS.org
3
+ //
4
+
5
+ import React, { useState } from 'react';
6
+
7
+ import { type MarkdownProperties } from '@dxos/plugin-markdown';
8
+ import { Dialog, Button, useTranslation, Input } from '@dxos/react-ui';
9
+
10
+ import { useGhIdFromUrl } from '../hooks';
11
+ import { GITHUB_PLUGIN } from '../meta';
12
+
13
+ export const UrlDialog = ({ properties }: { properties: MarkdownProperties }) => {
14
+ const { t } = useTranslation(GITHUB_PLUGIN);
15
+ const [ghUrlValue, setGhUrlValue] = useState('');
16
+ const ghId = useGhIdFromUrl(ghUrlValue);
17
+
18
+ return (
19
+ <>
20
+ <Dialog.Title classNames='mbe-2'>{t('bind to file in github label')}</Dialog.Title>
21
+ <Input.Root validationValence='error'>
22
+ <Input.Label>{t('paste url to file in github label')}</Input.Label>
23
+ <Input.TextInput
24
+ placeholder={t('paste url to file in github placeholder')}
25
+ value={ghUrlValue}
26
+ onChange={({ target: { value } }) => setGhUrlValue(value)}
27
+ />
28
+ <Input.DescriptionAndValidation>
29
+ {ghUrlValue.length > 0 && !ghId && (
30
+ <Input.Validation>{t('error github markdown path message')}</Input.Validation>
31
+ )}
32
+ <Input.Description>{t('paste url to file in github description')}</Input.Description>
33
+ </Input.DescriptionAndValidation>
34
+ </Input.Root>
35
+ <div role='none' className='flex justify-end gap-2'>
36
+ <Dialog.Close asChild>
37
+ <Button
38
+ classNames='mbs-2'
39
+ onClick={() => {
40
+ if (ghId && document) {
41
+ // TODO(burdon): Meta should be immutable.
42
+ properties.__meta.keys.push({ source: 'github.com', id: ghId });
43
+ }
44
+ }}
45
+ >
46
+ {t('done label', { ns: 'os' })}
47
+ </Button>
48
+ </Dialog.Close>
49
+ </div>
50
+ </>
51
+ );
52
+ };
@@ -0,0 +1,12 @@
1
+ //
2
+ // Copyright 2023 DXOS.org
3
+ //
4
+
5
+ export * from './EmbeddedMain';
6
+ export * from './ExportDialog';
7
+ export * from './GithubApiProviders';
8
+ export * from './GithubEchoResolverProviders';
9
+ export * from './ImportDialog';
10
+ export * from './Issue';
11
+ export * from './MarkdownActions';
12
+ export * from './UrlDialog';
@@ -0,0 +1,6 @@
1
+ //
2
+ // Copyright 2023 DXOS.org
3
+ //
4
+
5
+ export * from './useDocGhId';
6
+ export * from './useGhIdFromUrl';
@@ -0,0 +1,38 @@
1
+ //
2
+ // Copyright 2023 DXOS.org
3
+ //
4
+
5
+ import { useMemo } from 'react';
6
+
7
+ import { log } from '@dxos/log';
8
+
9
+ import { type GhIdentifier } from '../types';
10
+
11
+ export const useDocGhId = (keys: { source?: string; id?: string }[]) => {
12
+ return useMemo<GhIdentifier | null>(() => {
13
+ try {
14
+ const key = keys?.find((key) => key.source === 'github.com');
15
+ const [owner, repo, type, ...rest] = key?.id?.split('/') ?? [];
16
+ if (type === 'issues') {
17
+ return {
18
+ owner,
19
+ repo,
20
+ issueNumber: parseInt(rest[0], 10),
21
+ };
22
+ } else if (type === 'blob') {
23
+ const [ref, ...pathParts] = rest;
24
+ return {
25
+ owner,
26
+ repo,
27
+ ref,
28
+ path: pathParts.join('/'),
29
+ };
30
+ } else {
31
+ return null;
32
+ }
33
+ } catch (err) {
34
+ log.catch(err);
35
+ return null;
36
+ }
37
+ }, [keys]);
38
+ };
@@ -0,0 +1,26 @@
1
+ //
2
+ // Copyright 2023 DXOS.org
3
+ //
4
+
5
+ import { useMemo } from 'react';
6
+
7
+ export const useGhIdFromUrl = (ghUrlValue: string) =>
8
+ useMemo<string | null>(() => {
9
+ try {
10
+ const url = new URL(ghUrlValue);
11
+ const [_, owner, repo, type, ...rest] = url.pathname.split('/');
12
+ if (type === 'blob') {
13
+ const [ref, ...pathParts] = rest;
14
+ const path = pathParts.join('/');
15
+ const ext = pathParts[pathParts.length - 1].split('.')[1];
16
+ return ext === 'md' ? `${owner}/${repo}/blob/${ref}/${path}` : null;
17
+ } else if (type === 'issues') {
18
+ const [issueNumberString] = rest;
19
+ return `${owner}/${repo}/issues/${issueNumberString}`;
20
+ } else {
21
+ return null;
22
+ }
23
+ } catch (e) {
24
+ return null;
25
+ }
26
+ }, [ghUrlValue]);
package/src/index.ts ADDED
@@ -0,0 +1,9 @@
1
+ //
2
+ // Copyright 2023 DXOS.org
3
+ //
4
+
5
+ import { GithubPlugin } from './GithubPlugin';
6
+
7
+ export default GithubPlugin;
8
+
9
+ export * from './GithubPlugin';
package/src/meta.tsx ADDED
@@ -0,0 +1,21 @@
1
+ //
2
+ // Copyright 2023 DXOS.org
3
+ //
4
+
5
+ import { GithubLogo, type IconProps } from '@phosphor-icons/react';
6
+ import React from 'react';
7
+
8
+ import { pluginMeta } from '@dxos/app-framework';
9
+
10
+ export const GITHUB_PLUGIN = 'dxos.org/plugin/github';
11
+ export const GITHUB_PLUGIN_SHORT_ID = 'github';
12
+
13
+ export default pluginMeta({
14
+ id: GITHUB_PLUGIN,
15
+ shortId: GITHUB_PLUGIN_SHORT_ID,
16
+ name: 'GitHub',
17
+ description: 'GitHub integration.',
18
+ tags: ['experimental'],
19
+ iconComponent: (props: IconProps) => <GithubLogo {...props} />,
20
+ iconSymbol: 'ph--github-logo--regular',
21
+ });
@@ -0,0 +1,72 @@
1
+ //
2
+ // Copyright 2023 DXOS.org
3
+ //
4
+
5
+ import { GITHUB_PLUGIN } from './meta';
6
+
7
+ export default [
8
+ {
9
+ 'en-US': {
10
+ [GITHUB_PLUGIN]: {
11
+ 'plugin name': 'GitHub',
12
+ 'markdown actions label': 'GitHub actions',
13
+ 'unbind to file in github label': 'Disconnect from GitHub',
14
+ 'bind to file in github label': 'Connect to issue or file in GitHub',
15
+ 'github pat label': 'GitHub personal access token:',
16
+ 'github pat description':
17
+ 'Composer needs this in order to communicate with GitHub. <docsLink>GitHub’s documentation describes how to create a token.</docsLink> Composer only needs write access to issues, contents, and pull requests.',
18
+ 'github pat description href':
19
+ 'https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens',
20
+ 'empty github pat message': 'Set a GitHub personal access token to continue.',
21
+ 'set github pat label': 'Set GitHub token',
22
+ 'error github pat message':
23
+ 'There was a problem authenticating with GitHub using the personal access token provided.',
24
+ 'error github markdown path message': 'This is not a valid path to a Markdown file or Issue in GitHub.',
25
+ 'paste url to file in github label': 'Paste the URL to the Issue or Markdown file in GitHub.',
26
+ 'paste url to file in github description':
27
+ 'Navigate to the issue or file in GitHub, then copy the URL in your browser and paste it here.',
28
+ 'paste url to file in github placeholder': 'https://github.com/owner/repo/blob/main/path/to/README.md',
29
+ 'confirm export title': 'Export to GitHub',
30
+ 'export to github success message':
31
+ '<resultStyle>Success!</resultStyle> Your changes are now live here: <prLink>{{linkText}}</prLink>',
32
+ 'github branch name label': 'Name of the branch to create',
33
+ 'github branch name placeholder': 'update-readme',
34
+ 'github commit message label': 'Commit message',
35
+ 'github commit message placeholder': 'Updated README.md',
36
+ 'save and close description': 'Save changes to GitHub and close the editor',
37
+ 'close embed description':
38
+ 'Close the editor without saving changes to GitHub. Your changes will still persist in Composer.',
39
+ 'resolver init document message': 'Syncing this document, one moment…',
40
+ 'comment stale title': 'No longer in-sync',
41
+ 'comment stale body':
42
+ 'The document in GitHub was updated in another session. To re-sync, please save your changes, reload the page, and choose to edit from GitHub again.',
43
+ 'open in github label': 'Open in GitHub',
44
+ 'stale rescue title': 'Set a personal access token',
45
+ 'stale rescue description':
46
+ 'Another user has recently updated this issue, so GitHub won’t accept your changes unless you set a personal access token (a PAT) here, or refresh the page.',
47
+ 'embedded options label': 'Options',
48
+ 'unset repo space label': 'Select a different space for this repository',
49
+ 'loading preview message': 'Loading preview…',
50
+ 'preview gfm label': 'Preview Markdown',
51
+ 'exit gfm preview label': 'Exit preview',
52
+ 'save and close label': 'Save & close',
53
+ 'export to github label': 'Export to GitHub',
54
+ 'import from github label': 'Import from GitHub',
55
+ 'resolver tree label': 'Choose a Space',
56
+ 'resolver tree description':
57
+ 'To collaborate on documents in this repository, choose the Space that will store and control access to the documents.',
58
+ 'resolver no spaces message': 'You aren’t in any spaces yet',
59
+ 'resolver create space label': 'Create a space for this repository',
60
+ 'bound members message_one': 'One member uses this space for this repository',
61
+ 'bound members message_other': '{{count}} members use this space for this repository',
62
+ 'select label': 'Select',
63
+ 'selected label': 'Selected',
64
+ 'open in composer label': 'Open in Composer',
65
+ 'confirm import title': 'Overwrite this document’s content?',
66
+ 'confirm import body':
67
+ 'Importing will overwrite this document’s content. If you’d rather import into a new document, first create a new document and then import into it.',
68
+ 'target blank description': 'Link opens in a new tab.',
69
+ },
70
+ },
71
+ },
72
+ ];
package/src/types.ts ADDED
@@ -0,0 +1,51 @@
1
+ //
2
+ // Copyright 2023 DXOS.org
3
+ //
4
+
5
+ import { type Dispatch, type SetStateAction } from 'react';
6
+
7
+ import {
8
+ type GraphBuilderProvides,
9
+ type TranslationsProvides,
10
+ type SettingsProvides,
11
+ type SurfaceProvides,
12
+ } from '@dxos/app-framework';
13
+ import { type DocumentType } from '@dxos/plugin-markdown/types';
14
+ import { type Space } from '@dxos/react-client/echo';
15
+
16
+ export type EditorViewState = 'editor' | 'preview';
17
+
18
+ export type MarkdownDocumentProps = {
19
+ space: Space;
20
+ document: DocumentType;
21
+ layout: 'standalone' | 'embedded';
22
+ editorViewState: EditorViewState;
23
+ setEditorViewState: Dispatch<SetStateAction<EditorViewState>>;
24
+ };
25
+
26
+ export type GhSharedProps = {
27
+ owner: string;
28
+ repo: string;
29
+ };
30
+
31
+ export type GhFileIdentifier = GhSharedProps & {
32
+ ref: string;
33
+ path: string;
34
+ };
35
+
36
+ export type GhIssueIdentifier = GhSharedProps & {
37
+ issueNumber: number;
38
+ };
39
+
40
+ export type GhIdentifier = GhFileIdentifier | GhIssueIdentifier;
41
+
42
+ export type ExportViewState = 'create-pr' | 'pending' | 'response' | null;
43
+
44
+ export type GithubSettingsProps = {
45
+ pat?: string;
46
+ };
47
+
48
+ export type GithubPluginProvides = SurfaceProvides &
49
+ GraphBuilderProvides &
50
+ SettingsProvides<GithubSettingsProps> &
51
+ TranslationsProvides;