| /api/[version] |
12 |
13 | ## Query
14 |
15 | | | Type | Description | Required | Default |
16 | | :-------- | :----- | :----------------------------- | :------- | :------ |
17 | | word | String | The word to search for | Yes | |
18 | | version | String | The version of the API to use | Yes | v1 |
19 |
20 | ## Methods
21 |
22 | | | Endpoint | Description | Example |
23 | | :-------- | :--------------------------| :-------------------------------------- | :--------------------------------|
24 | | `GET` | `/pronunciation/en/[word]` | Pronunciation of the given word | /api/v1/pronunciation/en/go |
25 |
26 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 |
2 | The MIT License (MIT)
3 |
4 | Copyright (c) 2021 Sang Nguyen
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | SOFTWARE.
23 |
--------------------------------------------------------------------------------
/docs/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: home
3 |
4 | hero:
5 | name: Free Dictionary API
6 | text: A new way to write stories
7 | tagline: Powered by Vite
8 | image:
9 | src: /logo.svg
10 | alt: Free Dictionary API logo
11 | actions:
12 | - theme: brand
13 | text: Get Started
14 | link: /guide/getting-started
15 | - theme: alt
16 | text: Why Histoire?
17 | link: /guide/
18 | - theme: alt
19 | text: View on GitHub
20 | link: https://github.com/ngocsangyem/freedictionaryapi
21 |
22 | features:
23 | - title: 📖 Stories
24 | details: Write stories to showcase and document your components.
25 | - title: ⚡ Fast
26 | details: Incredibly fast development building and production page loading!
27 | - title: 🔧️ No-config
28 | details: Sane and configurable defaults, automatically reuses your Vite config!
29 | - title: 🎨 Themable
30 | details: Customize the look of the generated app with your own branding.
31 | - title: 💻️ Copiable code
32 | details: Automatically generates dynamic template source code!
33 | - title: 🌙 Dark mode
34 | details: Enjoy a more pleasing experience during night.
35 | ---
36 |
37 |
--------------------------------------------------------------------------------
/src/app.js:
--------------------------------------------------------------------------------
1 | const express = require('express');
2 | const rateLimit = require('express-rate-limit');
3 | const { getDefinition } = require('./routes/definition');
4 | const WikiDictionary = require('./modules/wiktionary/dictionary');
5 | const path = require('path');
6 |
7 | const app = express();
8 | let dictionary;
9 |
10 | const limiter = rateLimit({
11 | windowMs: 5 * 60 * 1000, // 5 minutes
12 | max: 800, // limit each IP to 450 requests per windowMs
13 | });
14 | const host = '0.0.0.0'
15 | const PORT = process.env.PORT || 3000;
16 |
17 |
18 | async function initializeDictionary() {
19 | try {
20 | const WikDictionary = new WikiDictionary();
21 | await WikDictionary.loadDictionary(path.join(__dirname, '../data/data.jsonl'));
22 |
23 | dictionary = WikDictionary.dictionaryData;
24 | } catch (error) {
25 | console.error('Error loading dictionary:', error);
26 | process.exit(1);
27 | }
28 | }
29 |
30 | app.set('trust proxy', true);
31 | app.use(limiter);
32 |
33 | initializeDictionary().then(() => {
34 | app.use((req, res, next) => {
35 | req.dictionary = dictionary;
36 | next();
37 | });
38 |
39 | app.use('/api', getDefinition);
40 |
41 | app.listen(PORT, host, () => {
42 | console.log('Server is running on port 3000');
43 | });
44 | });
45 |
46 | module.exports = app;
47 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "freedictionaryapi",
3 | "version": "1.0.0",
4 | "description": "Dictionary for EDict extension",
5 | "main": "src/app.js",
6 | "scripts": {
7 | "start": "node ./src/app.js",
8 | "docs:dev": "vitepress dev docs",
9 | "docs:build": "vitepress build docs",
10 | "docs:serve": "vitepress serve docs"
11 | },
12 | "repository": {
13 | "type": "git",
14 | "url": "git+https://github.com/ngocsangyem/freedictionaryapi.git"
15 | },
16 | "keywords": [
17 | "API",
18 | "Nodejs",
19 | "Javascript"
20 | ],
21 | "author": "ngocsangyem",
22 | "license": "MIT",
23 | "bugs": {
24 | "url": "https://github.com/ngocsangyem/freedictionaryapi/issues"
25 | },
26 | "homepage": "https://github.com/ngocsangyem/freedictionaryapi#readme",
27 | "dependencies": {
28 | "axios": "^0.27.2",
29 | "cheerio": "^1.0.0-rc.10",
30 | "dotenv": "^16.0.3",
31 | "event-stream": "^4.0.1",
32 | "express": "^4.17.3",
33 | "express-rate-limit": "^6.3.0",
34 | "jsdom": "^19.0.0",
35 | "mongodb": "^5.1.0",
36 | "node-fetch": "^2.6.7"
37 | },
38 | "devDependencies": {
39 | "@iconify/vue": "^3.2.1",
40 | "@vueuse/core": "^8.9.0",
41 | "autoprefixer": "^10.4.7",
42 | "floating-vue": "^2.0.0-beta.17",
43 | "postcss": "^8.4.14",
44 | "sass": "^1.53.0",
45 | "tailwindcss": "^3.1.4",
46 | "vitepress": "^1.0.0-alpha.4",
47 | "vue": "^3.2.37"
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/docs/.vitepress/theme/DemoPreview.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
10 |
11 |
15 |
16 |
29 |
30 |
31 |
36 |
41 | Online demo
42 |
43 |
44 |
--------------------------------------------------------------------------------
/docs/.vitepress/theme/SponsorButton.vue:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 |
13 |
27 |
28 |
29 |
55 |
56 |
57 |
58 |
--------------------------------------------------------------------------------
/tailwind.config.cjs:
--------------------------------------------------------------------------------
1 | const defaultTheme = require('tailwindcss/defaultTheme')
2 | const colors = require('tailwindcss/colors')
3 |
4 | module.exports = {
5 | theme: {
6 | extend: {
7 | colors: {
8 | primary: colors.emerald,
9 |
10 | gray: {
11 | ...colors.zinc,
12 | 750: '#323238',
13 | 850: '#1f1f21',
14 | 950: '#101012',
15 | },
16 | },
17 |
18 | maxWidth: theme => ({
19 | ...theme('width'),
20 | }),
21 |
22 | maxHeight: theme => ({
23 | ...theme('height'),
24 | }),
25 |
26 | minWidth: theme => ({
27 | ...theme('width'),
28 | }),
29 |
30 | minHeight: theme => ({
31 | ...theme('height'),
32 | }),
33 |
34 | screens: Object.keys(defaultTheme.screens).reduce((obj, key) => {
35 | const [rawMin] = defaultTheme.screens[key].split('px')
36 | const max = parseInt(rawMin) - 1
37 | obj[`!${key}`] = { max: `${max}px` }
38 | return obj
39 | }, {}),
40 |
41 | borderRadius: {
42 | sm: '0.25rem',
43 | DEFAULT: '0.375rem',
44 | md: '0.5rem',
45 | lg: '0.75rem',
46 | xl: '1rem',
47 | '2xl': '1.5rem',
48 | '3xl': '2rem',
49 | },
50 |
51 | cursor: {
52 | 'ew-resize': 'ew-resize',
53 | 'ns-resize': 'ns-resize',
54 | 'cursor-not-allowed': 'cursor-not-allowed',
55 | },
56 |
57 | transitionProperty: {
58 | border: 'border',
59 | },
60 | },
61 | },
62 | content: [
63 | './docs/**/*.{vue,js,ts,jsx,tsx,md}',
64 | './docs/.vitepress/**/*.{vue,js,ts,jsx,tsx,md}',
65 | ],
66 | darkMode: 'class', // or 'media' or 'class'
67 | corePlugins: {
68 | preflight: false,
69 | },
70 | plugins: [],
71 | }
72 |
--------------------------------------------------------------------------------
/docs/.vitepress/theme/style/index.pcss:
--------------------------------------------------------------------------------
1 | @tailwind base;
2 | @tailwind components;
3 |
4 | button {
5 | font-size: inherit;
6 | }
7 |
8 | @tailwind utilities;
9 |
10 | .btn {
11 | @apply border border-solid border-gray-200 rounded hover:bg-primary-100 hover:border-primary-200 !text-primary-500 cursor-pointer hover:no-underline;
12 | .dark & {
13 | @apply bg-gray-850 border-gray-700 hover:bg-primary-900 hover:border-primary-600;
14 | }
15 | }
16 |
17 | .btn-blue {
18 | @apply border border-solid border-gray-200 rounded hover:bg-blue-100 hover:border-blue-200 !text-blue-500 cursor-pointer hover:no-underline;
19 | .dark & {
20 | @apply bg-gray-850 border-gray-700 hover:bg-blue-900 hover:border-blue-600;
21 | }
22 | }
23 |
24 | .btn-flat {
25 | @apply hover:no-underline rounded hover:bg-primary-100 border border-solid border-transparent hover:border-primary-200;
26 | .dark & {
27 | @apply hover:bg-primary-900 hover:border-primary-600;
28 | }
29 | }
30 |
31 | .home-hero {
32 | figure {
33 | .image {
34 | max-height: 140px;
35 | }
36 | }
37 | }
38 |
39 | .home-features {
40 | .wrapper {
41 | @apply pt-0 border-t-0 !important;
42 | }
43 | }
44 |
45 | .v-popper--theme-dropdown {
46 | .dark & {
47 | .v-popper__inner {
48 | @apply bg-gray-850 border-gray-750 text-gray-100;
49 | }
50 |
51 | .v-popper__arrow-inner {
52 | @apply border-gray-850;
53 | }
54 |
55 | .v-popper__arrow-outer {
56 | @apply border-gray-750;
57 | }
58 | }
59 |
60 | &.v-popper__popper--show-from .v-popper__wrapper {
61 | transform: scale(.75);
62 | }
63 |
64 | &.v-popper__popper--show-to .v-popper__wrapper {
65 | transform: none;
66 | transition: transform .15s cubic-bezier(0, 1, .5, 1);
67 | }
68 | }
69 |
70 | table {
71 | .dark & {
72 | tr, td, th {
73 | border-color: var(--c-border);
74 | }
75 |
76 | tr:nth-child(2n) {
77 | background-color: #1a1e23;
78 | }
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/src/routes/definition/get.definition.route.js:
--------------------------------------------------------------------------------
1 | const express = require('express');
2 | const router = express.Router();
3 | const path = require('path');
4 |
5 | const Utils = require('../../utils/utils');
6 | const errors = require('../../utils/errors');
7 |
8 | /**
9 | * Get definition
10 | */
11 |
12 | const getDefinition = router.get(
13 | '/:version/entries/:language/:word',
14 | async (req, res) => {
15 | let { word, language, version } = req.params;
16 | word = decodeURIComponent(word).trim().toLocaleLowerCase();
17 |
18 | if (!word || !language || !version) {
19 | return Utils.handleError.call(res, new errors.NoDefinitionsFound());
20 | }
21 |
22 | if (!Utils.isVersionSupported(version)) {
23 | return Utils.handleError.call(res, new errors.NoDefinitionsFound());
24 | }
25 |
26 | if (language === 'en_US' || language === 'en_GB' || language === 'en') {
27 | language = 'english';
28 | }
29 |
30 | if (
31 | language === 'vi_VN' ||
32 | language === 'vietnamese' ||
33 | language === 'vn' ||
34 | language === 'vi'
35 | ) {
36 | language = 'english-vietnamese';
37 | }
38 |
39 | language = language.toLowerCase();
40 |
41 | if (!Utils.isLanguageSupported(language)) {
42 | return Utils.handleError.call(res, new errors.NoDefinitionsFound());
43 | }
44 |
45 | try {
46 | if (language !== 'english') {
47 | throw new errors.NoDefinitionsFound({
48 | reason: 'Only English is supported at the moment.',
49 | });
50 | }
51 |
52 | const meaning = req.dictionary.get(word);
53 |
54 | res.set('Content-Type', 'application/json');
55 | res.set('Access-Control-Allow-Origin', '*');
56 |
57 | if (!meaning) {
58 | throw new errors.NoDefinitionsFound();
59 | }
60 |
61 | return res.status(200).send(meaning);
62 | } catch (error) {
63 | console.log('error', error);
64 | throw new errors.NoDefinitionsFound({
65 | reason: 'Website returned 404.',
66 | });
67 | }
68 | }
69 | );
70 |
71 | module.exports = { getDefinition };
72 |
--------------------------------------------------------------------------------
/src/utils/errors.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | NoDefinitionsFound: class NoDefinitionsFound extends Error {
3 | constructor(additionalInfo = {}) {
4 | super();
5 |
6 | this.name = 'NoDefinitionsFound';
7 | this.title = 'No Definitions Found';
8 | this.message =
9 | "Sorry pal, we couldn't find definitions for the word you were looking for.";
10 | this.resolution =
11 | 'You can try the search again at later time or head to the web instead.';
12 | this.additionalInfo = additionalInfo;
13 | this.requestType = 'notFound';
14 | }
15 | },
16 |
17 | NoPronunciationFound: class NoPronunciation extends Error {
18 | constructor(additionalInfo = {}) {
19 | super();
20 |
21 | this.name = 'NoPronunciation';
22 | this.title = 'No Pronunciation Found';
23 | this.message =
24 | "Sorry pal, we couldn't find pronunciation for the word you were looking for.";
25 | this.resolution =
26 | 'You can try the search again at later time or head to the web instead.';
27 | this.additionalInfo = additionalInfo;
28 | this.requestType = 'notFound';
29 | }
30 | },
31 |
32 | RateLimitError: class RateLimitError extends Error {
33 | constructor(additionalInfo = {}) {
34 | super();
35 |
36 | this.name = 'RateLimitError';
37 | this.title = 'API Rate Limit Exceeded';
38 | this.message =
39 | 'Sorry pal, you were just rate limited by the upstream server.';
40 | this.resolution =
41 | 'You can try the search again at later time or head to the web instead.';
42 | this.additionalInfo = additionalInfo;
43 | this.requestType = 'rateLimit';
44 | }
45 | },
46 |
47 | UnexpectedError: class UnexpectedError extends Error {
48 | constructor(additionalInfo = {}) {
49 | super();
50 |
51 | this.name = 'UnexpectedError';
52 | this.title = 'Something Went Wrong';
53 | this.message =
54 | 'Sorry pal, something went wrong, and its not your fault.';
55 | this.resolution =
56 | 'You can try the search again at later time or head to the web instead.';
57 | this.additionalInfo = additionalInfo;
58 | this.requestType = 'serverError';
59 | }
60 | },
61 |
62 | BadHTTPResponse: class BadHTTPResponse extends Error {
63 | constructor(additionalInfo = {}) {
64 | super();
65 |
66 | this.name = 'BadHTTPResponse';
67 | this.title = 'Upstream Server Failed';
68 | this.message = 'Sorry pal, upstream servers failed us.';
69 | this.resolution =
70 | 'You can try the search again at later time or head to the web instead.';
71 | this.additionalInfo = additionalInfo;
72 | this.requestType = 'serverError';
73 | }
74 | },
75 | };
76 |
--------------------------------------------------------------------------------
/docs/.vitepress/config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | title: 'Free Dictionary API',
3 | description: 'Fast stories powered by Vite',
4 | head: [
5 | ['meta', { property: 'og:title', content: 'Free Dictionary API' }],
6 | ['meta', { property: 'og:site_name', content: 'Free Dictionary API' }],
7 | ['meta', { property: 'og:type', content: 'website' }],
8 | [
9 | 'meta',
10 | {
11 | property: 'og:description',
12 | content: 'Fast stories powered by Vite',
13 | },
14 | ],
15 | [
16 | 'meta',
17 | { property: 'og:url', content: 'https://freedictionaryapi.dev/' },
18 | ],
19 | [
20 | 'meta',
21 | {
22 | property: 'og:image',
23 | content: 'https://freedictionaryapi.dev/opengraph.png',
24 | },
25 | ],
26 | ['meta', { property: 'og:image:width', content: '600' }],
27 | ['meta', { property: 'og:image:height', content: '315' }],
28 | ['meta', { name: 'twitter:card', content: 'summary_large_image' }],
29 | ['meta', { name: 'twitter:site', content: '@ngocsangyem' }],
30 | ],
31 |
32 | lastUpdated: true,
33 |
34 | themeConfig: {
35 | logo: '/logo.svg',
36 |
37 | editLink: {
38 | repo: 'ngocsangyem/freedictionaryapi',
39 | branch: 'main',
40 | dir: 'docs',
41 | text: 'Edit this page on GitHub',
42 | pattern: 'https://github.com/ngocsangyem/freedictionary/edit/main/docs'
43 | },
44 |
45 | footer: {
46 | message: 'Released under the MIT License.',
47 | copyright: 'Copyright © 2022-present Sang Nguyen',
48 | },
49 |
50 | nav: [
51 | { text: 'API Reference', link: '/reference/definition' },
52 | {
53 | text: 'Changelog',
54 | link: 'https://github.com/ngocsangyem/freedictionaryapi/blob/main/CHANGELOG.md',
55 | },
56 | {
57 | text: 'Sponsor',
58 | items: [
59 | {
60 | text: 'Sang Nguyen',
61 | link: 'https://github.com/ngocsangyem',
62 | },
63 | ],
64 | },
65 | ],
66 |
67 | socialLinks: [
68 | {
69 | icon: 'github',
70 | link: 'https://github.com/ngocsangyem/freedictionaryapi',
71 | },
72 | { icon: 'twitter', link: 'https://twitter.com/ngocsangyem' },
73 | ],
74 |
75 | sidebar: {
76 | '/reference/': [
77 | {
78 | text: 'API Reference',
79 | items: [
80 | {
81 | text: 'Definition',
82 | link: '/reference/definition',
83 | },
84 | {
85 | text: 'Pronunciation',
86 | link: '/reference/pronunciation',
87 | },
88 | ],
89 | },
90 | ],
91 | '/guide/': [
92 | {
93 | text: 'Guide',
94 | collapsible: true,
95 | items: [],
96 | },
97 | ],
98 | },
99 | },
100 | };
101 |
--------------------------------------------------------------------------------
/docs/.vitepress/theme/MeetTeam.vue:
--------------------------------------------------------------------------------
1 |
30 |
31 |
32 |
90 |
91 |
--------------------------------------------------------------------------------
/docs/public/logo.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
77 |
--------------------------------------------------------------------------------
/src/utils/utils.js:
--------------------------------------------------------------------------------
1 | const fetch = require('node-fetch');
2 | const cheerio = require('cheerio');
3 | const errors = require('./errors');
4 | const { JSDOM } = require('jsdom');
5 | const { DOMParser } = new JSDOM().window;
6 |
7 | const SUPPORTED_VERSIONS = new Set(['v1', 'v2']);
8 | const SUPPORTED_LANGUAGES = new Set([
9 | // 'hi', // Hindi
10 | 'en', // English (US)
11 | 'english', // English (US)
12 | 'en-uk', // English (UK)
13 | // 'es', // Spanish
14 | // 'fr', // French
15 | // 'ja', // Japanese
16 | // 'cs', // Czech
17 | // 'nl', // Dutch
18 | // 'sk', // Slovak
19 | // 'ru', // Russian
20 | // 'de', // German
21 | // 'it', // Italian
22 | // 'ko', // Korean
23 | // 'pt-BR', // Brazilian Portuguese
24 | // 'ar', // Arabic
25 | // 'tr', // Turkish
26 | 'vi', // Vietnamese
27 | 'english-vietnamese', // Vietnamese
28 | ]);
29 |
30 | const Utils = {
31 | async getHTML(url) {
32 | if (typeof url !== 'string') {
33 | throw new errors.UnexpectedError({
34 | reason: `The url type must be a string, received "${typeof url}"!`,
35 | });
36 | }
37 |
38 | try {
39 | const res = await fetch(url, {
40 | redirect: 'follow',
41 | cache: 'force-cache',
42 | });
43 | if (!res.ok) return '';
44 | const html = await res.text();
45 | return { html, url: res.url, isRedirected: res.redirected };
46 | } catch (e) {
47 | console.error('Error fetching HTML:', e);
48 | return '';
49 | }
50 | },
51 |
52 | loadHTML(html) {
53 | if (typeof html !== 'string')
54 | throw new errors.UnexpectedError({
55 | reason: `The html type must be a string, received "${typeof html}"!`,
56 | });
57 | return cheerio.load(html);
58 | },
59 |
60 | removeLineBreak(str) {
61 | if (typeof str !== 'string') return '';
62 | return str.replace(/\s+/g, ' ').replace(':', '').trim();
63 | },
64 |
65 | logEvent(word, language, message, additionalInfo = {}) {
66 | console.log({
67 | Word: word,
68 | Language: language,
69 | Message: message,
70 | AdditionalInfo: JSON.stringify(additionalInfo),
71 | });
72 | },
73 |
74 | isLanguageSupported(language) {
75 | return SUPPORTED_LANGUAGES.has(language);
76 | },
77 |
78 | isVersionSupported(version) {
79 | return SUPPORTED_VERSIONS.has(version);
80 | },
81 |
82 | cleanText(text) {
83 | if (!text) {
84 | return text;
85 | }
86 | return new DOMParser().parseFromString(text, 'text/html').body.textContent;
87 | },
88 |
89 | getUrlParameter(url, name) {
90 | name = name.replace(/[\[]/, '\\[').replace(/[\]]/, '\\]');
91 | const regex = new RegExp('[\\?&]' + name + '=([^]*)');
92 | const results = regex.exec(url);
93 | return results === null ? '' : decodeURIComponent(results[1].replace(/\+/g, ' '));
94 | },
95 |
96 | handleError(err = {}) {
97 | if (!errors.requestType) {
98 | err = new errors.UnexpectedError({ original_error: err });
99 | }
100 | const { requestType, title, message, resolution } = err;
101 | const status = { notFound: 404, rateLimit: 429, serverError: 500 }[requestType];
102 | const body = JSON.stringify({ title, message, resolution });
103 | console.error('Error:', body);
104 | return { status, body };
105 | },
106 | };
107 |
108 | module.exports = Utils;
109 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ### macOS ###
2 | # General
3 | .DS_Store
4 | .AppleDouble
5 | .LSOverride
6 |
7 | # Icon must end with two \r
8 | Icon
9 |
10 |
11 | # Thumbnails
12 | ._*
13 |
14 | # Files that might appear in the root of a volume
15 | .DocumentRevisions-V100
16 | .fseventsd
17 | .Spotlight-V100
18 | .TemporaryItems
19 | .Trashes
20 | .VolumeIcon.icns
21 | .com.apple.timemachine.donotpresent
22 |
23 | # Directories potentially created on remote AFP share
24 | .AppleDB
25 | .AppleDesktop
26 | Network Trash Folder
27 | Temporary Items
28 | .apdisk
29 |
30 | ### Node ###
31 | # Logs
32 | logs
33 | *.log
34 | npm-debug.log*
35 | yarn-debug.log*
36 | yarn-error.log*
37 | lerna-debug.log*
38 | .pnpm-debug.log*
39 |
40 | # Diagnostic reports (https://nodejs.org/api/report.html)
41 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
42 |
43 | # Runtime data
44 | pids
45 | *.pid
46 | *.seed
47 | *.pid.lock
48 |
49 | # Directory for instrumented libs generated by jscoverage/JSCover
50 | lib-cov
51 |
52 | # Coverage directory used by tools like istanbul
53 | coverage
54 | *.lcov
55 |
56 | # nyc test coverage
57 | .nyc_output
58 |
59 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
60 | .grunt
61 |
62 | # Bower dependency directory (https://bower.io/)
63 | bower_components
64 |
65 | # node-waf configuration
66 | .lock-wscript
67 |
68 | # Compiled binary addons (https://nodejs.org/api/addons.html)
69 | build/Release
70 |
71 | # Dependency directories
72 | node_modules/
73 | jspm_packages/
74 |
75 | # Snowpack dependency directory (https://snowpack.dev/)
76 | web_modules/
77 |
78 | # TypeScript cache
79 | *.tsbuildinfo
80 |
81 | # Optional npm cache directory
82 | .npm
83 |
84 | # Optional eslint cache
85 | .eslintcache
86 |
87 | # Microbundle cache
88 | .rpt2_cache/
89 | .rts2_cache_cjs/
90 | .rts2_cache_es/
91 | .rts2_cache_umd/
92 |
93 | # Optional REPL history
94 | .node_repl_history
95 |
96 | # Output of 'npm pack'
97 | *.tgz
98 |
99 | # Yarn Integrity file
100 | .yarn-integrity
101 |
102 | # dotenv environment variables file
103 | .env
104 | .env.test
105 | .env.production
106 |
107 | # parcel-bundler cache (https://parceljs.org/)
108 | .cache
109 | .parcel-cache
110 |
111 | # Next.js build output
112 | .next
113 | out
114 |
115 | # Nuxt.js build / generate output
116 | .nuxt
117 | dist
118 |
119 | # Gatsby files
120 | .cache/
121 | # Comment in the public line in if your project uses Gatsby and not Next.js
122 | # https://nextjs.org/blog/next-9-1#public-directory-support
123 | # public
124 |
125 | # vuepress build output
126 | .vuepress/dist
127 |
128 | # Serverless directories
129 | .serverless/
130 |
131 | # FuseBox cache
132 | .fusebox/
133 |
134 | # DynamoDB Local files
135 | .dynamodb/
136 |
137 | # TernJS port file
138 | .tern-port
139 |
140 | # Stores VSCode versions used for testing VSCode extensions
141 | .vscode-test
142 |
143 | # yarn v2
144 | .yarn/cache
145 | .yarn/unplugged
146 | .yarn/build-state.yml
147 | .yarn/install-state.gz
148 | .pnp.*
149 |
150 | ### VisualStudioCode ###
151 | .vscode/*
152 | !.vscode/settings.json
153 | !.vscode/tasks.json
154 | !.vscode/launch.json
155 | !.vscode/extensions.json
156 | *.code-workspace
157 |
158 | # Local History for Visual Studio Code
159 | .history/
160 |
161 | ### VisualStudioCode Patch ###
162 | # Ignore all local history of files
163 | .history
164 | .ionide
165 |
166 |
167 | .vercel
168 | .elasticbeanstalk/
169 |
170 | # Elastic Beanstalk Files
171 | .elasticbeanstalk/*
172 | !.elasticbeanstalk/*.cfg.yml
173 | !.elasticbeanstalk/*.global.yml
174 | .env
175 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Welcome to freedictionaryapi 👋
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | > Inspired by [freeDictionaryAPI](https://github.com/meetDeveloper/freeDictionaryAPI)
19 |
20 | ### 🏠 [Homepage](https://github.com/ngocsangyem/freedictionaryapi#readme)
21 |
22 | ### ✨ [Demo](https://api.freedictionary.dev/)
23 |
24 | ### Introduction
25 |
26 | - More than 700k+ Definitions of word
27 | - [freedictionaryapi](https://github.com/ngocsangyem/freedictionaryapi) base on open source Wiktionary.
28 | - It is a simple and easy to use API to get the definition of a word.
29 | - It is a free and open source project.
30 |
31 | ## Development
32 |
33 | ```sh
34 | npm install
35 | ```
36 |
37 | ```sh
38 | npm start
39 | ```
40 |
41 | ## Usage
42 |
43 | ### Definitions
44 |
45 | ```sh
46 | https://api.freedictionary.dev/api/{version}/entries/en/{word}
47 | ```
48 |
49 | #### Type Definitions
50 |
51 | ```typescript
52 | interface IPhonetic {
53 | ipa: string;
54 | audio: string;
55 | type: string;
56 | }
57 |
58 | interface IForm {
59 | text: string;
60 | type: string;
61 | }
62 |
63 | interface IAntonym {
64 | text: string;
65 | meaning: string
66 | }
67 |
68 | interface ISynonym {
69 | text: string;
70 | meaning: string
71 | }
72 |
73 | interface IMeaning {
74 | definition: string;
75 | examples: string[]
76 | antonyms?: IAntonym[] | null;
77 | synonyms?: ISynonym[] | null;
78 | }
79 |
80 | interface IWord {
81 | word: string;
82 | partOfSpeech: string;
83 | phonetics?: IPhonetic[];
84 | meanings: IMeaning[];
85 | forms?: IForm[];
86 | }
87 | ```
88 |
89 | #### Example
90 |
91 | ```sh
92 | https://api.freedictionary.dev/api/v1/entries/en/go
93 | ```
94 |
95 | You will get result
96 |
97 | ```json
98 | [
99 | {
100 | "word":"go",
101 | "partOfSpeech":"verb",
102 | "phonetics":[
103 | {
104 | "type":"uk",
105 | "audio":"https://upload.wikimedia.org/wikipedia/commons/transcoded/e/ef/En-uk-to_go.ogg/En-uk-to_go.ogg.mp3",
106 | "ipa":"/ɡəʊ/"
107 | },
108 | {
109 | "type":"us",
110 | "audio":"https://upload.wikimedia.org/wikipedia/commons/transcoded/0/0a/En-us-go.ogg/En-us-go.ogg.mp3",
111 | "ipa":"/ɡoʊ/"
112 | }
113 | ],
114 | "forms":[
115 | {
116 | "text":"goes",
117 | "type":"present singular third-person"
118 | },
119 | {
120 | "text":"going",
121 | "type":"participle present"
122 | },
123 | {
124 | "text":"went",
125 | "type":"past"
126 | }
127 | ],
128 | "meanings":[
129 | {
130 | "definition":"To move through space (especially to or through a place). (May be used of tangible things like people or cars, or intangible things like moods or information.)",
131 | "examples":[
132 | "She was so mad she wouldn't speak to me for quite a spell, but at last I coaxed her into going up to Miss Emmeline's room and fetching down a tintype of the missing Deacon man.",
133 | ],
134 | "antonyms":[
135 | {
136 | "text":"freeze",
137 | "meaning":""
138 | },
139 | {
140 | "text":"halt",
141 | "meaning":""
142 | }
143 | ],
144 | "synonyms":[
145 | {
146 | "text":"move",
147 | "meaning":""
148 | },
149 | {
150 | "text":"fare",
151 | "meaning":""
152 | }
153 | ]
154 | }
155 | ]
156 | }
157 | ]
158 | ```
159 |
160 | ### Pronunciation
161 |
162 | ```sh
163 | https://api.freedictionary.dev/api/{version}/pronunciation/en/{word}
164 | ```
165 |
166 | #### Type Definitions
167 |
168 | ```typescript
169 | interface IPhonetic {
170 | type: string;
171 | audio: string;
172 | }
173 |
174 | interface IPronunciation {
175 | word: string;
176 | phonetics: IPhonetic[];
177 | }
178 | ```
179 |
180 | #### Example
181 |
182 | ```sh
183 | https://api.freedictionary.dev/api/v1/entries/en/go
184 | ```
185 |
186 | You will get result
187 |
188 | ```json
189 | {
190 | "word": "go",
191 | "phonetics": [
192 | {
193 | "type": "uk",
194 | "audio": "https://dictionary.cambridge.org/media/english/uk_pron/u/ukg/ukglu/ukglutt024.mp3"
195 | },
196 | {
197 | "type": "us",
198 | "audio": "https://dictionary.cambridge.org/media/english/us_pron/g/go_/go___/go.mp3"
199 | },
200 | {
201 | "type": "uk",
202 | "audio": "https://dictionary.cambridge.org/media/english/uk_pron/u/ukg/ukglu/ukglutt024.mp3"
203 | },
204 | {
205 | "type": "us",
206 | "audio": "https://dictionary.cambridge.org/media/english/us_pron/g/go_/go___/go.mp3"
207 | }
208 | ]
209 | }
210 | ```
211 |
212 | ## Note
213 |
214 | If you are using linguarobot, create `.env` and add linguarobot API key to it.
215 |
216 | ```
217 | API_KEY=xxxxx
218 | ```
219 |
220 | ## Todo
221 |
222 | - Performance query
223 | - Docs
224 | - Refactor code
225 |
226 | ## Author
227 |
228 | 👤 **ngocsangyem**
229 |
230 | - Website:
231 | - Twitter: [@ngocsangyem](https://twitter.com/ngocsangyem)
232 | - Github: [@ngocsangyem](https://github.com/ngocsangyem)
233 | - LinkedIn: [@ngocsangyem](https://linkedin.com/in/ngocsangyem)
234 |
235 | ## 🤝 Contributing
236 |
237 | Contributions, issues and feature requests are welcome!
Feel free to check [issues page](https://github.com/ngocsangyem/freedictionaryapi/issues). You can also take a look at the [contributing guide](https://github.com/ngocsangyem/freedictionaryapi/blob/master/CONTRIBUTING.md).
238 |
239 | ## Show your support
240 |
241 | Give a ⭐️ if this project helped you!
242 |
243 |
244 |
245 |
246 |
247 | ## 📝 License
248 |
249 | Copyright © 2022 [ngocsangyem](https://github.com/ngocsangyem).
250 | This project is [MIT](https://github.com/ngocsangyem/freedictionaryapi/blob/main/LICENSE) licensed.
251 |
--------------------------------------------------------------------------------
/docs/public/histoire+percy.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
160 |
--------------------------------------------------------------------------------