Skip to content

Commit

Permalink
Merge branch 'main' into react-app
Browse files Browse the repository at this point in the history
  • Loading branch information
nickcoutsos committed Apr 29, 2022
2 parents 7f6b1db + 260f0c6 commit 94efab0
Show file tree
Hide file tree
Showing 18 changed files with 146 additions and 390 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ A browser app (plus NodeJS server) to edit ZMK keymaps. This is still in its
infancy and doesn't yet support parsing existing ZMK keymaps which limits some
kinds of functionality (mainly those involving custom/configured behaviours).

**Try it live!** Go to the [keymap-editor] and try it out with the built-in
[zmk-config-corne-demo] before setting up your own repo.

![Screenshot](editor-screenshot.png)

## Features
Expand Down
26 changes: 26 additions & 0 deletions api/config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
const process = require('process')
require('dotenv/config')

const PORT = process.env.PORT || 8080
const ENABLE_DEV_SERVER = process.env.ENABLE_DEV_SERVER
const ENABLE_GITHUB = process.env.ENABLE_GITHUB
const GITHUB_APP_NAME = process.env.GITHUB_APP_NAME
const GITHUB_APP_PRIVATE_KEY = process.env.GITHUB_APP_PRIVATE_KEY
const GITHUB_APP_ID = process.env.GITHUB_APP_ID
const GITHUB_CLIENT_ID = process.env.GITHUB_CLIENT_ID
const GITHUB_CLIENT_SECRET = process.env.GITHUB_CLIENT_SECRET
const GITHUB_OAUTH_CALLBACK_URL = process.env.GITHUB_OAUTH_CALLBACK_URL
const APP_BASE_URL = process.env.APP_BASE_URL

module.exports = {
PORT,
ENABLE_DEV_SERVER,
ENABLE_GITHUB,
GITHUB_APP_NAME,
GITHUB_APP_PRIVATE_KEY,
GITHUB_APP_ID,
GITHUB_CLIENT_ID,
GITHUB_CLIENT_SECRET,
GITHUB_OAUTH_CALLBACK_URL,
APP_BASE_URL
}
9 changes: 5 additions & 4 deletions api/index.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
require('dotenv/config')
const express = require('express')
const bodyParser = require('body-parser')
const cors = require('cors')
const morgan = require('morgan')

const config = require('./config')
const applicationInit = require('./routes/application')
const keyboards = require('./routes/keyboards')

Expand All @@ -14,14 +14,15 @@ app.use(cors({
origin: 'https://nickcoutsos.github.io'
}))

