aboutsummaryrefslogtreecommitdiffhomepage
path: root/api/services/zmk/keymap.js
diff options
context:
space:
mode:
Diffstat (limited to 'api/services/zmk/keymap.js')
-rw-r--r--api/services/zmk/keymap.js50
1 files changed, 49 insertions, 1 deletions
diff --git a/api/services/zmk/keymap.js b/api/services/zmk/keymap.js
index a8837ea..4eafb88 100644
--- a/api/services/zmk/keymap.js
+++ b/api/services/zmk/keymap.js
@@ -9,6 +9,14 @@ const uniq = require('lodash/uniq')
const { renderTable } = require('./layout')
+class KeymapValidationError extends Error {
+ constructor (errors) {
+ super()
+ this.name = 'KeymapValidationError'
+ this.errors = errors
+ }
+}
+
const behaviours = JSON.parse(fs.readFileSync(path.join(__dirname, 'data/zmk-behaviors.json')))
const behavioursByBind = keyBy(behaviours, 'code')
@@ -145,8 +153,48 @@ function generateKeymapJSON (layout, keymap, encoded) {
return base.replace('"layers": null', `"layers": [\n ${layers.join(', ')}\n ]`)
}
+function validateKeymapJson(keymap) {
+ const errors = []
+
+ if (typeof keymap !== 'object' || keymap === null) {
+ errors.push('keymap.json root must be an object')
+ } else if (!Array.isArray(keymap.layers)) {
+ errors.push('keymap must include "layers" array')
+ } else {
+ for (let i in keymap.layers) {
+ const layer = keymap.layers[i]
+
+ if (!Array.isArray(layer)) {
+ errors.push(`Layer at layers[${i}] must be an array`)
+ } else {
+ for (let j in layer) {
+ const key = layer[j]
+ const keyPath = `layers[${i}][${j}]`
+
+ if (typeof key !== 'string') {
+ errors.push(`Value at "${keyPath}" must be a string`)
+ } else {
+ const bind = key.match(/^&.+?\b/)
+ if (!(bind && bind[0] in behavioursByBind)) {
+ errors.push(`Key bind at "${keyPath}" has invalid behaviour`)
+ }
+ }
+
+ // TODO: validate remaining bind parameters
+ }
+ }
+ }
+ }
+
+ if (errors.length) {
+ throw new KeymapValidationError(errors)
+ }
+}
+
module.exports = {
+ KeymapValidationError,
encodeKeymap,
parseKeymap,
- generateKeymap
+ generateKeymap,
+ validateKeymapJson
}