Skip to content

Commit ba2c3a4

Browse files
zhensherlockcodex
andcommitted
feat(goodlinks): add GoodLinks URL scheme support
Co-Authored-By: Codex <267193182+codex@users.noreply.github.com>
1 parent d1890fe commit ba2c3a4

14 files changed

Lines changed: 808 additions & 0 deletions

File tree

.changeset/twenty-parents-teach.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'protocol-launcher': minor
3+
---
4+
5+
feat(goodlinks): add GoodLinks URL scheme support

apps/docs/.vitepress/config.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ export default defineConfig({
6060
'en/apps/ftstreets.md': 'apps/ftstreets.md',
6161
'en/apps/github-desktop.md': 'apps/github-desktop.md',
6262
'en/apps/gladys.md': 'apps/gladys.md',
63+
'en/apps/goodlinks.md': 'apps/goodlinks.md',
6364
'en/apps/goland.md': 'apps/goland.md',
6465
'en/apps/hbuilderx.md': 'apps/hbuilderx.md',
6566
'en/apps/hookmark.md': 'apps/hookmark.md',
@@ -221,6 +222,7 @@ export default defineConfig({
221222
{ text: 'Streets', link: '/apps/ftstreets' },
222223
{ text: 'GitHub Desktop', link: '/apps/github-desktop' },
223224
{ text: 'Gladys', link: '/apps/gladys' },
225+
{ text: 'GoodLinks', link: '/apps/goodlinks' },
224226
{ text: 'GoLand', link: '/apps/goland' },
225227
{ text: 'HBuilderX', link: '/apps/hbuilderx' },
226228
{ text: 'Hookmark', link: '/apps/hookmark' },
@@ -388,6 +390,7 @@ export default defineConfig({
388390
{ text: 'Streets', link: '/apps/ftstreets' },
389391
{ text: 'GitHub Desktop', link: '/apps/github-desktop' },
390392
{ text: 'Gladys', link: '/apps/gladys' },
393+
{ text: 'GoodLinks', link: '/apps/goodlinks' },
391394
{ text: 'GoLand', link: '/apps/goland' },
392395
{ text: 'HBuilderX', link: '/apps/hbuilderx' },
393396
{ text: 'Hookmark', link: '/apps/hookmark' },
@@ -520,6 +523,7 @@ export default defineConfig({
520523
{ text: 'Streets', link: '/zh/apps/ftstreets' },
521524
{ text: 'GitHub Desktop', link: '/zh/apps/github-desktop' },
522525
{ text: 'Gladys', link: '/zh/apps/gladys' },
526+
{ text: 'GoodLinks', link: '/zh/apps/goodlinks' },
523527
{ text: 'GoLand', link: '/zh/apps/goland' },
524528
{ text: 'HBuilderX', link: '/zh/apps/hbuilderx' },
525529
{ text: 'Hookmark', link: '/zh/apps/hookmark' },
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
export const saveParams = {
2+
url: 'https://apple.com',
3+
starred: '1' as const,
4+
tags: 'apple ios',
5+
}
6+
7+
export const openParams = {
8+
url: 'https://example.com/article',
9+
}
10+
11+
export const pickParams = {
12+
urlParam: 'link',
13+
titleParam: 'name',
14+
summaryParam: 'description',
15+
}
16+
17+
export const tagParams = {
18+
name: 'apple',
19+
}

apps/docs/en/apps/goodlinks.md

Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
---
2+
layout: doc
3+
---
4+
5+
<script setup lang="ts">
6+
import { ref, computed } from 'vue';
7+
import VPLink from 'vitepress/dist/client/theme-default/components/VPLink.vue';
8+
import { save, open, pick, last, random, unread, starred, untagged, read, tag } from 'protocol-launcher/goodlinks';
9+
import { SelectInstallationMethod } from '../../.vitepress/components';
10+
import { saveParams, openParams, pickParams, tagParams } from '../../.vitepress/constants/goodlinks';
11+
12+
const currentMethod = ref('On-Demand');
13+
const importPath = computed(() => currentMethod.value === 'On-Demand' ? 'protocol-launcher/goodlinks' : 'protocol-launcher');
14+
</script>
15+
16+
# GoodLinks
17+
18+
[GoodLinks](https://goodlinks.app/) is a read-it-later app for saving and reading links. **Protocol Launcher** allows you to generate GoodLinks x-callback-url actions exactly from the official URL scheme: save, open, pick, last, random, unread, starred, untagged, read, and tag.
19+
20+
GoodLinks supports `x-success`, `x-error`, and `x-cancel` callback URLs. Pass them as `xSuccess`, `xError`, and `xCancel` when needed.
21+
22+
## Usage
23+
24+
There are two ways to use this library:
25+
26+
- On-Demand import from subpaths enables tree-shaking and keeps bundles small.
27+
- Full Import from the root package is convenient but includes all app modules.
28+
29+
Pick On-Demand for production builds; Full Import is fine for quick scripts or demos.
30+
31+
<SelectInstallationMethod v-model="currentMethod" />
32+
33+
### Save Link
34+
35+
```ts-vue [{{currentMethod}}]
36+
import { {{ currentMethod === 'On-Demand' ? 'save' : 'goodlinks' }} } from '{{ importPath }}'
37+
38+
const url = {{currentMethod === 'On-Demand' ? '' : 'goodlinks.'}}save({
39+
url: 'https://apple.com',
40+
starred: '1',
41+
tags: 'apple ios',
42+
})
43+
```
44+
45+
<div class="flex justify-center">
46+
<VPLink :href="save(saveParams)" target="_self">
47+
Save Link in GoodLinks
48+
</VPLink>
49+
</div>
50+
51+
### Open Link
52+
53+
```ts-vue [{{currentMethod}}]
54+
import { {{ currentMethod === 'On-Demand' ? 'open' : 'goodlinks' }} } from '{{ importPath }}'
55+
56+
const url = {{currentMethod === 'On-Demand' ? '' : 'goodlinks.'}}open({
57+
url: 'https://example.com/article',
58+
})
59+
```
60+
61+
<div class="flex justify-center">
62+
<VPLink :href="open(openParams)" target="_self">
63+
Open Link in GoodLinks
64+
</VPLink>
65+
</div>
66+
67+
### Pick Link Details
68+
69+
```ts-vue [{{currentMethod}}]
70+
import { {{ currentMethod === 'On-Demand' ? 'pick' : 'goodlinks' }} } from '{{ importPath }}'
71+
72+
const url = {{currentMethod === 'On-Demand' ? '' : 'goodlinks.'}}pick({
73+
urlParam: 'link',
74+
titleParam: 'name',
75+
summaryParam: 'description',
76+
})
77+
```
78+
79+
<div class="flex justify-center">
80+
<VPLink :href="pick(pickParams)" target="_self">
81+
Pick Link Details in GoodLinks
82+
</VPLink>
83+
</div>
84+
85+
### Open Last Unread Link
86+
87+
```ts-vue [{{currentMethod}}]
88+
import { {{ currentMethod === 'On-Demand' ? 'last' : 'goodlinks' }} } from '{{ importPath }}'
89+
90+
const url = {{currentMethod === 'On-Demand' ? '' : 'goodlinks.'}}last()
91+
```
92+
93+
<div class="flex justify-center">
94+
<VPLink :href="last()" target="_self">
95+
Open Last Unread Link in GoodLinks
96+
</VPLink>
97+
</div>
98+
99+
### Open Random Unread Link
100+
101+
```ts-vue [{{currentMethod}}]
102+
import { {{ currentMethod === 'On-Demand' ? 'random' : 'goodlinks' }} } from '{{ importPath }}'
103+
104+
const url = {{currentMethod === 'On-Demand' ? '' : 'goodlinks.'}}random()
105+
```
106+
107+
<div class="flex justify-center">
108+
<VPLink :href="random()" target="_self">
109+
Open Random Unread Link in GoodLinks
110+
</VPLink>
111+
</div>
112+
113+
### Show Unread List
114+
115+
```ts-vue [{{currentMethod}}]
116+
import { {{ currentMethod === 'On-Demand' ? 'unread' : 'goodlinks' }} } from '{{ importPath }}'
117+
118+
const url = {{currentMethod === 'On-Demand' ? '' : 'goodlinks.'}}unread()
119+
```
120+
121+
<div class="flex justify-center">
122+
<VPLink :href="unread()" target="_self">
123+
Show Unread List in GoodLinks
124+
</VPLink>
125+
</div>
126+
127+
### Show Starred List
128+
129+
```ts-vue [{{currentMethod}}]
130+
import { {{ currentMethod === 'On-Demand' ? 'starred' : 'goodlinks' }} } from '{{ importPath }}'
131+
132+
const url = {{currentMethod === 'On-Demand' ? '' : 'goodlinks.'}}starred()
133+
```
134+
135+
<div class="flex justify-center">
136+
<VPLink :href="starred()" target="_self">
137+
Show Starred List in GoodLinks
138+
</VPLink>
139+
</div>
140+
141+
### Show Untagged List
142+
143+
```ts-vue [{{currentMethod}}]
144+
import { {{ currentMethod === 'On-Demand' ? 'untagged' : 'goodlinks' }} } from '{{ importPath }}'
145+
146+
const url = {{currentMethod === 'On-Demand' ? '' : 'goodlinks.'}}untagged()
147+
```
148+
149+
<div class="flex justify-center">
150+
<VPLink :href="untagged()" target="_self">
151+
Show Untagged List in GoodLinks
152+
</VPLink>
153+
</div>
154+
155+
### Show Read List
156+
157+
```ts-vue [{{currentMethod}}]
158+
import { {{ currentMethod === 'On-Demand' ? 'read' : 'goodlinks' }} } from '{{ importPath }}'
159+
160+
const url = {{currentMethod === 'On-Demand' ? '' : 'goodlinks.'}}read()
161+
```
162+
163+
<div class="flex justify-center">
164+
<VPLink :href="read()" target="_self">
165+
Show Read List in GoodLinks
166+
</VPLink>
167+
</div>
168+
169+
### Show Tagged Links
170+
171+
```ts-vue [{{currentMethod}}]
172+
import { {{ currentMethod === 'On-Demand' ? 'tag' : 'goodlinks' }} } from '{{ importPath }}'
173+
174+
const url = {{currentMethod === 'On-Demand' ? '' : 'goodlinks.'}}tag({
175+
name: 'apple',
176+
})
177+
```
178+
179+
<div class="flex justify-center">
180+
<VPLink :href="tag(tagParams)" target="_self">
181+
Show Tagged Links in GoodLinks
182+
</VPLink>
183+
</div>

apps/docs/en/guide/getting-started.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,7 @@ For detailed usage instructions for each application, please refer to their resp
159159
- [Streets](../apps/ftstreets.md)
160160
- [GitHub Desktop](../apps/github-desktop.md)
161161
- [Gladys](../apps/gladys.md)
162+
- [GoodLinks](../apps/goodlinks.md)
162163
- [GoLand](../apps/goland.md)
163164
- [HBuilderX](../apps/hbuilderx.md)
164165
- [Hookmark](../apps/hookmark.md)

apps/docs/en/guide/what-is-it.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ Currently, we support the following applications:
6262
- [Streets](../apps/ftstreets.md)
6363
- [GitHub Desktop](../apps/github-desktop.md)
6464
- [Gladys](../apps/gladys.md)
65+
- [GoodLinks](../apps/goodlinks.md)
6566
- [GoLand](../apps/goland.md)
6667
- [HBuilderX](../apps/hbuilderx.md)
6768
- [Hookmark](../apps/hookmark.md)

0 commit comments

Comments
 (0)