if (process.env.ENABLE_DEV_SERVER) {
if (config.ENABLE_DEV_SERVER) {
applicationInit(app)
}

app.use(morgan('dev'))
app.use(keyboards)
app.use('/github', require('./routes/github'))
app.get('/health', (req, res) => res.sendStatus(200))

app.use(keyboards)
config.ENABLE_GITHUB && app.use('/github', require('./routes/github'))

module.exports = app

6 changes: 4 additions & 2 deletions api/routes/application.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ const path = require('path')
const express = require('express')
const expressWs = require('express-ws')

const config = require('../config')

const appDir = path.join(__dirname, '..', '..', 'application')

function init (app) {
Expand All @@ -12,8 +14,8 @@ function init (app) {
cwd: appDir,
env: Object.assign({}, process.env, {
ENABLE_LOCAL: true,
ENABLE_GITHUB: true,
GITHUB_APP_NAME: process.env.GITHUB_APP_NAME,
ENABLE_GITHUB: config.ENABLE_GITHUB,
GITHUB_APP_NAME: config.GITHUB_APP_NAME,
API_BASE_URL: 'http://localhost:8080',
APP_BASE_URL: 'http://localhost:8080/application'
})
Expand Down
15 changes: 8 additions & 7 deletions api/services/github/auth.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@ const path = require('path')
const jwt = require('jsonwebtoken')

const api = require('./api')
const config = require('../../config')

const pemPath = path.join(__dirname, '..', '..', '..', 'private-key.pem')
const privateKey = process.env.GITHUB_APP_PRIVATE_KEY || fs.readFileSync(pemPath)
const privateKey = config.GITHUB_APP_PRIVATE_KEY || fs.readFileSync(pemPath)

function createAppToken () {
return jwt.sign({ iss: process.env.GITHUB_APP_ID }, privateKey, {
return jwt.sign({ iss: config.GITHUB_APP_ID }, privateKey, {
algorithm: 'RS256',
expiresIn: '10m'
})
Expand All @@ -24,16 +25,16 @@ function createOauthFlowUrl () {
const redirectUrl = new URL('https://github.com/login/oauth/authorize')

redirectUrl.search = new URLSearchParams({
client_id: process.env.GITHUB_CLIENT_ID,
redirect_uri: process.env.GITHUB_OAUTH_CALLBACK_URL,
client_id: config.GITHUB_CLIENT_ID,
redirect_uri: config.GITHUB_OAUTH_CALLBACK_URL,
state: 'foo'
}).toString()

return redirectUrl.toString()
}

function createOauthReturnUrl (token) {
const url = new URL(process.env.APP_BASE_URL)
const url = new URL(config.APP_BASE_URL)
url.search = new URLSearchParams({ token }).toString()
return url.toString()
}
Expand All @@ -46,8 +47,8 @@ function getOauthToken (code) {
Accept: 'application/json'
},
data: {
client_id: process.env.GITHUB_CLIENT_ID,
client_secret: process.env.GITHUB_CLIENT_SECRET,
client_id: config.GITHUB_CLIENT_ID,
client_secret: config.GITHUB_CLIENT_SECRET,
code
}
})
Expand Down
1 change: 0 additions & 1 deletion api/services/zmk/layout.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ function renderTable (layout, layer, opts={}) {
(row[i] || []).length
+ columnSeparator.length
+ (useQuotes ? 2 : 0) // wrapping with quotes adds 2 characters
+ (i === 6 ? 10 : 0) // sloppily add a little space between halves (right half starts at column 6)
))
))

Expand Down
57 changes: 57 additions & 0 deletions application/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Keymap Editor - Web Application

This is a single page application currently written in Vue (but I'm starting to
experiment with porting it to React) to integrate with the Keymap Editor API.

It handles keyboard selection and rendering of parsed keymap data into a visual
editor. This application is _aware_ of some of the particulars of ZMK, but it
receives key bindings already parsed into a tree of values and parameters.

## Building

The easiest way to use this is the [hosted version](https://nickcoutsos.github.io/keymap-editor).
The second easiest is locally, served up via the API itself (in the repo root,
run `npm run dev` and open `http://localhost:8080` in your browser).

If you must deploy this app to the web then you'll need to take care of building
it. This requires some configuration, as seen in the [config module](./config.js).

All configuration is provided via environment variables.

Variable | Description
------------------|-------------
`API_BASE_URL` | Fully qualified publicly accessible URL of the backend API.
`APP_BASE_URL` | Fully qualified publicly accessible URL of _this_ app.
`GITHUB_APP_NAME` | The app name (slug?) of the GitHub app integration (only required if using with GitHub).
`ENABLE_GITHUB` | Whether to enable fetching keyboard data from GitHub. Default is false, values `"1"`, `"on"`, `"yes"`, `"true"` are interpreted as `true`.
`ENABLE_LOCAL` | Whether to enable fetching keyboard data from locally. Default is false, values `"1"`, `"on"`, `"yes"`, `"true"` are interpreted as `true`.

_Note: choosing to use the GitHub integration in your own environment isn't a
matter of flipping a switch, you will need to set up your own app in GitHub and
configure your API accordingly._

With these set you can run the npm build script, e.g.

```bash
export API_BASE_URL=...
export APP_BASE_URL=...
export GITHUB_APP_NAME=...
export ENABLE_GITHUB=...
export ENABLE_LOCAL=...
npm run build
```

_(make sure you're in this directory, not the repository root!)_

This will have webpack produce bundles in the `dist/` directory which you can
deploy however you like.

### Deploying to GitHub Pages

On your GitHub repository's settings page, select _Pages_ in the sidebar. Pick a
branch you want to serve the app from (I use `pages`) and choose the `/ (root)`
directory. Check out that branch (I have another working repository locally for
this) locally, or make a new orphaned branch if such a branch doesn't exist, and
copy the contents of `dist/` to it. Commit and push to the GitHub remote.

If you're not familiar with this it's worth reading up on the [GitHub Pages docs](https://docs.github.com/en/pages).
2 changes: 1 addition & 1 deletion application/components/key-value.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
@click.stop="onSelect({ target: $event.target, codeIndex: index, code: value, param })"
>
<template v-if="source">
<span v-if="source.faIcon" class="['fa', `fa-${source.faIcon}" />
<span v-if="source.faIcon" :class="['fa', `fa-${source.faIcon}`]" />
<template v-else>{{source.symbol || source.code}}</template>
</template>
<template v-else>⦸</template>
Expand Down
6 changes: 4 additions & 2 deletions application/components/key.vue
Original file line number Diff line number Diff line change
Expand Up @@ -140,15 +140,17 @@ export default {
},
isSimple() {
const [first] = this.normalized.params
const icon = get(first, 'source.faIcon')
const symbol = get(first, 'source.symbol', get(first, 'source.code', ''))
const shortSymbol = symbol.length === 1
const shortSymbol = !!icon || symbol.length === 1
const singleParam = this.normalized.params.length === 1
return singleParam && shortSymbol
},
isComplex() {
const [first] = this.normalized.params
const icon = get(first, 'source.faIcon')
const symbol = get(first, 'source.symbol', get(first, 'value', ''))
const isLongSymbol = symbol.length > 4
const isLongSymbol = !icon && symbol.length > 4
const isMultiParam = this.behaviourParams.length > 1
const isNestedParam = get(first, 'params', []).length > 0
Expand Down
2 changes: 1 addition & 1 deletion application/components/keyboard-picker.vue
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export default {
sourceChoices,
source: onlySource || (
sourceChoices.find(source => source.id === selectedSource)
? selectedSource.id
? selectedSource
: null
)
}
Expand Down
Loading

0 comments on commit 94efab0

Please sign in to comment.