diff --git a/.gitignore b/.gitignore index 8d270cc..4f15e0b 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,6 @@ node_modules build installed-resources installed-data -.DS_Store \ No newline at end of file +.DS_Store +dist +assets \ No newline at end of file diff --git a/README.md b/README.md index d9c1f79..293a7a7 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,23 @@ # Phlexicon -Beginner-friendly phonetic keyboards for spoken & sign languages on desktop Mac, Windows, & Linux. +A catalog of [phonemes](https://en.wikipedia.org/wiki/Phoneme) in hundreds of languages, dialects, and lexicons—both [signed](https://www.signwriting.org/about/) and [spoken](https://en.wikipedia.org/wiki/International_Phonetic_Alphabet). -Type [phonemes](https://en.wikipedia.org/wiki/Phoneme) using the [International Phonetic Alphabet (IPA)](https://en.wikipedia.org/wiki/International_Phonetic_Alphabet) -for spoken languages and [SignWriting](https://www.signwriting.org/about/) for sign languages. -Choose from a list of phonemes used by a particular dialect or optionally, all phonemes in the IPA or SignWriting. +![Demo of Phlexicon app](docs/demo.gif) -The application is still under development and is only available for developers to build from scratch. -The [user guide](https://mxskylar.github.io/phlexicon/) will be updated when Phlexicon is available for installation. +See the [user guide](https://mxskylar.github.io/phlexicon/) for details about the app. +Read the reast of this README for technical details. > Phlexicon would be nothing without the open source data and frameworks it depends on. > Read more about those [here](https://mxskylar.github.io/phlexicon/attribution). +## Install + +Download the [latest release](https://github.com/mxskylar/phlexicon/releases/latest) for your operating system: + +- **macOS:** If your Mac uses an M1 chip, download an `arm64` file. Download either a `zip` or `dmg` file. +- **Windows:** Download the `exe` installer. +- **Linux:** Download an `rpm`, `deb`, `AppImage`, `pacman` file. + ## Development Phlexicon is an [Electron](https://www.electronjs.org/) app built with [Node](https://nodejs.org/) `v23.10.0`. @@ -103,10 +109,58 @@ npm run compile-react --- +Creates the database from scratch, inserts data, transpiles Typescript into JavaScript, then bundles the application with [Webpack](https://webpack.js.org/). + +```bash +npm run build +``` + +*Deletes cache?* **Yes**, deletes the bundle for the previous version of the app, if it exists, then re-creates it. + +--- + Launches the Electron application. ```bash npm run electron ``` -*Deletes cache?* **No**, launches the app using its existing bundle. \ No newline at end of file +*Deletes cache?* **No**, launches the app using its existing bundle. + +--- + +Packages app distribution for macOS. Only works when run on macOS. + +```bash +npm run dist-mac +``` + +*Deletes cache?* **Partially**, replaces files for previous app macOS distribution, if they exist. + +--- + +Packages app distribution for Windows. + +```bash +./electron-builder-docker win +npm run dist-win +``` + +These commands may give the following, expected error while still succeeding to package the app for Windows. + +``` +0024:err:environ:run_wineboot failed to start wineboot 1 +``` + +*Deletes cache?* **Partially**, replaces files for previous app Windows distributions, if they exist. + +--- + +Packages app distribution for Linux. + +```bash +./electron-builder-docker linux +npm run dist-linux +``` + +*Deletes cache?* **Partially**, replaces files for previous app Linux distributions, if they exist. \ No newline at end of file diff --git a/ci/app/init.ts b/ci/app/init.ts index 20f5730..939eb53 100644 --- a/ci/app/init.ts +++ b/ci/app/init.ts @@ -1,5 +1,5 @@ import * as fs from 'fs'; -import { BUILD_DIR, DATABASE_FILE_PATH } from '../../src/build-constants'; +import { ASSETS_DIR, BUILD_DIR, DATABASE_RELATIVE_FILE_PATH } from '../../src/build-constants'; import { Database } from '../../src/db/database'; import { CONSONANTS_TABLE, @@ -32,8 +32,9 @@ import { SpokenDialectParser } from './spoken/spoken-dialect-parser'; import { SignWritingFontParser } from './sign/sign-writing-font-parser'; import { SignPhonemeParser } from './sign/sign-phoneme-parser'; -// STEP 1: Prep the build directory +// STEP 1: Prep the build & assets directories recreateDirectory(BUILD_DIR); +recreateDirectory(ASSETS_DIR); // Installed Resources console.log(`Copying contents of ${INSTALLED_RESOURCES_DIR} to ${BUILD_DIR}`); @@ -45,8 +46,8 @@ console.log(`Copying contents of ${CUSTOM_RESOURCES_DIR} to ${BUILD_DIR}`); fs.cpSync(CUSTOM_RESOURCES_DIR, BUILD_DIR, {recursive: true}); // Database -console.log(`Creating database: ${DATABASE_FILE_PATH}`); -const db = new Database(DATABASE_FILE_PATH); +console.log(`Creating database: ${DATABASE_RELATIVE_FILE_PATH}`); +const db = new Database(DATABASE_RELATIVE_FILE_PATH); // STEP 2: Insert data into the database // SPOKEN DIALECTS diff --git a/ci/utils.ts b/ci/utils.ts index e4ebeef..537ab61 100644 --- a/ci/utils.ts +++ b/ci/utils.ts @@ -21,6 +21,6 @@ export const recreateDirectory = (path: string) => { recursive: true, force: true }); - fs.mkdirSync(path); } + fs.mkdirSync(path); }; \ No newline at end of file diff --git a/custom-resources/app.css b/custom-resources/app.css index 1a793b0..c4694ca 100644 --- a/custom-resources/app.css +++ b/custom-resources/app.css @@ -1,3 +1,18 @@ body { height: 100vh; +} + +#navigation-bar .navbar-brand { + font-family: 'Merriweather', serif; +} + +footer { + position: fixed; + left: 0; + bottom: 0; + background: #ffffff; + padding: 5px; + text-align: center; + font-size: 10px; + width: 100%; } \ No newline at end of file diff --git a/custom-resources/icon.png b/custom-resources/icon.png new file mode 100644 index 0000000..a6ea4c8 Binary files /dev/null and b/custom-resources/icon.png differ diff --git a/custom-resources/logo.svg b/custom-resources/logo.svg deleted file mode 100644 index 5a24b2b..0000000 --- a/custom-resources/logo.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/docs/README.md b/docs/README.md index 1566753..31ad808 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,15 +1,9 @@ -# Phlexicon +![Demo of Phlexicon app](demo.gif) -Beginner-friendly phonetic keyboards for spoken & sign languages on desktop Mac, Windows, & Linux. +## Install -Type [phonemes](https://en.wikipedia.org/wiki/Phoneme) using the [International Phonetic Alphabet (IPA)](https://en.wikipedia.org/wiki/International_Phonetic_Alphabet) -for spoken languages and [SignWriting](https://www.signwriting.org/about/) for sign languages. -Choose from a list of phonemes used by a particular dialect or optionally, all phonemes in the IPA or SignWriting. +Download the [latest release](https://github.com/mxskylar/phlexicon/releases/latest) for your operating system: -The application is still under development and is only available for developers to [build from scratch](https://github.com/mxskylar/phlexicon). -This user guide will be updated when Phlexicon is available for installation. - ---- - -Phlexicon would be nothing without the open source data and frameworks it depends on. -Read more about those [here](./attribution.md). \ No newline at end of file +- **macOS:** If your Mac uses an M1 chip, download an `arm64` file. Download either a `zip` or `dmg` file. +- **Windows:** Download the `exe` installer. +- **Linux:** Download an `rpm`, `deb`, `AppImage`, `pacman` file. \ No newline at end of file diff --git a/docs/_config.yml b/docs/_config.yml new file mode 100644 index 0000000..4a4e6d6 --- /dev/null +++ b/docs/_config.yml @@ -0,0 +1,6 @@ +# https://github.com/pages-themes/minimal +remote_theme: pages-themes/minimal@v0.2.0 +plugins: + - jekyll-remote-theme +title: Phlexicon +logo: "logo.png" \ No newline at end of file diff --git a/docs/_layouts/default.html b/docs/_layouts/default.html new file mode 100644 index 0000000..83aa3cd --- /dev/null +++ b/docs/_layouts/default.html @@ -0,0 +1,55 @@ + + + + + + + + +{% seo %} + + + + {% include head-custom.html %} + + +
+
+

