Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ Run `opencli list` for the live registry.
| **bloomberg** | `main` `markets` `economics` `industries` `tech` `politics` `businessweek` `opinions` `feeds` `news` | Public / Browser |
| **ctrip** | `search` | Browser |
| **devto** | `top` `tag` `user` | Public |
| **dictionary** | `search` `synonyms` `examples` | Public |
| **arxiv** | `search` `paper` | Public |
| **wikipedia** | `search` `summary` `random` `trending` | Public |
| **hackernews** | `top` `new` `best` `ask` `show` `jobs` `search` `user` | Public |
Expand Down
1 change: 1 addition & 0 deletions README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ npm install -g @jackwener/opencli@latest
| **bloomberg** | `main` `markets` `economics` `industries` `tech` `politics` `businessweek` `opinions` `feeds` `news` | ε…¬ε…± API / ζ΅θ§ˆε™¨ |
| **ctrip** | `search` | ζ΅θ§ˆε™¨ |
| **devto** | `top` `tag` `user` | ε…¬εΌ€ |
| **dictionary** | `search` `synonyms` `examples` | ε…¬εΌ€ |
| **arxiv** | `search` `paper` | ε…¬εΌ€ |
| **wikipedia** | `search` `summary` `random` `trending` | ε…¬εΌ€ |
| **hackernews** | `top` `new` `best` `ask` `show` `jobs` `search` `user` | ε…¬ε…± API |
Expand Down
1 change: 1 addition & 0 deletions docs/.vitepress/config.mts
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ export default defineConfig({
items: [
{ text: 'HackerNews', link: '/adapters/browser/hackernews' },
{ text: 'Dev.to', link: '/adapters/browser/devto' },
{ text: 'Dictionary', link: '/adapters/browser/dictionary' },
{ text: 'BBC', link: '/adapters/browser/bbc' },
{ text: 'Apple Podcasts', link: '/adapters/browser/apple-podcasts' },
{ text: 'Xiaoyuzhou', link: '/adapters/browser/xiaoyuzhou' },
Expand Down
27 changes: 27 additions & 0 deletions docs/adapters/browser/dictionary.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Dictionary

**Mode**: 🌐 Public · **Domain**: `api.dictionaryapi.dev`

Search the open dictionary to quickly fetch native definitions, part of speech contexts, and phonetic pronunciations directly in your IDE terminal.

## Commands

| Command | Description |
|---------|-------------|
| `opencli dictionary search` | Fetch the exact definition of a word |
| `opencli dictionary synonyms` | Find related synonyms for a word |
| `opencli dictionary examples` | Read real-world sentence usage examples |

## Usage Examples

```bash
# Look up a complex term
opencli dictionary search serendipity

# Discover phonetics
opencli dictionary search ephemeral
```

## Prerequisites

- No browser required β€” utilizes the fast, open JSON definitions API.
1 change: 1 addition & 0 deletions docs/adapters/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ Run `opencli list` for the live registry.
| **[hackernews](/adapters/browser/hackernews)** | `top` `new` `best` `ask` `show` `jobs` `search` `user` | 🌐 Public |
| **[bbc](/adapters/browser/bbc)** | `news` | 🌐 Public |
| **[devto](/adapters/browser/devto)** | `top` `tag` `user` | 🌐 Public |
| **[dictionary](/adapters/browser/dictionary)** | `search` `synonyms` `examples` | 🌐 Public |
| **[apple-podcasts](/adapters/browser/apple-podcasts)** | `search` `episodes` `top` | 🌐 Public |
| **[xiaoyuzhou](/adapters/browser/xiaoyuzhou)** | `podcast` `podcast-episodes` `episode` | 🌐 Public |
| **[yahoo-finance](/adapters/browser/yahoo-finance)** | `quote` | 🌐 Public |
Expand Down
25 changes: 25 additions & 0 deletions src/clis/dictionary/examples.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
site: dictionary
name: examples
description: Read real-world example sentences utilizing the word
domain: api.dictionaryapi.dev
strategy: public
browser: false

args:
word:
type: string
required: true
positional: true
description: Word to get example sentences for

pipeline:
- fetch:
url: "https://api.dictionaryapi.dev/api/v2/entries/en/${{ args.word | urlencode }}"

- map:
word: "${{ item.word }}"
example: "${{ (() => { if (item.meanings) { for (const m of item.meanings) { if (m.definitions) { for (const d of m.definitions) { if (d.example) return d.example; } } } } return 'No example found in API.'; })() }}"

- limit: 1

columns: [word, example]
27 changes: 27 additions & 0 deletions src/clis/dictionary/search.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
site: dictionary
name: search
description: Search the Free Dictionary API for definitions, parts of speech, and pronunciations.
domain: api.dictionaryapi.dev
strategy: public
browser: false

args:
word:
type: string
required: true
positional: true
description: Word to define (e.g., serendipity)

pipeline:
- fetch:
url: "https://api.dictionaryapi.dev/api/v2/entries/en/${{ args.word | urlencode }}"

- map:
word: "${{ item.word }}"
phonetic: "${{ (() => { if (item.phonetic) return item.phonetic; if (item.phonetics) { for (const p of item.phonetics) { if (p.text) return p.text; } } return ''; })() }}"
type: "${{ item.meanings[0].partOfSpeech }}"
definition: "${{ item.meanings[0].definitions[0].definition }}"

- limit: 1

columns: [word, phonetic, type, definition]
25 changes: 25 additions & 0 deletions src/clis/dictionary/synonyms.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
site: dictionary
name: synonyms
description: Find synonyms for a specific word
domain: api.dictionaryapi.dev
strategy: public
browser: false

args:
word:
type: string
required: true
positional: true
description: Word to find synonyms for (e.g., serendipity)

pipeline:
- fetch:
url: "https://api.dictionaryapi.dev/api/v2/entries/en/${{ args.word | urlencode }}"

- map:
word: "${{ item.word }}"
synonyms: "${{ (() => { const s = new Set(); if (item.meanings) { for (const m of item.meanings) { if (m.synonyms) { for (const syn of m.synonyms) s.add(syn); } if (m.definitions) { for (const d of m.definitions) { if (d.synonyms) { for (const syn of d.synonyms) s.add(syn); } } } } } const arr = Array.from(s); return arr.length > 0 ? arr.slice(0, 5).join(', ') : 'No synonyms found in API.'; })() }}"

- limit: 1

columns: [word, synonyms]
33 changes: 33 additions & 0 deletions tests/e2e/public-commands.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -489,4 +489,37 @@ describe('public commands E2E', () => {
expect(data.length).toBeGreaterThan(0);
expect(data.every((d: any) => d.type === 'image')).toBe(true);
}, 30_000);

// ── dictionary (public API, browser: false) ──
it('dictionary search returns word definitions', async () => {
const { stdout, code } = await runCli(['dictionary', 'search', 'serendipity', '-f', 'json']);
expect(code).toBe(0);
const data = parseJsonOutput(stdout);
expect(Array.isArray(data)).toBe(true);
expect(data.length).toBeGreaterThanOrEqual(1);
expect(data[0]).toHaveProperty('word', 'serendipity');
expect(data[0]).toHaveProperty('phonetic');
expect(data[0]).toHaveProperty('definition');
}, 30_000);

it('dictionary synonyms returns synonyms', async () => {
const { stdout, code } = await runCli(['dictionary', 'synonyms', 'serendipity', '-f', 'json']);
expect(code).toBe(0);
const data = parseJsonOutput(stdout);
expect(Array.isArray(data)).toBe(true);
expect(data.length).toBeGreaterThanOrEqual(1);
expect(data[0]).toHaveProperty('word', 'serendipity');
expect(data[0]).toHaveProperty('synonyms');
}, 30_000);

it('dictionary examples returns examples', async () => {
const { stdout, code } = await runCli(['dictionary', 'examples', 'perfect', '-f', 'json']);
expect(code).toBe(0);
const data = parseJsonOutput(stdout);
expect(Array.isArray(data)).toBe(true);
expect(data.length).toBeGreaterThanOrEqual(1);
expect(data[0]).toHaveProperty('word', 'perfect');
expect(data[0]).toHaveProperty('example');
}, 30_000);
}, 30_000);
});
Loading