{{ site.title }}

+ + {% if site.logo %} + + {% endif %} + +

+ A catalog of phonemes  + in hundreds of languages, dialects, and lexicons—both signed  + and spoken. +

+ + {% if site.github.is_project_page %} +

+ FAQ •  + Source Code •  + Download App +

+ {% endif %} +
+
+ + {{ content }} + +
+ +
+ + + \ No newline at end of file diff --git a/docs/attribution.md b/docs/attribution.md index fe12f71..dbc6f61 100644 --- a/docs/attribution.md +++ b/docs/attribution.md @@ -1,14 +1,17 @@ # Attribution Phlexicon would be nothing without the open source data and frameworks it depends on: -- [PBase](https://pbase.phon.chass.ncsu.edu/): Phonetic data for spoken languages -- [SignWriting](https://www.signwriting.org/) & [SignPuddle](https://signpuddle.org/): Writing system & phonetic data for sign languages -- [International SignWriting Alphabet 2010](https://www.signbank.org/iswa/): Font for writing phonemes in sign language -- [SIL ISO 639-3](https://iso639-3.sil.org/): Language names & identifiers -- [Charis SIL](https://software.sil.org/charis/): Font that supports International Phonentic Alphabet (IPA) symbols -- [Bootstrap](https://getbootstrap.com/): UI framework & [icons](https://icons.getbootstrap.com/) -- [Bootswatch](https://bootswatch.com/): Theme for Bootstrap -- [React](https://react.dev/): Framework for web development -- [Webpack](https://webpack.js.org/): JavaScript bundler -- [Electron](https://www.electronjs.org/): Framework to distribute web apps as desktop apps -- [Node.js](https://nodejs.org/): JavaScript development tool \ No newline at end of file + +| | Description | License | +|---|---|---| +| [PBase](https://pbase.phon.chass.ncsu.edu/) | Phonetic data for spoken languages | [Attribution-NonCommercial-ShareAlike 4.0 International](https://creativecommons.org/licenses/by-nc-sa/4.0/) | +| [International SignWriting Alphabet 2010](https://www.signbank.org/iswa/), [SignWriting](https://www.signwriting.org/), & [SignPuddle 3.0](https://signpuddle.org/) | Writing system, font, & phonetic data for sign languages | [Attribution-ShareAlike 3.0 Unported](https://creativecommons.org/licenses/by-sa/3.0/) | +| [SIL ISO 639-3](https://iso639-3.sil.org/) | Language names & identifiers | | +| [Charis SIL](https://software.sil.org/charis/) | Font that supports International Phonetic Alphabet (IPA) symbols | | +| [Bootstrap](https://getbootstrap.com/) | UI framework | [MIT](https://github.com/twbs/bootstrap/blob/main/LICENSE) | +| [Bootstrap Icons](https://icons.getbootstrap.com/) | Icon symbols | [MIT](https://github.com/twbs/icons/blob/main/LICENSE) | +| [Bootswatch](https://bootswatch.com/) | Theme for Bootstrap | [MIT](https://github.com/thomaspark/bootswatch/blob/v5/LICENSE) | +| [React](https://react.dev/) | Framework for web development | [MIT](https://github.com/facebook/react/blob/main/LICENSE) | +| [Webpack](https://webpack.js.org/) | JavaScript bundler | [MIT](https://github.com/webpack/webpack/blob/main/LICENSE) | +| [Electron](https://www.electronjs.org/) | Framework to distribute web apps as desktop apps | [MIT](https://github.com/electron/electron/blob/main/LICENSE) | +| [Node.js](https://nodejs.org/) | JavaScript development tool | [MIT](https://github.com/nodejs/node/blob/main/LICENSE) | \ No newline at end of file diff --git a/docs/demo.gif b/docs/demo.gif new file mode 100644 index 0000000..a230c39 Binary files /dev/null and b/docs/demo.gif differ diff --git a/docs/faq.md b/docs/faq.md new file mode 100644 index 0000000..6fe8231 --- /dev/null +++ b/docs/faq.md @@ -0,0 +1,31 @@ +# FAQ + +## Where does Phlexicon get its data? + +Spoken phonemes are pulled from [PBase](https://pbase.phon.chass.ncsu.edu/) +and the handshapes of sign languages are pulled from [SignPuddle 3.0](https://signpuddle.org/) +and the [one-dimensional font](https://www.sutton-signwriting.io/#fonts) for [SignWriting](https://www.signwriting.org/about). + +These datasets are normalized and parsed by Phlexicon. +Some granular data may be excluded or simplified, but the data in the app +should not meaningfully differ from original datasets, +unless there is a [bug](https://github.com/mxskylar/phlexicon/issues). + +See the [data parsing source code](https://github.com/mxskylar/phlexicon/blob/main/ci/app/init.ts) +to better understand how the original datasets are normalized, simplified, and parsed. + +## What fonts does Phlexicon use? + +The [Charis SIL font](https://software.sil.org/charis/) for spoken phonemes in the +[International Phonetic Alphabet (IPA)](https://en.wikipedia.org/wiki/International_Phonetic_Alphabet) +and the [one-dimensional font for SignWriting](https://www.sutton-signwriting.io/#fonts), +which can be used to write sign languages. + +Some characters in the IPA use are in a [Unicode private use area](https://en.wikipedia.org/wiki/Private_Use_Areas), +which means that the Charis font or another IPA-compatible font will need to be used to properly render them. +The SignWriting font must be used to render all symbols in the SignWriting system. + +## Where can I find symobls for movement, location, expressions, etc. in sign languages? + +For now, only oriented handshapes are supported by Phlexicon. The [SignMaker tool](https://www.signbank.org/signmaker/#) +can be used to find symbols for other phonemic parameters in the [SignWriting](https://www.signwriting.org/about) system. \ No newline at end of file diff --git a/docs/favicon.ico b/docs/favicon.ico new file mode 100644 index 0000000..9cd984f Binary files /dev/null and b/docs/favicon.ico differ diff --git a/docs/logo.png b/docs/logo.png new file mode 100644 index 0000000..a6ea4c8 Binary files /dev/null and b/docs/logo.png differ diff --git a/docs/style.css b/docs/style.css new file mode 100644 index 0000000..b55ffd1 --- /dev/null +++ b/docs/style.css @@ -0,0 +1,16 @@ +header, footer { + text-align: center; +} + +header h1 { + font-family: 'Merriweather', serif; + margin-bottom: 0; +} + +#logo { + height: 150px; +} + +a { + color: #2fa4e7; +} \ No newline at end of file diff --git a/electron-builder-docker b/electron-builder-docker new file mode 100755 index 0000000..cc6bd81 --- /dev/null +++ b/electron-builder-docker @@ -0,0 +1,18 @@ +#!/bin/bash +# https://www.electron.build/multi-platform-build#build-electron-app-using-docker-on-a-local-machine + +IMAGE_VERSION="" +if [[ "$1" == "win" ]]; then + IMAGE_VERSION=":wine" +fi + +set -o xtrace +docker run --rm -ti \ + --env-file <(env | grep -iE 'DEBUG|NODE_|ELECTRON_|YARN_|NPM_|CI|CIRCLE|TRAVIS_TAG|TRAVIS|TRAVIS_REPO_|TRAVIS_BUILD_|TRAVIS_BRANCH|TRAVIS_PULL_REQUEST_|APPVEYOR_|CSC_|GH_|GITHUB_|BT_|AWS_|STRIP|BUILD_') \ + --env ELECTRON_CACHE="/root/.cache/electron" \ + --env ELECTRON_BUILDER_CACHE="/root/.cache/electron-builder" \ + -v ${PWD}:/project \ + -v ${PWD##*/}-node-modules:/project/node_modules \ + -v ~/.cache/electron:/root/.cache/electron \ + -v ~/.cache/electron-builder:/root/.cache/electron-builder \ + electronuserland/builder$IMAGE_VERSION \ No newline at end of file diff --git a/package.json b/package.json index 509197c..70f8871 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "version": "1.0.0", "description": "A phonetic catalog for lexicons: Study a language. Document vocabulary. Analyze accents.", "main": "build/main.js", - "author": "https://github.com/mxskylar", + "author": "https://github.com/mxskylar <11418651+mxskylar@users.noreply.github.com>", "license": "GNU General Public License v3.0", "type": "module", "scripts": { @@ -13,9 +13,13 @@ "init-app": "npx tsx ci/app/init.ts", "compile-typescript": "tsc", "compile-react": "webpack --mode development --config webpack.react.config.js", + "build": "npm run init-app && npm run compile-typescript && npm run compile-react", "electron": "electron .", - "app": "npm run init-app && npm run compile-typescript && npm run compile-react && npm run electron", - "start": "npm install && npm run app" + "app": "npm run build && npm run electron", + "start": "npm install && npm run app", + "dist-mac": "electron-builder -m", + "dist-win": "electron-builder -w", + "dist-linux": "electron-builder -l" }, "dependencies": { "react": "^19.0.0", @@ -44,6 +48,59 @@ "webpack-cli": "^6.0.1", "opentype.js": "^1.3.4", "undici": "^7.8.0", - "psd": "^3.4.0" + "psd": "^3.4.0", + "electron-builder": "^26.0.12" + }, + "build": { + "appId": "phlexicon.app", + "productName": "Phlexicon", + "files": ["build/**/*"], + "extraResources": [ + { + "from": "./assets/", + "to": "assets/", + "filter": ["**/*"] + } + ], + "mac": { + "target": { + "target": "default", + "arch": [ + "arm64", + "x64" + ] + } + }, + "win": { + "target": { + "target": "nsis", + "arch": ["x64"] + }, + "signAndEditExecutable": false + }, + "nsis": { + "deleteAppDataOnUninstall": true + }, + "linux": { + "category": "Utility", + "target": [ + { + "target": "rpm", + "arch": ["x64"] + }, + { + "target": "deb", + "arch": ["x64"] + }, + { + "target": "AppImage", + "arch": ["x64"] + }, + { + "target": "pacman", + "arch": ["x64"] + } + ] + } } } diff --git a/publish b/publish new file mode 100755 index 0000000..ac7e6d7 --- /dev/null +++ b/publish @@ -0,0 +1,7 @@ +#!/bin/bash + +set -o xtrace + +npm run dist-mac +docker-compose up dist-win-linux +npm run publish \ No newline at end of file diff --git a/src/build-constants.ts b/src/build-constants.ts index 7b42678..8919425 100644 --- a/src/build-constants.ts +++ b/src/build-constants.ts @@ -1,3 +1,5 @@ export const BUILD_DIR = "build"; -export const DATABASE_FILE_PATH = `${BUILD_DIR}/phlexicon.db`; +export const ASSETS_DIR = "assets" +export const DATABASE_FILE_NAME = "phlexicon.db"; +export const DATABASE_RELATIVE_FILE_PATH = `${ASSETS_DIR}/${DATABASE_FILE_NAME}`; export const HAND_PICTURES_DIR = "hand-pictures"; \ No newline at end of file diff --git a/src/main.ts b/src/main.ts index 6786d20..0da0759 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,9 +1,12 @@ -import { app, BrowserWindow, ipcMain, shell, globalShortcut } from 'electron'; +import { app, BrowserWindow, globalShortcut, ipcMain, shell } from 'electron'; +import path from 'path'; import sqlite3 from 'sqlite3'; -import { BUILD_DIR, DATABASE_FILE_PATH } from './build-constants.ts'; +import { BUILD_DIR, DATABASE_RELATIVE_FILE_PATH } from './build-constants.ts'; const IS_DEV = !app.isPackaged; -const db = new sqlite3.Database(DATABASE_FILE_PATH); +const db = new sqlite3.Database( + IS_DEV ? DATABASE_RELATIVE_FILE_PATH : path.join(process.resourcesPath, DATABASE_RELATIVE_FILE_PATH) +); const createWindow = () => { const window = new BrowserWindow({ diff --git a/src/react-app.tsx b/src/react-app.tsx index f7ddb81..0b38ce9 100644 --- a/src/react-app.tsx +++ b/src/react-app.tsx @@ -99,6 +99,10 @@ class App extends React.Component { }/> }/> + ); }