1
|
{"version":3,"file":"shared.764f9fe054eaa120c46e.js","mappings":"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","sources":["webpack:///../api/packages/devicetree/index.js","webpack:///../api/packages/devicetree/lib/formatters.js","webpack:///../api/packages/devicetree/lib/helpers/index.js","webpack:///../api/packages/devicetree/lib/helpers/nodes.js","webpack:///../api/packages/devicetree/lib/helpers/properties.js","webpack:///../api/packages/devicetree/lib/helpers/trees.js","webpack:///../api/packages/devicetree/lib/helpers/values.js","webpack:///../api/packages/devicetree/lib/node-collection.js","webpack:///../api/packages/devicetree/lib/parser.js","webpack:///../api/packages/keymap-editor-zmk-backend/lib/apply-keymap-changes.js","webpack:///../api/packages/keymap-editor-zmk-backend/lib/devicetree/bindings.js","webpack:///../api/packages/keymap-editor-zmk-backend/lib/devicetree/collections/behaviors.js","webpack:///../api/packages/keymap-editor-zmk-backend/lib/devicetree/collections/combos.js","webpack:///../api/packages/keymap-editor-zmk-backend/lib/devicetree/collections/layers.js","webpack:///../api/packages/keymap-editor-zmk-backend/lib/devicetree/collections/macros.js","webpack:///../api/packages/keymap-editor-zmk-backend/lib/devicetree/keymap-document.js","webpack:///../api/packages/keymap-editor-zmk-backend/lib/devicetree/sanity-checks.js","webpack:///../api/packages/keymap-editor-zmk-backend/lib/extract-keymap-data.js","webpack:///../api/packages/keymap-editor-zmk-backend/lib/keymap.js","webpack:///../api/packages/keymap-layout-tools/lib/render.js","webpack:///../api/packages/string-utils/index.js","webpack:///../api/packages/zmk-data/behaviors.js","webpack:///../api/packages/zmk-data/keycode-mappings.js","webpack:///../api/packages/zmk-data/keycodes.js","webpack:///../api/packages/zmk-data/parameters.js"],"sourcesContent":["module.exports = require('./lib/parser')\n","const {\n removeStartingWhitespace,\n removeTrailingWhitespace,\n reindent,\n dedent\n} = require('string-utils')\nconst { getLabeledItem, getNodeLabels } = require('./helpers/nodes')\n\nconst DEFAULT_INDENT = ' '\nconst DEFAULT_MULTILINE_INTEGER_CELLS_INDENT = 'keep'\n\nfunction isMultilineNode (node) {\n return node.text.indexOf('\\n') !== -1\n}\n\nfunction isMultilinePropertyNode (node) {\n return node?.type === 'property' && (\n node.namedChildren.length > 2 ||\n node.namedChildren.slice(1).some(isMultilineNode)\n )\n}\n\nfunction isInlineComment (node) {\n return (\n node.type === 'comment' &&\n node.previousSibling &&\n // Nodes for pre-processor directives include trailing newline characters.\n // For simplicity, a preproc cannot have an inline comment.\n node.previousSibling.type !== 'preproc_def' &&\n node.previousSibling.type !== 'preproc_function_def' &&\n node.previousSibling.type !== 'preproc_include' &&\n node.previousSibling.endPosition.row === node.startPosition.row\n )\n}\n\nfunction getNodeIndentation (node, tab) {\n return tab.repeat(getNodeDepth(node))\n}\n\nfunction getModelineConfiguration (tree) {\n return tree.rootNode.namedChildren.reduce((config, node) => {\n if (node.type === 'comment') {\n const contents = node.text.startsWith('//')\n ? node.text.slice(2).trim()\n : node.text.slice(2, -2).trim()\n\n for (const line of contents.split('\\n')) {\n const match = line.match(/dt-formatter:\\s*(\\w+)\\s*=\\s*(.+)$/)\n if (match) {\n const [key, jsonValue] = match.slice(1)\n try {\n const value = JSON.parse(jsonValue)\n config[key] = value\n } catch {}\n }\n }\n }\n\n return config\n }, {})\n}\n\n/**\n * Determine the depth of the node in the device tree\n *\n * A depth of 0 is anything at the document level -- this includes the \"/\" node\n *\n * @param {SyntaxNode} node any kind of syntax node\n * @returns {Integer} depth\n */\nfunction getNodeDepth (node) {\n let n = node\n let depth = 0\n const stop = node.tree.rootNode\n\n while ((n = n.parent) && n && n.id !== stop.id) {\n if (n.type !== 'labeled_item') {\n depth++\n }\n }\n\n return depth\n}\n\nfunction shouldIncludeBlank (nodeA, nodeB) {\n if (!nodeB) {\n return false\n }\n\n const sameType = nodeA.type === nodeB.type\n const isAdjacentDeviceTreeNode = sameType && nodeA.type === 'node'\n\n // TODO: this should probably just not insert whitespace around comments\n return (\n isAdjacentDeviceTreeNode ||\n isMultilinePropertyNode(nodeA) ||\n (!sameType && !isInlineComment(nodeB))\n )\n}\n\n/**\n * Apply formatting (indentation and whitespace) to a node and its descendents\n *\n * Indentation is based on the node's depth in the full tree (not just relative\n * to the supplied `node` parameter) and currently limited to 4-space tabs.\n *\n * The existing formatting of `integer_cells` nodes (ie, `bindings = <...>;`) is\n * considered sacred and 0 levels of indentation will be applied to those lines.\n * @param {SyntaxNode} node any node in the devicetree\n * @returns {String} the newly-formatted text for the syntax node\n */\nfunction formatNode (node, options = {}) {\n const { indent = DEFAULT_INDENT } = options\n\n if (node.type === 'labeled_item') {\n node = getLabeledItem(node)\n }\n\n const [identifier, ...children] = node.namedChildren\n const indentation = getNodeIndentation(node, indent)\n\n function formatChildren (children) {\n return children.reduce((lines, childNode, i, arr) => {\n // Merge inline comments onto the previous node's line.\n // This feels a bit hacky but it must be performed on the \"unformatted\"\n // comment syntax node (this check is also happening when the previous\n // node is being formatted and the extra blank line is being considered).\n if (isInlineComment(childNode)) {\n lines[lines.length - 1] += childNode.text\n return lines\n }\n lines.push(...formatNode(childNode, options))\n\n if (shouldIncludeBlank(childNode, children[i + 1])) {\n lines.push('')\n }\n\n return lines\n }, [])\n }\n\n switch (node.type) {\n case 'document':\n return [...formatChildren(node.namedChildren), '']\n\n case 'node':\n return [\n indentation + `${formatLabels(getNodeLabels(node))}${identifier.text}${getAddress(node)} {`,\n ...formatChildren(hasAddress(node) ? node.namedChildren.slice(2) : children),\n indentation + '};'\n ]\n\n case 'property':\n return formatPropertyNode(node, options)\n\n case 'preproc_include':\n case 'preproc_def':\n case 'preproc_function_def':\n return [node.text.trimEnd()]\n\n default:\n // this is mainly for things I didn't expect to see, but also includes\n // commonly used features like preproc_includes that technically work when\n // used inside nodes but aren't recognized by the grammar at the moment.\n // See: https://github.com/joelspadin/tree-sitter-devicetree/issues/1\n return [indentation + node.text]\n }\n}\n\nfunction hasAddress (node) {\n return !!node.childForFieldName('address')\n}\n\nfunction getAddress (node) {\n return hasAddress(node)\n // note address field doesn't give the actual value yet\n ? `@${node.namedChildren[1].text}`\n : ''\n}\n\nfunction formatLabels (labels) {\n return labels.map(text => `${text}: `).join('')\n}\n\nfunction formatPropertyNode (node, options = {}) {\n const {\n indent = DEFAULT_INDENT,\n multilineIntegerCellsIndent = DEFAULT_MULTILINE_INTEGER_CELLS_INDENT\n } = options\n\n const [identifier, ...children] = node.namedChildren\n const indentation = getNodeIndentation(node, indent)\n\n const noValue = children.length === 0\n const simpleValue = children.length === 1 && !isMultilineNode(children[0])\n const singleIntegerCell = children.length === 1 && children[0].type === 'integer_cells'\n const labels = formatLabels(getNodeLabels(node))\n\n // TODO: get smarter about different property value types\n if (noValue) return [indentation + node.text]\n\n if (simpleValue) {\n return [indentation + `${labels}${identifier.text} = ${children[0].text};`]\n } else if (singleIntegerCell) {\n let bindingsLines = removeStartingWhitespace(\n removeTrailingWhitespace(\n children[0].text.slice(1, -2)\n )\n )\n\n switch (multilineIntegerCellsIndent) {\n case 'reindent':\n bindingsLines = reindent(bindingsLines, indentation + indent)\n break\n\n case 'dedent':\n bindingsLines = dedent(bindingsLines)\n break\n\n case 'keep':\n default:\n break\n }\n\n return [\n indentation + `${labels}${identifier.text} = <`,\n ...bindingsLines.split('\\n'),\n indentation + '>;'\n ]\n }\n\n return [\n indentation + `${identifier.text} =`,\n ...[].concat(...children.map(node => formatNode(node, options)))\n .map((line, i, arr) => {\n const suffix = i === arr.length - 1 ? ';' : ','\n return [line, suffix].join('')\n })\n ]\n}\n\nmodule.exports = {\n formatNode,\n getModelineConfiguration,\n getNodeDepth,\n isInlineComment,\n shouldIncludeBlank\n}\n","module.exports = Object.assign(\n {},\n require('./nodes'),\n require('./properties'),\n require('./trees'),\n require('./values')\n)\n","const assert = require('assert')\nconst reverse = require('lodash/reverse')\n\n/**\n * Check if an ordered list of nodes are consecutive\n * Nodes are consecutive if each node is adjacent to the next, so that no other\n * sibling nodes exist between them.\n * @param {Array<SyntaxNode>} nodes\n * @returns {Boolean}\n */\nfunction nodesAreConsecutive (nodes) {\n return nodes.every((node, i) => (\n i < nodes.length - 1\n ? node.nextSibling.id === nodes[i + 1].id\n : true\n ))\n}\n\n/**\n * Get the string value of each reference label attached to the given node.\n * Labels are in in descending order of depth.\n * @param {SyntaxNode} node\n * @returns {Array<String>}\n */\nfunction getNodeLabels (node) {\n return getNodeLabelNodes(node).map(label => label.text)\n}\n\n// blech\nfunction getNodeLabelNodes (node) {\n return getNodeChildrenByFieldName(node.parent, 'label')\n}\n\n/**\n * Descend into a chain of labeled_item nodes to get at the actual item\n * @param {SyntaxNode} labeledItemNode syntax node for a devicetree label\n * @returns {SyntaxNode}\n */\nfunction getLabeledItem (labeledItemNode) {\n assert(labeledItemNode.type === 'labeled_item')\n return labeledItemNode.childForFieldName('item')\n}\n\nfunction getNodeChildrenByFieldName (node, fieldName) {\n const children = []\n\n // Iteration is done with a cursor here because only TreeCursor will directly\n // tell us what field is associated with the current node. The node itself\n // will not tell us about its own field, and Node.childForFieldName(field)\n // will only tell us about a single child with the specified field.\n const cursor = node.walk()\n cursor.gotoFirstChild()\n\n do {\n const isNamed = cursor.currentNode().isNamed()\n const isField = cursor.currentFieldName() === fieldName\n if (isNamed && isField) {\n children.push(cursor.currentNode())\n }\n } while (cursor.gotoNextSibling())\n\n cursor.delete()\n\n return children\n}\n\n/**\n * Find a single child of the given node with a matching identifier\n * @param {SyntaxNode} node\n * @param {Function|String} nameOrMatch\n * @returns {SyntaxNode}\n */\nfunction findChildrenByIdentifier (node, nameOrMatch) {\n const match = typeof nameOrMatch === 'string'\n ? text => text === nameOrMatch\n : nameOrMatch\n\n return node.namedChildren.filter(node => (\n node.type === 'node' &&\n node.children.find(sub => (\n sub.type === 'identifier' &&\n match(sub.text)\n ))\n ))\n}\n\n/**\n * Find a child of the given node(s) with a matching name.\n * If multiple nodes are given to search through, they will be searched in\n * reverse order so that the \"latest\" instance of a node takes precedence.\n * @param {Array<SyntaxNode>|SyntaxNode} nodes\n * @param {RegExp|String} nameOrMatch\n */\nfunction findChildByIdentifier (nodes, nameOrMatch) {\n nodes = [].concat(nodes)\n for (const node of reverse(nodes)) {\n const match = findChildrenByIdentifier(node, nameOrMatch)[0]\n if (match) {\n return match\n }\n }\n}\n\nfunction listNodes (nodes, opts = {}) {\n const { stripNewlines = true, limit = 50 } = opts\n for (const node of nodes) {\n let value = node.text\n if (stripNewlines) value = value.replace(/\\n/g, '')\n if (limit) value = value.slice(0, limit)\n\n console.log(node.id, `[${node.type}]`, '->', value)\n }\n}\n\nmodule.exports = {\n nodesAreConsecutive,\n getNodeLabels,\n getNodeLabelNodes,\n getLabeledItem,\n getNodeChildrenByFieldName,\n findChildByIdentifier,\n findChildrenByIdentifier,\n listNodes\n}\n","const { getNodeChildrenByFieldName } = require('./nodes')\nconst {\n parseStringLiteral,\n parseIntegerCells,\n parseIntegerArray,\n parsePhandles,\n parsePhandle,\n parsePhandleArray,\n parseIntegerUnion,\n serializeIntValue,\n serializeArrayValue\n} = require('./values')\n\n/** @typedef {{ parsed: any, raw: string, useRaw?: boolean }} PropertyValue */\n/** @typedef {Object.<string, PropertyValue>} Properties */\n\n/**\n * Get a property with the given name in this node, if it exists.\n * @param {SyntaxNode} node\n * @param {String} propertyName\n * @returns {SyntaxNode|undefined}\n */\nfunction findNodeProperty (node, propertyName) {\n return node.children.find(node => (\n node.type === 'property' &&\n node.children[0].text === propertyName\n ))\n}\n\nfunction getPropertyNode (node, propertyName) {\n return node.namedChildren.find(child => (\n child.type === 'property' &&\n child.childForFieldName('name')?.text === propertyName\n ))\n}\n\nfunction getProperty (node, property) {\n const propertyNode = node.children.find(node => (\n node.type === 'property' &&\n node.children[0].text === property\n ))\n\n return propertyNode && {\n syntaxNode: propertyNode,\n name: property,\n value: propertyNode.children[2]?.text\n }\n}\n\nfunction getPropertyValue (node, property) {\n property = typeof property === 'string'\n ? getPropertyNode(node, property)\n : property\n\n return property?.childForFieldName('value')\n}\n\nfunction getPropertyValues (node, property) {\n const propertyNode = getPropertyNode(node, property)\n return propertyNode && getNodeChildrenByFieldName(propertyNode, 'value')\n}\n\n/**\n * @param {SyntaxNode} node devicetree node from which to extract property values\n * @param {Object} schema devicetree schema of a spcecific node\n * @return {Properties} properties\n */\nfunction parsePropertiesFromSchema (node, schema) {\n return Object.keys(schema).reduce((properties, prop) => {\n const propSchema = schema[prop]\n const values = parsePropertyFromSchema(node, prop, propSchema)\n\n if (values !== undefined) {\n properties[prop] = {\n parsed: values\n }\n }\n\n return properties\n }, {})\n}\n\n/**\n * @param {SyntaxNode} node devicetree node from which to extract a property value\n * @param {String} property name of property\n * @param {Object} schema devicetree schema of specific property\n */\nfunction parsePropertyFromSchema (node, property, schema) {\n const propertyNode = findNodeProperty(node, property)\n const values = getPropertyValues(node, property)\n\n switch (schema.type) {\n case 'string':\n return parseStringLiteral(values?.[0])\n\n case 'boolean':\n return !!propertyNode\n\n case 'int':\n return parseIntegerCells(values)?.[0]\n\n case 'array':\n return parseIntegerArray(values)\n\n case 'phandle':\n return parsePhandle(values)\n\n case 'phandles':\n return parsePhandles(values)\n\n case 'phandle-array':\n return parsePhandleArray(values)\n\n case 'integer-union':\n return parseIntegerUnion(values)\n }\n}\n\nfunction serializePropertyFromSchema (property, schema) {\n // TODO: Probably make separate functions?\n switch (schema.type) {\n case 'string':\n return `\"${property.parsed}\"`\n\n case 'boolean':\n // This is a weird case because instead of an explicit value we use the\n // presense of the property (name) to indicate true or false. Note that\n // this will get more complicated when supporting the `/delete-property/`\n // flag (?)\n return property.parsed\n\n case 'int':\n return serializeIntValue(property.parsed)\n\n case 'array':\n return serializeArrayValue(property.parsed)\n\n case 'phandle':\n return property.parsed.map(phandle => `<${phandle}>`).join(', ')\n\n case 'phandles':\n case 'phandle-array':\n // TODO: Grouping binding cells into separate phandle-arrays shouldn't\n // be the default behavior but right now the only place this would be\n // unacceptably weird is the bindings property for layer and macro nodes\n // which already do their own formatting explicitly.\n return property.parsed\n .reduce((bindings, node) => {\n if (node.startsWith('&')) {\n bindings.push([node])\n } else {\n const last = bindings[bindings.length - 1]\n last.push(node)\n }\n\n return bindings\n }, [])\n .map(group => `<${group.join(' ')}>`)\n .join(', ')\n\n case 'integer-union':\n return `<(${property.parsed.map(v => v.toString()).join('|')})>`\n }\n}\n\nmodule.exports = {\n findNodeProperty,\n getProperty,\n getPropertyNode,\n getPropertyValue,\n getPropertyValues,\n parsePropertiesFromSchema,\n parsePropertyFromSchema,\n serializePropertyFromSchema\n}\n","\n/**\n *\n * @param {Tree|Node} tree Starting point for breadth-first traversal\n * @param {Object} [options={}]\n * @param {Integer} [options.maxDepth=-1]\n * @returns {Function} get next node, or undefined when traversal is complete\n */\nfunction BreadthFirstIterator (tree, options = {}) {\n const { maxDepth = -1 } = options\n const queue = [{ depth: 0, node: tree.rootNode || tree }]\n\n return function next () {\n const current = queue.shift()\n if (current && (maxDepth === -1 || current.depth < maxDepth)) {\n queue.push(...current.node.namedChildren.map(node => ({\n node, depth: current.depth + 1\n })))\n }\n return current?.node\n }\n}\n\n/**\n *\n * @param {Tree|Node} tree Starting point for depth-first traversal\n * @param {Object} [options={}]\n * @param {Integer} [options.maxDepth=-1]\n * @returns {Function} get next node, or undefined when traversal is complete\n */\nfunction DepthFirstIterator (tree, options = {}) {\n const { maxDepth = -1 } = options\n const stack = [{ depth: 0, node: tree.rootNode || tree }]\n\n return function next () {\n const current = stack.shift()\n if (current && (maxDepth === -1 || current.depth < maxDepth)) {\n stack.unshift(...current.node.namedChildren.map(node => ({\n node, depth: current.depth + 1\n })))\n }\n return current?.node\n }\n}\n\n/**\n * Find nodes in `tree` that satisfy the given `predicate` function.\n *\n * @param {Tree|SyntaxNode} tree\n * @param {Function} predicate\n * @param {Object} [options={}]\n * @param {Boolean} [options.single=false]\n * @param {Integer} [options.maxDepth=-1]\n * @param {Boolean} [options.depthFirst=false]\n * @returns {Array<SyntaxNode>|SyntaxNode} use options.single to return only the first matching node\n */\nfunction searchTree (tree, predicate, options = {}) {\n const {\n single = false,\n maxDepth = -1,\n depthFirst = false\n } = options\n\n const iter = depthFirst\n ? DepthFirstIterator(tree, { maxDepth })\n : BreadthFirstIterator(tree, { maxDepth })\n\n const matches = []\n let node\n\n while ((node = iter())) {\n if (predicate(node)) {\n if (single) {\n return node\n }\n\n matches.push(node)\n }\n }\n\n if (single) {\n return undefined\n }\n\n return matches\n}\n\nfunction findNodeByIdentifier (tree, name) {\n return searchTree(tree, node => (\n node.type === 'node' &&\n node.childForFieldName('name').text === name\n ), { single: true })\n}\n\nfunction findLabeledItem (tree, name) {\n let node = searchTree(tree, node => (\n node.type === 'labeled_item' &&\n node.children[0].type === 'identifier' &&\n node.children[0].text === name\n ), { single: true })\n\n if (!node) {\n return null\n }\n\n do {\n node = node.childForFieldName('item')\n } while (node.type === 'labeled_item')\n\n return node\n}\n\nfunction createPredicateForCompatible (compatible) {\n let match\n\n if (compatible instanceof RegExp) {\n match = text => compatible.test(text)\n } else if (typeof compatible === 'string') {\n match = text => text === `\"${compatible}\"`\n } else if (typeof compatible === 'function') {\n match = compatible\n } else {\n throw new TypeError('Unexpected type ' + typeof compatible)\n }\n\n return node => (\n node.type === 'property' &&\n node.childForFieldName('name').text === 'compatible' &&\n match(node.childForFieldName('value').text)\n )\n}\n\n/**\n * Find single node including a `compatible` property with the given value.\n *\n * @param {Tree|SyntaxNode} tree\n * @param {String|RegExp|Function} compatible\n * @returns {SyntaxNode|undefined}\n */\nfunction findNodeWithCompatible (tree, compatible) {\n // TODO: look into tree sitter queries again, doing these searches within web\n // assembly is probably much faster. Alternatively, performing this lookup as\n // a breadth-first search would likely save a lot of time since we're often\n // expecting to match nodes just inside the devicetree root node. It may also\n // be worth refining the depth-first search to avoid going deeper in some\n // situations -- if I'm matching a property string it doesn't make sense to\n // recurse into the property values.\n const predicate = createPredicateForCompatible(compatible)\n const propertyNode = searchTree(tree, predicate, { single: true })\n\n return propertyNode?.parent\n}\n/**\n * Find descendent nodes including a `compatible` property with the given value.\n *\n * @param {Tree|SyntaxNode} tree\n * @param {String|RegExp|Function} compatible\n * @returns {Array<SyntaxNode>}\n */\nfunction findNodesWithCompatible (tree, compatible) {\n const predicate = createPredicateForCompatible(compatible)\n return searchTree(tree, predicate).map(property => property.parent)\n}\n\nmodule.exports = {\n BreadthFirstIterator,\n DepthFirstIterator,\n searchTree,\n findLabeledItem,\n findNodeByIdentifier,\n findNodeWithCompatible,\n findNodesWithCompatible\n}\n","const { searchTree } = require('./trees')\n\nconst isNegativeInteger = node => (\n node.type === 'unary_expression' &&\n node.childForFieldName('operator').type === '-' &&\n node.childForFieldName('argument').type === 'integer_literal'\n)\n\nconst isNumberishType = node => (\n ['identifier', 'integer_literal'].includes(node.type) || isNegativeInteger(node)\n)\n\nconst isBindingType = node => (\n // call_expression node includes modifier functions like `LC(A)`\n ['identifier', 'integer_literal', 'reference', 'call_expression'].includes(node.type)\n)\n\nconst isBindingRef = node => node.type === 'reference'\n\nconst extractInteger = node => (\n node.type === 'integer_literal' || isNegativeInteger(node)\n ? Number(node.text)\n : node.text\n)\n\nfunction parseStringLiteral (value) {\n return value?.text?.slice(1, -1)\n}\n\nfunction parseIntegerCells (values) {\n return parseIntegerArray(values)\n}\n\nfunction parseIntegerArray (values) {\n return values?.flatMap(cells => (\n cells.namedChildren\n .filter(isNumberishType)\n .map(extractInteger)\n ))\n}\n\nfunction parsePhandle (values) {\n return parsePhandles(values)[0]\n}\n\nfunction parsePhandles (values) {\n return values?.flatMap(cells => (\n cells.namedChildren\n .filter(isBindingRef)\n .map(value => value.text)\n ))\n}\n\nfunction parsePhandleArray (values) {\n return values?.flatMap(cells => (\n cells.namedChildren\n .filter(isBindingType)\n .map(value => value.text)\n ))\n}\n\nfunction parseIntegerUnion (values) {\n return values?.flatMap(value => (\n searchTree(value, isNumberishType, { depthFirst: true })\n )).map(extractInteger)\n}\n\nfunction sanitizeIdentifier (name) {\n return name\n .replace(/[^a-zA-Z0-9,._+-]/g, '_')\n .slice(0, 31)\n}\n\nfunction serializeIntegerCell (value) {\n value = value.toString()\n if (value.match(/-\\d+/)) {\n value = `(${value})`\n }\n\n return value\n}\n\nfunction serializeIntValue (value) {\n return `<${serializeIntegerCell(value)}>`\n}\n\nfunction serializeArrayValue (values) {\n return `<${values.map(serializeIntegerCell).join(' ')}>`\n}\n\nmodule.exports = {\n parseStringLiteral,\n parseIntegerCells,\n parseIntegerArray,\n parsePhandle,\n parsePhandleArray,\n parsePhandles,\n parseIntegerUnion,\n sanitizeIdentifier,\n serializeIntValue,\n serializeArrayValue\n}\n","const assert = require('assert')\nconst { ReferenceError } = assert\nconst difference = require('lodash/difference')\nconst filter = require('lodash/filter')\nconst isEqual = require('lodash/isEqual')\nconst map = require('lodash/map')\nconst partition = require('lodash/partition')\nconst reverse = require('lodash/reverse')\n\nconst { getNodeLabels, getLabeledItem } = require('./helpers/nodes')\nconst { getPropertyValues } = require('./helpers/properties')\nconst { sanitizeIdentifier } = require('./helpers/values')\n\nclass NodeCollection {\n managedProperties = []\n _cached_container_node = null\n _cached_container_tree_version = 0\n _cached_collection_nodes = null\n _cached_collection_tree_version = 0\n\n constructor (document, options = {}) {\n this.document = document\n if (options.managedProperties) { this.managedProperties = options.managedProperties }\n if (options.lookupContainerNode) { this.lookupContainerNode = options.lookupContainerNode.bind(this) }\n if (options.injectContainerNode) { this.injectContainerNode = options.injectContainerNode.bind(this) }\n if (options.lookupNodes) { this.lookupNodes = options.lookupNodes.bind(this) }\n if (options.injectNode) { this.injectNode = options.injectNode.bind(this) }\n }\n\n lookupContainerNode () { throw new ReferenceError('Provide `lookupContainerNode` in constructor or override this method') }\n injectContainerNode () { throw new ReferenceError('Provide `injectContainerNode` in constructor or override this method') }\n\n lookupNodes () { throw new ReferenceError('Provide `lookupNodes` in constructor or override this method') }\n injectNode () { throw new ReferenceError('Provide `injectNode` in constructor or override this method') }\n\n get container () {\n if (this._cached_container_tree_version !== this.document._parse_version) {\n delete this._cached_container_node\n }\n if (!this._cached_container_node) {\n this._cached_container_node = this.lookupContainerNode(this.document)\n this._cached_container_tree_version = this.document._parse_version\n }\n\n return this._cached_container_node\n }\n\n get nodes () {\n if (this._cached_collection_tree_version !== this.document._parse_version) {\n delete this._cached_collection_nodes\n }\n if (!this._cached_collection_nodes) {\n this._cached_collection_nodes = this.lookupNodes(this.document)\n this._cached_collection_tree_version = this.document._parse_version\n }\n\n return this._cached_collection_nodes\n }\n\n updateCollection (collection) {\n if (collection.length && !this.container) {\n this.injectContainerNode(this)\n this.document.flushChanges()\n }\n\n const originalIndices = [...this.nodes.keys()]\n const reusedIndices = filter(map(collection, 'index'), index => this.nodes[index])\n const removedIndices = difference(originalIndices, reusedIndices)\n const [updates, additions] = partition(collection, node => this.nodes[node.index])\n\n for (const node of updates) {\n this.updateNode(node.index, node)\n }\n\n for (const index of reverse(removedIndices)) {\n this.document.removeNode(this.nodes[index])\n }\n\n for (const node of additions) {\n this.injectNode(this, node)\n this.document.flushChanges()\n this.updateNode(this.nodes.length - 1, node)\n }\n }\n\n /**\n * Update an existing devicetree node\n * @param {Integer} index the position of the existing node to update\n * @param {Object} update the new node state to apply to devicetree\n * @param {String} update.name the devicetree node name\n * @param {Array<String>} update.labels zero or more devictree labels to apply to the node\n * @param {Object} update.properties mapping of property name to (serialized) property values\n */\n updateNode (index, update) {\n const existing = this.extractNode(this.nodes[index])\n this.updateNodeName(index, update, existing)\n this.updateNodeLabels(index, update, existing)\n this.updateNodeProperties(index, update, existing)\n this.cleanupNodeProperties(index, update, existing)\n }\n\n updateNodeName (index, update, existing) {\n if (existing.name !== update.name) {\n const identifier = this.nodes[index].childForFieldName('name')\n this.document.replaceNode(identifier, sanitizeIdentifier(update.name), {\n removeStartingWhitespace: false\n })\n }\n }\n\n updateNodeLabels (index, update, existing) {\n if (!isEqual(existing.labels, update.labels)) {\n this.document.replaceNodeLabels(this.nodes[index], update.labels)\n }\n }\n\n updateNodeProperties (index, update, existing) {\n const { properties } = update\n\n for (const name in properties) {\n const values = properties[name]\n\n if (!isEqual(values, existing.properties[name])) {\n this.document.setProperty(\n this.nodes[index],\n name,\n values\n )\n }\n }\n }\n\n cleanupNodeProperties (index, update, existing) {\n const { properties } = update\n for (const name of this.managedProperties) {\n if (name in existing.properties && !(name in properties)) {\n this.document.deleteProperty(this.nodes[index], name)\n }\n }\n }\n\n /**\n * Extract basic information from a devicetree node for convenience.\n * The output of this function is an object with structure:\n * {\n * name: String,\n * labels: Array<String>\n * properties: Object<name:values>\n * }\n * This can be overridden to include additional details.\n * @param {SyntaxNode} node a devicetree node from which to extract info\n * @returns {Object}\n */\n extractNode (node) {\n // TODO: should there be a `Node` class?\n // TODO: Should there be a `PropertyCollection` with similar abstractions?\n assert(node.type === 'node')\n\n const name = node.childForFieldName('name').text\n const labels = getNodeLabels(node)\n const properties = node.namedChildren.reduce((acc, child) => {\n if (child.type === 'labeled_item') {\n child = getLabeledItem(child)\n }\n if (child.type === 'property') {\n const name = child.childForFieldName('name').text\n const values = getPropertyValues(node, name)\n const parsed = map(values, 'text')\n const raw = parsed.join(', ')\n acc[name] = { parsed, raw }\n }\n\n return acc\n }, {})\n\n return {\n name,\n labels,\n properties\n }\n }\n\n /**\n * Evaluate each node with `extractNode` and include an `index` property\n * @returns {Array<Object>}\n */\n extractCollection () {\n return this.nodes.map((node, index) => ({\n index, ...this.extractNode(node)\n }))\n }\n}\n\nmodule.exports = {\n NodeCollection\n}\n","const assert = require('assert')\nconst { sortBy } = require('lodash')\n\nconst TreeSitter = require('web-tree-sitter')\n\nconst { getPosition } = require('string-utils')\nconst { getNodeLabelNodes } = require('./helpers/nodes')\nconst { getProperty } = require('./helpers/properties')\n\nlet _parser\n\nasync function getParser () {\n if (!_parser) {\n await TreeSitter.init()\n const language = await TreeSitter.Language.load(\n\n // This is meant to make loading possible in a browser.\n global.window\n ? require('../data/tree-sitter-devicetree.wasm')\n : __dirname + '/../data/tree-sitter-devicetree.wasm'\n )\n _parser = new TreeSitter()\n _parser.setLanguage(language)\n }\n\n return _parser\n}\n\nclass DevicetreeDocument {\n constructor (parser, text) {\n this.parser = parser\n this._parse_version = 0\n this._enableChangeBuffering = false\n this._bufferedChanges = []\n this.update(text)\n }\n\n cleanup () {\n this.tree.delete()\n }\n\n update (text, inputEdit = null) {\n if (inputEdit && this.tree && this._enableChangeBuffering) {\n const replacementText = text.slice(inputEdit.startIndex, inputEdit.newEndIndex)\n this._bufferedChanges.push({\n startIndex: inputEdit.startIndex,\n update: inputEdit,\n replacementText\n })\n } else {\n this.text = text\n this._reparse()\n }\n }\n\n _reparse () {\n this.tree && this.tree.delete()\n this.tree = this.parser.parse(this.text)\n this._parse_version++\n }\n\n flushChanges () {\n if (this._bufferedChanges.length === 0) {\n return\n }\n\n const updates = sortBy(this._bufferedChanges, 'startIndex')\n\n // console.log('flushing updates', updates)\n // console.log({ original: this.text })\n\n const chunks = updates.reduce((chunks, { update, replacementText }, i) => {\n const nextUpdate = updates[i + 1]\n const prevEnd = i > 0\n ? updates[i - 1].update.oldEndIndex\n : 0\n\n const preChunk = this.text.slice(prevEnd, update.startIndex)\n const chunk = replacementText\n chunks.push(preChunk)\n chunks.push(chunk)\n\n // console.log({\n // preChunk,\n // chunk\n // })\n\n if (!nextUpdate) {\n // console.log('selecting final cunk', {\n // original: this.text,\n // update,\n // postChunk: this.text.slice(update.oldEndIndex)\n // })\n chunks.push(this.text.slice(update.oldEndIndex))\n }\n\n return chunks\n }, [])\n\n // console.log('generated chunks', chunks)\n\n this.text = chunks.join('')\n // console.log('generated text', this.text)\n this._reparse()\n this._bufferedChanges = []\n }\n\n removeNode (node) {\n this.replaceNode(node, '')\n }\n\n /**\n * Replace the contents of a syntax node with other (serialized) content.\n *\n * @param {SyntaxNode} node the node to be replaced\n * @param {String} newContent the devicetree source replacing the original node\n * @param {Object} options\n * @param {Bool} options.removeStartingWhitespace whether to attempt to start replacing at the start of `node`'s line\n */\n replaceNode (node, newContent, options = {}) {\n const { removeStartingWhitespace = true } = options\n const { text: documentText } = this\n\n // TODO: this all should probably go\n const precedingNewline = documentText.lastIndexOf('\\n', node.startIndex)\n const hasStartingWhitespace = precedingNewline !== -1 && documentText.slice(precedingNewline + 1, node.startIndex).match(/\\s+/)\n const start = hasStartingWhitespace && removeStartingWhitespace\n ? precedingNewline\n : node.startIndex\n\n const replacement = [\n documentText.slice(0, start),\n newContent,\n documentText.slice(node.endIndex)\n ].join('')\n\n const inputEdit = {\n startIndex: start,\n startPosition: getPosition(newContent, start),\n oldEndIndex: node.endIndex,\n oldEndPosition: node.endPosition,\n newEndIndex: start + newContent.length,\n newEndPosition: getPosition(replacement, start + newContent.length)\n }\n\n this.update(replacement, inputEdit)\n }\n\n replaceRange (startIndex, skipToIndex, newContent) {\n const { text: source } = this\n const pre = source.slice(0, startIndex)\n const post = source.slice(skipToIndex)\n const replacement = [pre, newContent, post].join('')\n const newEndIndex = startIndex + newContent.length\n const inputEdit = {\n startIndex,\n startPosition: getPosition(source, startIndex),\n oldEndIndex: skipToIndex,\n oldEndPosition: getPosition(source, skipToIndex),\n newEndIndex,\n newEndPosition: getPosition(replacement, newEndIndex)\n }\n\n return this.update(replacement, inputEdit)\n }\n\n /**\n * Replace any existing labels attached to the specified node.\n * @param {SyntaxNode} labeledNode\n * @param {Array<String>} newLabels\n */\n replaceNodeLabels (labeledNode, newLabels) {\n const labelNodes = getNodeLabelNodes(labeledNode)\n const sorted = sortBy(labelNodes, 'startIndex')\n const serializedLabels = newLabels.map(label => `${label}:`).join(' ')\n const start = (sorted[0] && sorted[0].parent) || labeledNode\n\n this.replaceRange(start.startIndex, labeledNode.startIndex, serializedLabels)\n }\n\n /**\n * Insert text content before a specified node\n * @param {SyntaxNode} node the node before which to insert\n * @param {String} newContent the new devicetree source to be inserted\n */\n insertTextBeforeNode (node, newContent) {\n this.replaceRange(node.startIndex, node.startIndex, newContent)\n }\n\n /**\n * Insert text content after a specified node\n * @param {SyntaxNode} node the node after which to insert\n * @param {String} newContent the new devicetree source to be inserted\n */\n insertTextAfterNode (node, newContent) {\n this.replaceRange(node.endIndex, node.endIndex, newContent)\n }\n\n /**\n * Append devicetree source to the specified node\n * @param {SyntaxNode} parentNode parent node in which to add content\n * @param {*} newContent the new devicetree source to be inserted\n */\n addChildNode (parentNode, newContent) {\n assert(parentNode.type === 'node')\n\n const closingBrace = parentNode.children.find(node => node.type === '}')\n return this.replaceRange(\n closingBrace.startIndex,\n closingBrace.startIndex,\n newContent\n )\n }\n\n /**\n * Set/create a property with the specified value in the specified node\n * @param {SyntaxNode} node target node in which to set property\n * @param {String} property name of property to set\n * @param {String|Boolean} value serialized devicetree value.\n */\n setProperty (node, property, value) {\n const existing = getProperty(node, property)\n\n if (typeof value === 'boolean' && !value) {\n if (existing) {\n this.deleteProperty(node, property)\n }\n\n return\n }\n\n const newText = value.length\n ? `${property} = ${value};`\n : `${property};`\n\n if (existing) {\n return this.replaceNode(\n existing.syntaxNode,\n newText,\n { removeStartingWhitespace: false }\n )\n }\n\n return this.addChildNode(node, `\\n ${newText}`)\n }\n\n /**\n * Remove a property from a specified devicetree node.\n * @param {SyntaxNode} node where to search for the named property\n * @param {String} property name of property to remove\n */\n deleteProperty (node, property) {\n const existing = getProperty(node, property)\n if (existing) {\n this.replaceNode(existing.syntaxNode, '')\n }\n }\n}\n\nmodule.exports = {\n getParser,\n DevicetreeDocument\n}\n","const flatten = require('lodash/flatten')\nconst get = require('lodash/get')\nconst keyBy = require('lodash/keyBy')\nconst map = require('lodash/map')\nconst uniq = require('lodash/uniq')\n\nconst { getParser } = require('devicetree')\nconst { formatNode, getModelineConfiguration } = require('devicetree/lib/formatters')\nconst { behaviorBindings } = require('zmk-data/behaviors')\n\nconst KeymapDocument = require('./devicetree/keymap-document')\nconst { encodeKeymap } = require('./keymap')\n\nconst behavioursByBind = keyBy(behaviorBindings, 'code')\n\nasync function applyKeymapChanges (layout, keymap, original, featureFlags = {}) {\n // TODO: generate this higher up in the call stack, I don't think we need the\n // original keymap object anymore except for the `layer_names` property\n const encoded = encodeKeymap(layout, keymap)\n const behaviourHeaders = flatten(getBehavioursUsed(keymap).map(\n bind => get(behavioursByBind, [bind, 'includes'], [])\n ))\n\n const devicetreeKeymap = new KeymapDocument(await getParser(), original)\n devicetreeKeymap._enableChangeBuffering = true\n devicetreeKeymap.mergeUpdated(encoded, featureFlags)\n devicetreeKeymap.replaceBehaviourIncludes(behaviourHeaders)\n devicetreeKeymap.flushChanges()\n\n try {\n const config = getModelineConfiguration(devicetreeKeymap.tree)\n return formatNode(devicetreeKeymap.tree.rootNode, config).join('\\n')\n } catch (err) {\n console.error('Failed to format devictree', err)\n return devicetreeKeymap.text\n } finally {\n devicetreeKeymap.cleanup()\n }\n}\n\nfunction getBehavioursUsed (keymap) {\n const keybinds = flatten(map(keymap.layers, layer => layer.properties?.bindings?.parsed || layer.bindings))\n const comboBinds = flatten(map(keymap.combos, 'bindings'))\n const macroBinds = flatten(map(keymap.macros, 'properties.bindings.parsed'))\n\n return uniq(map([\n ...keybinds,\n ...comboBinds,\n ...macroBinds\n ], 'value'))\n}\n\nmodule.exports = applyKeymapChanges\n","const filter = require('lodash/filter')\nconst get = require('lodash/get')\nconst { parsePropertyFromSchema } = require('devicetree/lib/helpers/properties')\n\n/** @typedef {String} IntegerCell */\n/** @typedef {String} Bind */\n/** @typedef {{ value: String, params: Array<BindValue> }} BindValue */\n\n/**\n * @param {SyntaxNode} node\n * @param {String} [propertyName='bindings']\n * @returns {Array<Bind>|undefined} bind strings\n */\nfunction parseBindings (node, propertyName = 'bindings') {\n const bindings = parsePropertyFromSchema(node, propertyName, {\n type: 'phandle-array'\n })\n\n return bindings\n ? groupPhandleArrayBindings([].concat(...bindings))\n : undefined\n}\n\n/**\n * @param {Array<IntegerCell>} bindingCells\n * @returns {Array<Bind>}\n */\nfunction groupPhandleArrayBindings (bindingCells) {\n return bindingCells.reduce((bindings, node) => {\n if (node.startsWith('&')) {\n bindings.push([node])\n } else {\n const last = bindings[bindings.length - 1]\n last.push(node)\n }\n\n return bindings\n }, []).map(binding => binding.join(' '))\n}\n\nconst MACRO_CONTROL_BEHAVIOURS = [\n '¯o_tap',\n '¯o_press',\n '¯o_release',\n '¯o_tap_time',\n '¯o_wait_time',\n '¯o_pause_for_release'\n]\n\n/**\n * Group a flat list of bind strings at macro activation mode change\n * @param {Array<Bind>} bindings\n * @returns {Array<Array<Bind>>}\n */\nfunction groupMacroBindings (bindings) {\n return bindings.reduce((rows, binding, i, arr) => {\n const behaviourBind = binding.split(' ')[0]\n\n if (MACRO_CONTROL_BEHAVIOURS.includes(behaviourBind)) {\n if (rows.at(-1).length > 0) {\n rows.push([])\n }\n\n rows.at(-1).push(binding)\n if (i < arr.length - 1) {\n rows.push([])\n }\n } else {\n rows.at(-1).push(binding)\n }\n\n return rows\n }, [[]])\n}\n\n/**\n * Parse a bind string into a tree of values and parameters\n * @param {Bind} binding\n * @returns {BindValue}\n */\nfunction parseKeyBinding (binding, keymap) {\n const paramsPattern = /\\((.+)\\)/\n\n function parse (code) {\n const value = code.replace(paramsPattern, '')\n const params = get(code.match(paramsPattern), '[1]', '').split(',')\n .map(s => s.trim())\n .filter(s => s.length > 0)\n .map(parse)\n\n return {\n // TODO: some defines (e.g., in bat43) can involve multiple bind values\n // this replacement should happen before the bindings array is parsed\n value: get(keymap.defines, value, value),\n params\n }\n }\n\n const value = binding.match(/^(&.+?)\\b/)[1]\n const params = filter(binding.replace(/^&.+?\\b\\s*/, '')\n .split(' '))\n .map(parse)\n\n return { value, params }\n}\n\n/**\n * Serialize a node of a BindValue tree\n * @param {BindValue} parsed\n * @returns {Bind}\n */\nfunction encodeBindValue (parsed) {\n const params = (parsed.params || []).map(encodeBindValue)\n const paramString = params.length > 0 ? `(${params.join(',')})` : ''\n return parsed.value + paramString\n}\n\n/**\n * Serialize a top-level BindValue object\n * @param {BindValue} parsed\n * @returns {Bind}\n */\nfunction encodeKeyBinding (parsed) {\n const { value, params } = parsed\n\n return `${value} ${params.map(encodeBindValue).join(' ')}`.trim()\n}\n\nmodule.exports = {\n parseBindings,\n parseKeyBinding,\n groupMacroBindings,\n groupPhandleArrayBindings,\n encodeKeyBinding\n}\n","const isEqual = require('lodash/isEqual')\n\nconst {\n findChildByIdentifier,\n findChildrenByIdentifier,\n findNodesWithCompatible,\n findNodeProperty,\n getPropertyValues,\n parsePropertyFromSchema,\n sanitizeIdentifier,\n serializePropertyFromSchema\n} = require('devicetree/lib/helpers')\nconst { NodeCollection } = require('devicetree/lib/node-collection')\nconst { behaviorSchemas } = require('zmk-data/behaviors')\n\nconst { parseKeyBinding, encodeKeyBinding } = require('../bindings')\n\nfunction resolveBehaviorBindings (behavior) {\n const bindingsValues = getPropertyValues(behavior, 'bindings') || []\n const bindings = bindingsValues.flatMap(bindingsValue => (\n bindingsValue.namedChildren.flatMap(bindCode => bindCode.text)\n ))\n\n return { bindings }\n}\n\nclass BehaviorCollection extends NodeCollection {\n lookupContainerNode () {\n const rootNodes = findChildrenByIdentifier(this.document.tree.rootNode, '/')\n return findChildByIdentifier(rootNodes, 'behaviors')\n }\n\n injectContainerNode () {\n const keymap = findNodesWithCompatible(this.document.tree.rootNode, 'zmk,keymap').at(-1)\n this.document.insertTextBeforeNode(keymap, '\\nbehaviors {};\\n')\n }\n\n lookupNodes () {\n return findNodesWithCompatible(this.document.tree.rootNode, value => (\n value.startsWith('\"zmk,behavior-') &&\n value !== '\"zmk,behavior-macro\"'\n ))\n }\n\n injectNode (_, behavior) {\n const name = sanitizeIdentifier(behavior.name)\n const last = this.nodes.at(-1)\n const nodeContent = `${behavior.labels[0]}: ${name} {\n compatible = ${behavior.properties.compatible.raw};\n };`\n\n // new node will be updated with full set of properties later, but for now\n // a known behavior has to be set to make sure this node is not filtered out\n if (last) {\n this.document.insertTextAfterNode(last, nodeContent)\n } else {\n this.document.addChildNode(this.container, nodeContent)\n }\n }\n\n extractNode (node) {\n const compatible = findNodeProperty(node, 'compatible')?.namedChildren[1].text.slice(1, -1)\n\n const schema = behaviorSchemas[compatible]\n const extracted = super.extractNode(node)\n const { name: identifier, labels } = extracted\n\n extracted.properties.compatible.parsed = compatible\n\n if (schema) {\n for (const prop in schema.properties) {\n const propSchema = schema.properties[prop]\n const extractedProp = extracted.properties[prop]\n if (extractedProp) {\n extractedProp.parsed = parsePropertyFromSchema(node, prop, propSchema)\n\n if (propSchema.type === 'phandle-array') {\n const bindStrings = extractedProp.parsed\n .reduce((bindings, node) => {\n if (node.startsWith('&')) {\n bindings.push([node])\n } else {\n const last = bindings[bindings.length - 1]\n last.push(node)\n }\n\n return bindings\n }, [])\n .map(group => group.join(' '))\n\n extractedProp.parsed = bindStrings.map(bind => parseKeyBinding(bind, {}))\n }\n }\n }\n }\n\n const bindingCells = extracted.properties['#binding-cells']?.parsed || 0\n const label = extracted.properties.label?.parsed\n\n return Object.assign(\n extracted,\n { binding: `&${labels[0]}` },\n { code: `&${labels[0]}` },\n { aliases: labels.map(label => `&${label}`) },\n { identifier },\n { bindingCells },\n label && { label },\n compatible && { compatible },\n\n resolveBehaviorBindings(node)\n )\n }\n\n legacyParseNodes () {\n return this.nodes.map(node => this.extractNode(node))\n }\n\n updateNodeProperties (index, update, existing) {\n const { properties } = update\n const compatible = findNodeProperty(this.nodes[index], 'compatible')?.namedChildren[1].text.slice(1, -1)\n const schema = behaviorSchemas[compatible]\n\n for (const name in properties) {\n const prop = properties[name]\n const propSchema = schema?.properties?.[name]\n\n if (!isEqual(prop, existing.properties[name])) {\n const serialized = propSchema && !prop.useRaw\n ? (\n // Not ideal to have this type-check here, but our handling of this\n // type goes beyond devicetree.\n propSchema.type !== 'phandle-array'\n ? serializePropertyFromSchema(prop, propSchema)\n : prop.parsed\n .map(binding => encodeKeyBinding(binding))\n .map(bindString => `<${bindString}>`)\n .join(', ')\n )\n : prop.raw\n\n this.document.setProperty(this.nodes[index], name, serialized)\n }\n }\n }\n\n cleanupNodeProperties (index, update, existing) {\n for (const prop in existing.properties) {\n if (!(prop in update.properties)) {\n this.document.deleteProperty(this.nodes[index], prop)\n }\n }\n }\n}\n\nmodule.exports = BehaviorCollection\n","const isEqual = require('lodash/isEqual')\n\nconst {\n findNodeWithCompatible,\n findNodesWithCompatible,\n getLabeledItem,\n getNodeLabels,\n parsePropertiesFromSchema,\n serializePropertyFromSchema\n} = require('devicetree/lib/helpers')\nconst { NodeCollection } = require('devicetree/lib/node-collection')\n\nconst { groupPhandleArrayBindings, parseKeyBinding, encodeKeyBinding } = require('../bindings')\n\n// TODO: extract the `zmk,combos` schema and handle the `childProperties` prop\nconst comboSchema = {\n bindings: { type: 'phandle-array' },\n 'key-positions': { type: 'array' },\n 'timeout-ms': { type: 'int' },\n 'slow-release': { type: 'boolean' },\n layers: { type: 'array' }\n}\n\nclass ComboCollection extends NodeCollection {\n managedProperties = [\n 'bindings',\n 'key-positions',\n 'timeout-ms',\n 'layers',\n 'slow-release'\n ]\n\n lookupContainerNode () {\n return findNodeWithCompatible(this.document.tree.rootNode, 'zmk,combos')\n }\n\n injectContainerNode () {\n // TODO: this sucks and is making many other things worse.\n // I've encountered keymap files that specify multiple root devicetree nodes\n // which ZMK accepts and merges together, and multiple keymap nodes which\n // devicetree accepts and selects the last one.\n // Working around this is a pain in the ass and is hurting performance so\n // the best thing to do is stop supporting this and present a warning to the\n // user explaining why their keymap isn't being parsed as expected.\n const keymap = findNodesWithCompatible(this.document.tree.rootNode, 'zmk,keymap').at(-1)\n this.document.insertTextBeforeNode(keymap, `\n combos {\n compatible = \"zmk,combos\";\n };\n `)\n }\n\n lookupNodes () {\n if (!this.container) {\n return []\n }\n\n return this.container.namedChildren.reduce((nodes, syntaxNode) => {\n if (syntaxNode.type === 'labeled_item') {\n syntaxNode = getLabeledItem(syntaxNode)\n }\n if (syntaxNode.type === 'node') {\n nodes.push(syntaxNode)\n }\n\n return nodes\n }, [])\n }\n\n injectNode (_, combo) {\n const name = combo.name.replace(/[^a-zA-Z0-9_]/g, '_')\n const last = this.nodes.at(-1)\n const nodeContent = `${name} {};`\n\n if (last) {\n this.document.insertTextAfterNode(last, nodeContent)\n } else {\n this.document.addChildNode(this.container, nodeContent)\n }\n }\n\n updateNodeProperties (index, update, existing) {\n const { properties } = update\n for (const name in properties) {\n const prop = properties[name]\n const propSchema = comboSchema[name]\n\n if (!isEqual(prop, existing.properties[name])) {\n const serialized = propSchema && !prop.useRaw\n ? (\n // Not ideal to have this type-check here, but our handling of this\n // type goes beyond devicetree.\n propSchema.type !== 'phandle-array'\n ? serializePropertyFromSchema(prop, propSchema)\n : prop.parsed\n .map(binding => encodeKeyBinding(binding))\n .map(bindString => `<${bindString}>`)\n .join(', ')\n )\n : prop.raw\n\n this.document.setProperty(this.nodes[index], name, serialized)\n }\n }\n\n if (!update.properties.layers) {\n this.document.deleteProperty(this.nodes[index], 'layers')\n }\n }\n\n extractNode (node) {\n const name = node.childForFieldName('name').text\n const labels = getNodeLabels(node)\n const properties = parsePropertiesFromSchema(node, comboSchema)\n\n if (properties.bindings) {\n properties.bindings.parsed = (\n groupPhandleArrayBindings(properties.bindings.parsed)\n .map(parseKeyBinding)\n )\n }\n\n return { name, labels, properties }\n }\n\n legacyParse (node) {\n const { name, labels, properties } = this.extractNode(node)\n const legacyNode = {\n name,\n labels,\n properties,\n identifier: name\n }\n\n const legacyMapping = {\n bindings: 'bindings',\n 'timeout-ms': 'timeoutMs',\n 'key-positions': 'keyPositions',\n 'slow-release': 'slowRelease',\n layers: 'layers'\n }\n\n for (const prop of Object.keys(legacyMapping)) {\n if (properties[prop]) {\n legacyNode[legacyMapping[prop]] = properties[prop].parsed\n }\n }\n\n if (legacyNode.layers?.length === 0 || isEqual(legacyNode.layers, [-1])) {\n delete legacyNode.layers\n }\n\n return legacyNode\n }\n\n legacyParseNodes () {\n return this.nodes.map(node => this.legacyParse(node))\n }\n}\n\nmodule.exports = ComboCollection\n","const difference = require('lodash/difference')\nconst filter = require('lodash/filter')\nconst isEqual = require('lodash/isEqual')\nconst map = require('lodash/map')\n\nconst {\n findChildrenByIdentifier,\n findNodesWithCompatible,\n getLabeledItem,\n getNodeLabels,\n parsePropertiesFromSchema,\n serializePropertyFromSchema\n} = require('devicetree/lib/helpers')\nconst { NodeCollection } = require('devicetree/lib/node-collection')\n\nconst { groupPhandleArrayBindings, parseKeyBinding, encodeKeyBinding } = require('../bindings')\n\nfunction isSorted (array) {\n return array.every((value, i, arr) => (\n i === arr.length - 1 ||\n arr[i] < arr[i + 1]\n ))\n}\n\n// TODO: extract the `zmk,keymap` schema and handle the `childProperties` prop\nconst layerSchema = {\n label: {\n type: 'string'\n },\n bindings: {\n type: 'phandle-array'\n },\n 'sensor-bindings': {\n type: 'phandle-array'\n }\n}\n\nclass LayerCollection extends NodeCollection {\n managedProperties = [\n 'label',\n 'bindings',\n 'sensor-bindings'\n ]\n\n lookupContainerNode () {\n return findNodesWithCompatible(this.document.tree.rootNode, 'zmk,keymap').at(-1)\n }\n\n injectContainerNode () {\n const rootNodes = findChildrenByIdentifier(this.document.tree.rootNode, '/')\n this.document.addChildNode(\n rootNodes.at(-1),\n '\\nkeymap { compatible = \"zmk,keymap\"; };\\n'\n )\n }\n\n lookupNodes () {\n if (!this.container) {\n return []\n }\n\n return this.container.namedChildren.reduce((nodes, syntaxNode) => {\n if (syntaxNode.type === 'labeled_item') {\n syntaxNode = getLabeledItem(syntaxNode)\n }\n if (syntaxNode.type === 'node') {\n nodes.push(syntaxNode)\n }\n\n return nodes\n }, [])\n }\n\n injectNode (_, layer) {\n const last = this.nodes.at(-1)\n const name = (layer.name || 'new_layer').replace(/[^a-zA-Z0-9_]/g, '_')\n const nodeContent = `${name} {};`\n\n if (last) {\n this.document.insertTextAfterNode(last, nodeContent)\n } else {\n this.document.addChildNode(this.container, nodeContent)\n }\n }\n\n updateCollection (collection) {\n const originalIndices = [...this.nodes.keys()]\n\n super.updateCollection(collection)\n this.updateLayerPositions(collection, originalIndices)\n }\n\n /**\n * Sort layer nodes according to the updates array ordering.\n * This could perhaps be implemented generically in NodeCollection or even in\n * DevicetreeDocument but that's complicated, especially considering scenarios\n * like BehaviorCollection and MacroCollection which may be dealing with nodes\n * that are subsets of a single nodes children, or even nodes that aren't even\n * children of the same parent.\n *\n * For now it only makes sense for layer nodes to be sortable, so here you go.\n *\n * @param {Array<Object>} updates same argument passed to updateCollection\n * @param {Array<Integer>} originalIndices node indices from before updates were applied\n */\n updateLayerPositions (updates, originalIndices) {\n const reusedIndices = filter(map(updates, 'index'), index => this.nodes[index])\n const removedIndices = difference(originalIndices, reusedIndices)\n const positionMap = [...originalIndices]\n\n // Add new nodes to the end of the position map. Their current position does\n // not matter because they're already sorted relative to eachother and the\n // mapping will let us reorder everything at the end.\n for (const index in updates) {\n const update = updates[index]\n const nextIndex = positionMap.length\n if (update.index === undefined || !originalIndices.includes(update.index)) {\n update.index = nextIndex\n positionMap[nextIndex] = nextIndex\n }\n }\n\n // Shift every mapped position for nodes following removed nodes.\n for (let i = removedIndices.length - 1; i >= 0; --i) {\n const index = removedIndices[i]\n positionMap[index] = null\n for (let j = index + 1; j < positionMap.length; j++) {\n if (positionMap[j] !== null) {\n positionMap[j] -= 1\n }\n }\n }\n\n const targetIndexOrder = map(updates, 'index')\n if (targetIndexOrder.length > 0 && !isSorted(targetIndexOrder)) {\n this.document.flushChanges()\n this.document.replaceRange(\n this.nodes[0].startIndex,\n this.nodes.at(-1).endIndex,\n targetIndexOrder\n .map(index => positionMap[index])\n .map(index => this.nodes[index].text)\n .join('\\n')\n )\n }\n }\n\n updateNodeProperties (index, update, existing) {\n const { properties } = update\n for (const name in properties) {\n const prop = properties[name]\n const propSchema = layerSchema[name]\n\n if (!isEqual(prop, existing.properties[name])) {\n const serialized = propSchema && !prop.useRaw\n ? (\n // Not ideal to have this type-check here, but our handling of this\n // type goes beyond devicetree.\n propSchema.type !== 'phandle-array'\n ? serializePropertyFromSchema(prop, propSchema)\n : prop.parsed\n .map(binding => encodeKeyBinding(binding))\n .map(bindString => `<${bindString}>`)\n .join(', ')\n )\n : prop.raw\n\n this.document.setProperty(this.nodes[index], name, serialized)\n }\n }\n }\n\n extractNode (node) {\n const name = node.childForFieldName('name').text\n const labels = getNodeLabels(node)\n const properties = parsePropertiesFromSchema(node, layerSchema)\n\n if (properties.bindings) {\n properties.bindings.parsed = (\n groupPhandleArrayBindings(properties.bindings.parsed)\n .map(parseKeyBinding)\n )\n }\n\n if (properties['sensor-bindings']) {\n properties['sensor-bindings'].parsed = (\n groupPhandleArrayBindings(properties['sensor-bindings'].parsed)\n .map(parseKeyBinding)\n )\n }\n\n return { name, labels, properties }\n }\n\n legacyParse (node) {\n const { name, labels, properties } = this.extractNode(node)\n const legacyNode = {\n name,\n labels,\n properties,\n identifier: name\n }\n\n if (properties.label) {\n legacyNode.label = properties.label.parsed\n }\n if (properties.bindings) {\n legacyNode.bindings = properties.bindings.parsed\n }\n if (properties['sensor-bindings']) {\n legacyNode.sensorBindings = properties['sensor-bindings'].parsed\n }\n\n return legacyNode\n }\n\n legacyParseNodes () {\n return this.nodes.map(node => this.legacyParse(node))\n }\n}\n\nmodule.exports = LayerCollection\n","const pick = require('lodash/pick')\n\nconst {\n findChildByIdentifier,\n findChildrenByIdentifier,\n findNodesWithCompatible\n} = require('devicetree/lib/helpers')\nconst { NodeCollection } = require('devicetree/lib/node-collection')\n\nconst BehaviorCollection = require('./behaviors')\nconst { groupMacroBindings, encodeKeyBinding } = require('../bindings')\n\nclass MacroCollection extends BehaviorCollection {\n managedProperties = [\n 'label',\n 'tap-ms',\n 'wait-ms'\n ]\n\n lookupContainerNode () {\n const rootNodes = findChildrenByIdentifier(this.document.tree.rootNode, '/')\n return findChildByIdentifier(rootNodes, 'macros')\n }\n\n injectContainerNode () {\n const keymap = findNodesWithCompatible(this.document.tree.rootNode, 'zmk,keymap').at(-1)\n this.document.insertTextBeforeNode(keymap, '\\nmacros {};\\n')\n }\n\n lookupNodes () {\n return findNodesWithCompatible(\n this.document.tree.rootNode,\n 'zmk,behavior-macro'\n )\n }\n\n injectNode (_, macro) {\n const name = macro.name.replace(/[^a-zA-Z0-9_]/g, '_')\n const last = this.nodes.at(-1)\n const nodeContent = (\n `${name}: ${name} {\n compatible = \"zmk,behavior-macro\";\n };`\n )\n\n if (last) {\n this.document.insertTextAfterNode(last, nodeContent)\n } else {\n this.document.addChildNode(this.container, nodeContent)\n }\n }\n\n updateNode (index, update) {\n const serialized = serializeMacroBindings(update.properties.bindings?.parsed || [])\n update.properties.bindings = {\n useRaw: true,\n raw: serialized\n }\n\n super.updateNode(index, update)\n }\n\n legacyParse (node) {\n return pick(this.extractNode(node), ['name', 'labels', 'properties'])\n }\n\n legacyParseNodes () {\n return this.nodes.map(node => this.legacyParse(node))\n }\n\n cleanupNodeProperties (index, update, existing) {\n const { cleanupNodeProperties } = NodeCollection.prototype\n return cleanupNodeProperties.call(this, index, update, existing)\n }\n}\n\nfunction serializeMacroBindings (bindings) {\n const serialized = groupMacroBindings(\n bindings.map(encodeKeyBinding)\n ).map(row => row.join(' '))\n\n return serialized.length === 1\n ? [`<${serialized[0]}>`]\n : serialized.map(row => `<${row}>`)\n}\n\nmodule.exports = MacroCollection\n","const filter = require('lodash/filter')\nconst last = require('lodash/last')\nconst reverse = require('lodash/reverse')\n\nconst { DevicetreeDocument } = require('devicetree')\nconst {\n nodesAreConsecutive,\n findChildByIdentifier,\n findChildrenByIdentifier,\n getLabeledItem\n} = require('devicetree/lib/helpers')\nconst { standardBehaviorIncludeFiles } = require('zmk-data/behaviors')\n\nconst MacroCollection = require('./collections/macros')\nconst ComboCollection = require('./collections/combos')\nconst LayerCollection = require('./collections/layers')\nconst BehaviorCollection = require('./collections/behaviors')\n\nclass KeymapDocument extends DevicetreeDocument {\n constructor (...args) {\n super(...args)\n this.macroCollection = new MacroCollection(this)\n this.comboCollection = new ComboCollection(this)\n this.layerCollection = new LayerCollection(this)\n this.behaviorCollection = new BehaviorCollection(this)\n }\n\n cleanup () {\n super.cleanup()\n delete this.layerCollection\n delete this.comboCollection\n delete this.macroCollection\n delete this.behaviorCollection\n }\n\n getChosenProperties () {\n const rootNodes = findChildrenByIdentifier(this.tree.rootNode, '/')\n const chosen = findChildByIdentifier(rootNodes, 'chosen')\n\n if (!chosen) {\n return {}\n }\n\n return chosen.namedChildren.reduce((acc, child) => {\n if (child.type === 'labeled_item') {\n child = getLabeledItem(child)\n }\n if (child.type === 'property') {\n const name = child.childForFieldName('name').text\n const value = child.childForFieldName('value').text\n acc[name] = value\n }\n\n return acc\n }, {})\n }\n\n mergeUpdated (updated, featureFlags = {}) {\n this.layerCollection.updateCollection(updated.layers)\n this.comboCollection.updateCollection(updated.combos)\n this.macroCollection.updateCollection(updated.macros)\n\n if (featureFlags.enableBehaviorEditing) {\n this.behaviorCollection.updateCollection(updated.behaviors)\n }\n }\n\n replaceBehaviourIncludes (updated) {\n const replacementText = updated.join('\\n') + '\\n'\n const behaviorIncludes = this.tree.rootNode.namedChildren.filter(node => (\n node.type === 'preproc_include' &&\n // TODO: update behavior overlays to just specify the include path and not\n // the include pre-processor statement. `startsWith` is necessary here\n // because preproc_include node parsing includes trailing newline(s).\n standardBehaviorIncludeFiles.some(line => node.text.startsWith(line))\n ))\n\n if (behaviorIncludes.length) {\n if (nodesAreConsecutive(behaviorIncludes)) {\n this.replaceRange(\n behaviorIncludes[0].startIndex,\n behaviorIncludes.at(-1).endIndex,\n ''\n )\n } else {\n for (const node of reverse(behaviorIncludes)) {\n this.removeNode(node)\n }\n }\n }\n\n const lastInclude = last(filter(\n this.tree.rootNode.children,\n { type: 'preproc_include' }\n ))\n const firstDefine = this.tree.rootNode.children.find(node => node.type === 'preproc_def')\n const firstDtNode = this.tree.rootNode.children.find(node => node.type === 'node')\n\n if (lastInclude) {\n this.insertTextAfterNode(lastInclude, replacementText)\n } else if (firstDefine || firstDtNode) {\n this.insertTextBeforeNode(\n firstDefine || firstDtNode,\n replacementText\n )\n }\n }\n}\n\nmodule.exports = KeymapDocument\n","const { getPropertyValues } = require('devicetree/lib/helpers/properties')\n\nconst MISSING_ROOT_NODE = 'MISSING_ROOT_NODE'\nconst USING_ZMK_NODEFREE_MACROS = 'USING_ZMK_NODEFREE_MACROS'\nconst USING_ZMK_MACRO_MACRO = 'USING_ZMK_MACRO_MACRO'\nconst USING_MULTIPLE_ROOT_NODES = 'USING_MULTIPLE_ROOT_NODES'\nconst USING_MIRYOKU_DTSI = 'USING_MIRYOKU_DTSI'\nconst USING_NON_ZMK_MACRO = 'USING_NON_ZMK_MACRO'\n\nfunction keymapUsesNodefreeConfigHelpers (document) {\n const macroNames = [\n 'ZMK_BEHAVIOR',\n 'ZMK_COMBO',\n 'ZMK_CONDITIONAL_LAYER',\n 'ZMK_LAYER',\n 'UC_MACRO'\n ]\n\n for (const node of document.tree.rootNode.namedChildren) {\n if (node.type === 'ERROR') {\n const { text } = node\n if (macroNames.some(name => text.startsWith(name))) {\n return USING_ZMK_NODEFREE_MACROS\n }\n }\n }\n}\n\nfunction keymapUsesMiryoku (document) {\n for (const node of document.tree.rootNode.namedChildren) {\n if (node.type === 'preproc_include') {\n if (node.childForFieldName('path').text.includes('miryoku.dtsi')) {\n return USING_MIRYOKU_DTSI\n }\n }\n }\n}\n\nfunction keymapBindingsUsePreprocessorMacros (document) {\n const zmkPreprocFunctions = [\n 'LA', 'LC', 'LG', 'LS',\n 'RA', 'RC', 'RG', 'RS',\n 'RGB_COLOR_HSB'\n ]\n\n for (const layerNode of document.layerCollection.nodes) {\n const [bindingsNode] = getPropertyValues(layerNode, 'bindings')\n const nonZmkPreprocFunction = bindingsNode.namedChildren.find(node => (\n node.type === 'call_expression' &&\n !zmkPreprocFunctions.includes(node.childForFieldName('function').text)\n ))\n\n if (nonZmkPreprocFunction) {\n return USING_NON_ZMK_MACRO\n }\n }\n}\n\nfunction keymapHasNoRootNodes (document) {\n for (let node of document.tree.rootNode.namedChildren) {\n if (node.type === 'labeled_item') {\n node = node.childForFieldName('item')\n }\n if (node.type === 'node' && node.childForFieldName('name').text === '/') {\n return\n }\n }\n\n return MISSING_ROOT_NODE\n}\n\n/**\n * Check if a devicetree document uses multiple root nodes.\n *\n * People sometimes organize different parts of a keymap (like behaviors and\n * combos) into separate instances of a root node. The devicetree compiler will\n * merge these root nodes into one, but preserving this for editing is annoying\n * and inefficient so I don't want to support it anymore.\n *\n * @param {DevicetreeDocument} document\n * @returns {String|undefined}\n */\nfunction keymapHasMultipleRootNodes (document) {\n let firstRootNode = null\n\n for (let node of document.tree.rootNode.namedChildren) {\n if (node.type === 'labeled_item') {\n node = node.childForFieldName('item')\n }\n if (node.type === 'node' && node.childForFieldName('name').text === '/') {\n if (firstRootNode !== null) {\n return USING_MULTIPLE_ROOT_NODES\n }\n\n firstRootNode = node\n }\n }\n}\n\n/**\n * This is just a last-ditch check to see if keymap parsing failed because of a\n * custom define that replaced the initial binding cell's behavior. This would\n * otherwise be caught by `keymapBindingsUsePreprocessorMacros` except that the\n * initial grouping fails.\n * @param {DevicetreeDocument} document\n */\nfunction keymapHasLayerBindingsWithNonBehaviorStarter (document) {\n return document.layerCollection.nodes.some(node => {\n const bindingCells = [].concat(...getPropertyValues(node, 'bindings'))\n .flatMap(integerCells => integerCells.namedChildren)\n const firstBindType = bindingCells[0]?.type\n\n return firstBindType && firstBindType !== 'reference'\n })\n}\n\nmodule.exports = {\n keymapHasNoRootNodes,\n keymapUsesNodefreeConfigHelpers,\n keymapUsesMiryoku,\n keymapBindingsUsePreprocessorMacros,\n keymapHasMultipleRootNodes,\n keymapHasLayerBindingsWithNonBehaviorStarter,\n warningFlags: {\n MISSING_ROOT_NODE,\n USING_ZMK_NODEFREE_MACROS,\n USING_ZMK_MACRO_MACRO,\n USING_MULTIPLE_ROOT_NODES,\n USING_MIRYOKU_DTSI,\n USING_NON_ZMK_MACRO\n }\n}\n","const compact = require('lodash/compact')\nconst { getParser } = require('devicetree')\nconst { resolveBehaviorParams } = require('zmk-data/parameters')\n\nconst KeymapDocument = require('./devicetree/keymap-document')\nconst {\n keymapUsesNodefreeConfigHelpers,\n keymapUsesMiryoku,\n keymapBindingsUsePreprocessorMacros,\n keymapHasNoRootNodes,\n keymapHasLayerBindingsWithNonBehaviorStarter,\n warningFlags: { USING_NON_ZMK_MACRO }\n} = require('./devicetree/sanity-checks')\nconst { parseStringLiteral } = require('devicetree/lib/helpers/values')\n\nasync function extractKeymapData (keymapText) {\n const parser = await getParser()\n const document = new KeymapDocument(parser, keymapText)\n\n try {\n // Behaviors need post-processing to determine types for their binding cells\n const behaviors = document.behaviorCollection.legacyParseNodes()\n resolveBehaviorParams(behaviors)\n\n return {\n warningFlags: extractWarnings(document),\n defines: extractDefines(document),\n headers: extractLocalHeaders(document),\n chosen: document.getChosenProperties(),\n behaviors,\n layers: document.layerCollection.legacyParseNodes(),\n combos: document.comboCollection.legacyParseNodes(),\n macros: document.macroCollection.legacyParseNodes()\n }\n } catch (err) {\n if (keymapHasLayerBindingsWithNonBehaviorStarter(document)) {\n return {\n warningFlags: [USING_NON_ZMK_MACRO],\n defines: {},\n headers: [],\n chosen: {},\n behaviors: [],\n layers: [],\n combos: [],\n macros: []\n }\n }\n console.error(err)\n return {\n warningFlags: ['KEYMAP_PARSING_FAILED'],\n defines: {},\n headers: [],\n chosen: {},\n behaviors: [],\n layers: [],\n combos: [],\n macros: []\n }\n } finally {\n document.cleanup()\n }\n}\n\nfunction extractWarnings (document) {\n return compact([\n keymapHasNoRootNodes(document),\n keymapUsesNodefreeConfigHelpers(document),\n keymapUsesMiryoku(document),\n keymapBindingsUsePreprocessorMacros(document)\n ])\n}\n\nfunction extractDefines (document) {\n return document.tree.rootNode.namedChildren.reduce((acc, node) => {\n if (node.type === 'preproc_def') {\n const name = node.childForFieldName('name').text\n const value = node.childForFieldName('value')?.text.trim()\n\n acc[name] = value\n }\n\n return acc\n }, {})\n}\n\nfunction extractLocalHeaders (document) {\n return document.tree.rootNode.namedChildren.reduce((acc, node) => {\n if (node.type === 'preproc_include') {\n const path = node.childForFieldName('path')\n if (path.type === 'string_literal') {\n acc.push(parseStringLiteral(path))\n }\n }\n\n return acc\n }, [])\n}\n\nmodule.exports = extractKeymapData\n","const omitBy = require('lodash/omitBy')\nconst renderLayout = require('keymap-layout-tools/lib/render')\n\nconst { encodeKeyBinding } = require('./devicetree/bindings')\n\nclass KeymapValidationError extends Error {\n constructor (errors) {\n super()\n this.name = 'KeymapValidationError'\n this.errors = errors\n }\n}\n\n// TODO: Rename this to something like \"hydrate\"?\nfunction encodeKeymap (layout, parsedKeymap) {\n /*\n This should basically become the standard format for a keymap when passed\n around the various layers of the backend.\n\n TODO: what do I want to do about keymap.json formatting? Should I call this a\n new version and update existing files on-the-fly?\n\n Also layer_names should be removed and the name (idenfitier?) + \"label\" should\n be given in the layer object.\n\n We can also analyze the unique set of behaviours used across all layers to\n determine ahead of time which headers to include.\n */\n return Object.assign({}, parsedKeymap, {\n layers: encodeLayers(parsedKeymap.layers, layout),\n combos: encodeCombos(parsedKeymap.combos)\n })\n}\n\nfunction encodeLayers (layers, layout) {\n return layers.map(layer => {\n // Newly created layers will specify name instead of identifier but still\n // use `layer.bindings` and `layer.label`\n if (layer.identifier || layer.bindings) {\n layer = {\n index: layer.index,\n name: layer.identifier || layer.name,\n labels: [],\n properties: {\n label: layer.label && { parsed: layer.label },\n bindings: layer.bindings && { parsed: layer.bindings },\n 'sensor-bindings': layer.sensorBindings && { parsed: layer.sensorBindings }\n }\n }\n }\n\n if (layer.properties.bindings?.parsed) {\n const { parsed } = layer.properties.bindings\n layer.properties.bindings = {\n parsed,\n useRaw: true,\n raw: `<\\n${renderLayout(layout, parsed.map(encodeKeyBinding))}\\n>`\n }\n }\n\n if (layer.properties.label && !layer.properties.label.parsed) {\n delete layer.properties.label\n }\n\n layer.properties = omitBy(layer.properties, value => !value)\n\n return layer\n })\n}\n\nfunction encodeCombos (combos) {\n return combos.map(combo => {\n if (combo.identifier) {\n combo = {\n index: combo.index,\n name: combo.identifier,\n labels: [],\n properties: {\n bindings: combo.bindings && { parsed: combo.bindings },\n 'key-positions': combo.keyPositions && { parsed: combo.keyPositions },\n 'timeout-ms': combo.timeoutMs && { parsed: combo.timeoutMs },\n 'slow-release': combo.slowRelease && { parsed: combo.slowRelease },\n layers: combo.layers?.length && { parsed: combo.layers }\n }\n }\n }\n\n combo.properties = omitBy(combo.properties, value => !value)\n\n if (!combo.properties.layers?.parsed?.length) {\n delete combo.properties.layers\n }\n\n return combo\n })\n}\n\nfunction parseKeymap (keymap) {\n // TODO: move all of this into extractKeymapData\n return Object.assign({}, keymap, {\n layers: keymap.layers.map((layer, i) => ({ ...layer, index: i })),\n combos: keymap.combos.map((combo, i) => ({ ...combo, index: i })),\n macros: keymap.macros.map((macro, i) => ({ ...macro, index: i })),\n behaviors: keymap.behaviors.map((behavior, i) => ({ ...behavior, index: i }))\n })\n}\n\nmodule.exports = {\n KeymapValidationError,\n encodeKeymap,\n encodeLayers,\n encodeCombos,\n parseKeymap\n}\n","const times = require('lodash/times')\n\nfunction renderLayout (layout, layer, opts = {}) {\n const { margin = 2 } = opts\n const table = layer.reduce((map, code, i) => {\n // TODO: this would be better as a loop over `layout`, checking for a\n // matching element in the `layer` array. Or, alternatively, an earlier\n // validation that asserts each layer is equal in length to the number of\n // keys in the layout.\n if (layout[i]) {\n const { row = 0, col } = layout[i]\n map[row] = map[row] || []\n map[row][col || map[row].length] = code\n }\n\n return map\n }, [])\n\n const rowIndices = Object.keys(table)\n const columns = Math.max(...rowIndices.map(i => table[i].length))\n const columnIndices = times(columns, n => n)\n const columnWidths = columnIndices.map(col => Math.max(\n ...rowIndices.map(row => table[row][col]?.length || 0)\n ))\n\n return table.map((row, i) => {\n return columnIndices.map(i => {\n const noMoreValues = row.slice(i).every(col => col === undefined)\n const padding = columnWidths[i] + (\n i === 0 ? '' : margin\n )\n\n if (noMoreValues) return ''\n if (!row[i]) return ' '.repeat(padding)\n return row[i].padStart(padding)\n }).join('').replace(/\\s+$/, '')\n }).join('\\n')\n}\n\nmodule.exports = renderLayout\n","/**\n * Remove common indentation from lines of a multiline string\n * @param {String} text a multiline string\n * @returns {String}\n */\nfunction dedent (text) {\n return _dedentedLines(text).join('\\n')\n}\n\nfunction _dedentedLines (text) {\n const lines = text.split('\\n')\n const minIndentation = lines.reduce((leastIndentation, line) => {\n const match = line.match(/^(\\s*)\\S/)\n\n if (!match) {\n return leastIndentation\n }\n\n return Math.min(leastIndentation, match[1].length)\n }, Infinity)\n\n return lines.map(line => (\n line.slice(0, minIndentation).match(/^\\s+$/)\n ? line.slice(minIndentation)\n : line\n ))\n}\n\n/**\n * Replace base indentation with a custom indentation string on all lines\n * @param {String} text\n * @param {String} indentation\n * @returns {String}\n */\nfunction reindent (text, indentation) {\n return _dedentedLines(text)\n .map(line => indentation + line)\n .join('\\n')\n}\n\nfunction getPosition (text, index) {\n let row, idx\n for (\n row = 0, idx = 0;\n idx !== -1;\n row++, idx = text.indexOf('\\n', idx + 1)\n );\n\n return { row, col: index - idx }\n}\n\nfunction removeStartingWhitespace (text) {\n return text.split('\\n')\n .reduce((lines, line) => {\n if (lines.length > 0 || line.match(/\\S/)) {\n lines.push(line)\n }\n return lines\n }, [])\n .join('\\n')\n}\n\nfunction removeTrailingWhitespace (text) {\n return text.split('\\n')\n .reverse()\n .reduce((lines, line) => {\n if (lines.length > 0 || line.match(/\\S/)) {\n lines.push(line)\n }\n return lines\n }, [])\n .reverse()\n .join('\\n')\n}\n\nmodule.exports = {\n dedent,\n reindent,\n getPosition,\n removeStartingWhitespace,\n removeTrailingWhitespace\n}\n","const merge = require('lodash/merge')\nconst isMatch = require('lodash/isMatch')\nconst uniq = require('lodash/uniq')\n\n/** @typedef {('string' | 'boolean' | 'int' | 'array' | 'phandle' | 'phandles' | 'phandle-array' | 'integer-union')} PropertyType */\n/** @typedef {{ type: PropertyType, required?: boolean, const?: any, default?: any, enum?: Array<any>, description?: string }} PropertyDefinition */\n/** @typedef {Object.<string, PropertyDefinition>} Properties */\n/** @typedef {{ description?: string, compatible: string, include: string, properties: Properties }} BehaviorSchema */\n/** @typedef {Object.<string, BehaviorSchema} BehaviorSchemas */\n/** @typedef {} BehaviorSchema */\n\n/** @type {BehaviorSchemas} */\nconst behaviorSchemas = require('./data/extracted-data/behavior-schemas.json')\n/** @type {BehaviorSchemas} */\nconst behaviorSchemaAdditions = require('./data/overlay-data/behavior-schemas-additions.json')\n\n/** @typedef {{ parsed: any, raw: string, useRaw?: boolean }} PropertyValue */\n/** @typedef {Object.<string, PropertyValue} ParsedProperties */\n/** @typedef {{ code: string, compatible: string, '#binding-cells': number, properties: ParsedProperties }} Behavior */\n\n/** @type {Array<Behavior>} */\nconst behaviorBindings = require('./data/extracted-data/behaviors.json')\n/** @type {Array<Behavior>} */\nconst behaviorAdditions = require('./data/overlay-data/behaviors-additions.json')\nconst behaviorSchemaOverlays = require('./data/overlay-data/behavior-schemas-overlay.json')\nconst behaviorOverlays = require('./data/overlay-data/behaviors-overlay.json')\n\nObject.assign(behaviorSchemas, behaviorSchemaAdditions)\nbehaviorBindings.push(...behaviorAdditions)\n\nfunction mergeBehaviorOverlays (base, overlays) {\n const baseValues = Array.isArray(base) ? base : Object.values(base)\n\n for (const value of baseValues) {\n for (const { match, ...overlay } of overlays) {\n if (isMatch(value, match)) {\n merge(value, overlay)\n }\n }\n }\n}\n\nmergeBehaviorOverlays(behaviorSchemas, behaviorSchemaOverlays)\nmergeBehaviorOverlays(behaviorBindings, behaviorOverlays)\n\nconst standardBehaviorIncludeFiles = uniq(\n behaviorOverlays.flatMap(overlay => overlay.includes || [])\n)\n\nfor (const behavior of behaviorBindings) {\n const schema = behaviorSchemas[behavior.compatible]\n merge(behavior, { schema })\n}\n\nmodule.exports = {\n behaviorSchemas,\n behaviorBindings,\n behaviorOverlays,\n behaviorSchemaOverlays,\n standardBehaviorIncludeFiles,\n mergeBehaviorOverlays\n}\n","const singleValue = value => ({ value: '&kp', params: [{ value, params: [] }] })\n\nconst patternMappings = [\n { pattern: /^[0-9]$/, convert: digit => singleValue(`N${digit}`) },\n { pattern: /^[a-z]$/, convert: char => singleValue(char.toUpperCase()) },\n {\n pattern: /^[A-Z]$/,\n convert: char => ({\n value: '&kp',\n params: [{\n value: 'LS',\n params: [{\n value: char.toUpperCase(),\n params: []\n }]\n }]\n })\n }\n]\n\nconst simpleMappings = {\n '!': singleValue('EXCL'),\n '@': singleValue('AT'),\n '#': singleValue('POUND'),\n '$': singleValue('DLLR'),\n '%': singleValue('PRCNT'),\n '^': singleValue('CARET'),\n '&': singleValue('AMPS'),\n '*': singleValue('STAR'),\n '(': singleValue('LPAR'),\n ')': singleValue('RPAR'),\n '\\n': singleValue('RET'),\n ' ': singleValue('SPACE'),\n '-': singleValue('MINUS'),\n '_': singleValue('UNDER'),\n '=': singleValue('EQUAL'),\n '+': singleValue('PLUS'),\n '[': singleValue('LBKT'),\n ']': singleValue('LBRC'),\n '{': singleValue('RBKT'),\n '}': singleValue('RBRC'),\n '\\\\': singleValue('BSLH'),\n '|': singleValue('PIPE'),\n '': singleValue('TILDE2'),\n ';': singleValue('SEMI'),\n ':': singleValue('COLON'),\n '\\'': singleValue('SQT'),\n '\"': singleValue('DQT'),\n '`': singleValue('GRAVE'),\n '~': singleValue('TILDE'),\n ',': singleValue('COMMA'),\n '<': singleValue('LT'),\n '.': singleValue('DOT'),\n '>': singleValue('GT'),\n '/': singleValue('FSLH'),\n '?': singleValue('QMARK')\n}\n\nfunction mapCharacter (char) {\n if (simpleMappings[char]) {\n return simpleMappings[char]\n }\n\n for (const { pattern, convert } of patternMappings) {\n if (char.match(pattern)) {\n return convert(char)\n }\n }\n}\n\nmodule.exports = {\n mapCharacter\n}\n","const keycodes = require('./data/extracted-data/keycodes.json')\nconst keycodeGlyphs = {\n basic: require('./data/overlay-data/keycode-glyphs.json'),\n unicode: require('./data/overlay-data/keycode-glyphs-unicode.json'),\n platforms: {\n mac: require('./data/overlay-data/keycode-glyphs-macos.json'),\n win: require('./data/overlay-data/keycode-glyphs-windows.json')\n }\n}\n\nmodule.exports = {\n keycodes,\n keycodeGlyphs\n}\n","const times = require('lodash/times')\nconst { behaviorSchemas, behaviorBindings } = require('./behaviors')\n\n/**\n * Parsing keymap gives us a number of custom behaviour definitions\n * Some custom behaviours may reference other behaviours\n * Some custom behaviours may reference other custom behaviours\n *\n * We need to add all new behaviour to a new map upon loading\n * After populating the map with all new behaviours we can resolve bind params\n *\n * Keep a list of \"visited\" behaviours\n * For each behaviour\n * For each behaviour referenced in bindings\n * Resolve behaviour reference to get params list\n * If behaviour reference already exists in list of visited behaviours, bail\n * If number of references to resolve exceeds X, bail\n */\n\nfunction BehaviorResolutionError (message) {\n this.message = message\n this.name = 'BehaviorResolutionError'\n}\n\n/** @typedef {string} Identifier */\n/** @typedef {string} Label */\n/** @typedef {{ parsed: any, raw: string, useRaw?: boolean }} PropertyValue */\n/** @typedef {Object.<string, PropertyValue>} Properties */\n/** @typedef {{ name: string, labels: Array<string>, properties: Properties }} ParsedBehavior */\n\nfunction parseNumBindingCells (behavior, prop = '#binding-cells') {\n const parsed = behavior.properties?.[prop]?.parsed\n\n if (typeof parsed === 'number') {\n return parsed\n }\n\n // For unrecognized behaviors we don't have the schema to parse the\n // \"#binding-cells\" property like we'd expect, so let's assume its a single\n // integer literal and parse the raw value\n const raw = behavior.properties?.[prop]?.raw || '<>'\n const match = raw.match(/<(\\d+)>/)\n\n if (match) {\n return Number(match[1])\n }\n}\n\nfunction behaviorMap (map, behavior) {\n for (const label of behavior.labels) {\n map[`&${label}`] = behavior\n }\n return map\n}\n\n/**\n * Attempt to provide parameter types for behaviours with binding-cells.\n * @param {Array<ParsedBehavior>} behaviors - custom behavior definitions\n */\nfunction resolveBehaviorParams (behaviors) {\n const standardBindingsMap = behaviorBindings.reduce(behaviorMap, {})\n // Here we attempt to resolve the binding to a \"known\" behaviour for which\n // I have already manually described the parameters. Failing that, this\n // would fall back to a single \"code\" parameter for each. This assumes\n // that a custom hold-tap wouldn't want something like \"hold for layer\"\n // and \"tap to connect to BT profile 1\".\n const newBindingsMap = behaviors.reduce(behaviorMap, {})\n\n /**\n * @param {ParsedBehavior} behavior\n * @param {Array<string>} [queue=[]]\n * @returns {void}\n */\n function resolve (behavior, queue = []) {\n if ('params' in behavior) {\n return behavior.params\n }\n\n const compatible = behavior.properties?.compatible?.parsed\n const schema = behaviorSchemas[compatible]\n\n const bindingsType = schema?.properties?.bindings?.type\n const bindingCells = parseNumBindingCells(behavior) ?? parseNumBindingCells(behavior, '#sensor-binding-cells')\n const bindings = (behavior.properties?.bindings?.parsed || [])\n\n // console.log('resolving for', {\n // compatible,\n // schema,\n // bindingsType,\n // bindingCells,\n // bindings\n // })\n\n if (!bindingCells) {\n return []\n }\n\n // A `bindings` prop of type `phandle-array` means the bindings are already\n // given along with binding cell values and don't need further params.\n if (bindingsType === 'phandle-array') {\n return []\n }\n\n if (!bindings.length) {\n return times(bindingCells, () => ({ type: 'string', raw: true }))\n }\n\n // This implementation relies on the existing pattern for behaviors which\n // reference other behaviors without parameters (hold-tap and sticky-key)\n // will only provide a single parameter to each referenced behavior without\n // concerning itself with the referenced behavior's binding cell count.\n // A possible future exception to this is parameterized macros:\n // https://github.com/zmkfirmware/zmk/pull/1232#issuecomment-1478977559\n // This will require re-visiting this solution.\n return bindings.reduce((params, binding) => {\n // This implies the bindings property we're inspecting is actually a\n // phandles-array type (behavior with params) and not phandle/phandles.\n // This shouldn't happen and stricter checking earlier on would be wise.\n if (!binding.startsWith('&')) {\n return params\n }\n\n if (queue.includes(binding)) {\n throw new BehaviorResolutionError(`Circular reference in bindings: \"&${behavior.labels[0]}\" -> \"${binding}\".`)\n } else if (queue.length > 3) {\n throw new BehaviorResolutionError('Reference depth limit exceeded.')\n }\n\n const nextBehavior = newBindingsMap[binding] || standardBindingsMap[binding]\n\n // Not sure if I'm ok with this. Previously the idea was that a behavior\n // referencing an unrecognized behavior cannot resolve parameters at all,\n // whereas now it just treats that as having a single raw parameter and\n // includes an error message property that nothing else uses.\n if (!nextBehavior) {\n behavior.error = `Unrecognized behavior binding \"${binding}\".`\n return [...params, { raw: true }]\n }\n\n try {\n nextBehavior.params = resolve(nextBehavior, [...queue, binding])\n params.push(nextBehavior.params[0] || { type: 'placeholder' })\n } catch (error) {\n if (error instanceof BehaviorResolutionError) {\n nextBehavior.error = error.message\n nextBehavior.params = []\n }\n throw error\n }\n\n return params\n }, [])\n }\n\n for (const behavior of behaviors) {\n // if (!behavior.properties.bindings) {\n // continue\n // }\n\n try {\n behavior.params = resolve(behavior)\n } catch (error) {\n if (!(error instanceof BehaviorResolutionError)) {\n throw error\n }\n\n console.error('Failed to resolve behavior parameters', error)\n behavior.error = error.message\n behavior.params = times(parseNumBindingCells(behavior) || 0, () => ({ raw: true }))\n }\n }\n}\n\nmodule.exports = {\n resolveBehaviorParams\n}\n"],"names":["module","exports","removeStartingWhitespace","removeTrailingWhitespace","reindent","dedent","require","getLabeledItem","getNodeLabels","DEFAULT_INDENT","DEFAULT_MULTILINE_INTEGER_CELLS_INDENT","isMultilineNode","node","text","indexOf","isInlineComment","type","previousSibling","endPosition","row","startPosition","getNodeIndentation","tab","repeat","getNodeDepth","n","depth","stop","tree","rootNode","parent","id","shouldIncludeBlank","nodeA","nodeB","sameType","namedChildren","length","slice","some","hasAddress","childForFieldName","getAddress","formatLabels","labels","map","join","formatNode","options","indent","identifier","children","indentation","formatChildren","reduce","lines","childNode","i","arr","push","multilineIntegerCellsIndent","noValue","simpleValue","singleIntegerCell","bindingsLines","split","concat","line","formatPropertyNode","trimEnd","getModelineConfiguration","config","contents","startsWith","trim","match","key","jsonValue","value","JSON","parse","Object","assign","assert","reverse","getNodeLabelNodes","getNodeChildrenByFieldName","fieldName","cursor","walk","gotoFirstChild","isNamed","currentNode","isField","currentFieldName","gotoNextSibling","delete","findChildrenByIdentifier","nameOrMatch","filter","find","sub","nodesAreConsecutive","nodes","every","nextSibling","label","labeledItemNode","findChildByIdentifier","listNodes","opts","stripNewlines","limit","replace","console","log","parseStringLiteral","parseIntegerCells","parseIntegerArray","parsePhandles","parsePhandle","parsePhandleArray","parseIntegerUnion","serializeIntValue","serializeArrayValue","findNodeProperty","propertyName","getPropertyNode","child","getPropertyValues","property","propertyNode","parsePropertyFromSchema","schema","values","getProperty","syntaxNode","name","getPropertyValue","parsePropertiesFromSchema","keys","properties","prop","propSchema","undefined","parsed","serializePropertyFromSchema","phandle","bindings","group","v","toString","BreadthFirstIterator","maxDepth","queue","current","shift","DepthFirstIterator","stack","unshift","searchTree","predicate","single","depthFirst","iter","matches","createPredicateForCompatible","compatible","RegExp","test","TypeError","findLabeledItem","findNodeByIdentifier","findNodeWithCompatible","findNodesWithCompatible","isNegativeInteger","isNumberishType","includes","isBindingType","isBindingRef","extractInteger","Number","flatMap","cells","serializeIntegerCell","sanitizeIdentifier","ReferenceError","difference","isEqual","partition","NodeCollection","managedProperties","_cached_container_node","_cached_container_tree_version","_cached_collection_nodes","_cached_collection_tree_version","constructor","document","this","lookupContainerNode","bind","injectContainerNode","lookupNodes","injectNode","container","_parse_version","updateCollection","collection","flushChanges","originalIndices","reusedIndices","index","removedIndices","updates","additions","updateNode","removeNode","update","existing","extractNode","updateNodeName","updateNodeLabels","updateNodeProperties","cleanupNodeProperties","replaceNode","replaceNodeLabels","setProperty","deleteProperty","acc","raw","extractCollection","sortBy","TreeSitter","getPosition","_parser","getParser","async","init","language","Language","load","global","window","__dirname","setLanguage","DevicetreeDocument","parser","_enableChangeBuffering","_bufferedChanges","cleanup","inputEdit","replacementText","startIndex","newEndIndex","_reparse","chunks","nextUpdate","prevEnd","oldEndIndex","preChunk","chunk","newContent","documentText","precedingNewline","lastIndexOf","start","replacement","endIndex","oldEndPosition","newEndPosition","replaceRange","skipToIndex","source","labeledNode","newLabels","labelNodes","sorted","serializedLabels","insertTextBeforeNode","insertTextAfterNode","addChildNode","parentNode","closingBrace","newText","flatten","get","keyBy","uniq","behaviorBindings","KeymapDocument","encodeKeymap","behavioursByBind","layout","keymap","original","featureFlags","encoded","behaviourHeaders","keybinds","layers","layer","comboBinds","combos","macroBinds","macros","getBehavioursUsed","devicetreeKeymap","mergeUpdated","replaceBehaviourIncludes","err","error","groupPhandleArrayBindings","bindingCells","binding","MACRO_CONTROL_BEHAVIOURS","encodeBindValue","params","paramString","parseBindings","parseKeyBinding","paramsPattern","code","s","defines","groupMacroBindings","rows","behaviourBind","at","encodeKeyBinding","behaviorSchemas","rootNodes","_","behavior","last","nodeContent","extracted","super","extractedProp","bindStrings","aliases","bindingsValue","bindCode","legacyParseNodes","serialized","useRaw","bindString","comboSchema","combo","legacyParse","legacyNode","legacyMapping","layerSchema","updateLayerPositions","positionMap","nextIndex","j","targetIndexOrder","sensorBindings","pick","BehaviorCollection","macro","serializeMacroBindings","prototype","call","standardBehaviorIncludeFiles","MacroCollection","ComboCollection","LayerCollection","args","macroCollection","comboCollection","layerCollection","behaviorCollection","getChosenProperties","chosen","updated","enableBehaviorEditing","behaviors","behaviorIncludes","lastInclude","firstDefine","firstDtNode","MISSING_ROOT_NODE","USING_ZMK_NODEFREE_MACROS","USING_MULTIPLE_ROOT_NODES","USING_MIRYOKU_DTSI","USING_NON_ZMK_MACRO","keymapHasNoRootNodes","keymapUsesNodefreeConfigHelpers","macroNames","keymapUsesMiryoku","keymapBindingsUsePreprocessorMacros","zmkPreprocFunctions","layerNode","bindingsNode","keymapHasMultipleRootNodes","firstRootNode","keymapHasLayerBindingsWithNonBehaviorStarter","firstBindType","integerCells","warningFlags","USING_ZMK_MACRO_MACRO","compact","resolveBehaviorParams","extractWarnings","extractDefines","extractLocalHeaders","path","keymapText","headers","omitBy","renderLayout","KeymapValidationError","Error","errors","encodeLayers","encodeCombos","keyPositions","timeoutMs","slowRelease","parsedKeymap","parseKeymap","times","margin","table","col","rowIndices","columns","Math","max","columnIndices","columnWidths","noMoreValues","padding","padStart","_dedentedLines","minIndentation","leastIndentation","min","Infinity","idx","merge","isMatch","behaviorSchemaAdditions","behaviorAdditions","behaviorSchemaOverlays","behaviorOverlays","mergeBehaviorOverlays","base","overlays","baseValues","Array","isArray","overlay","singleValue","patternMappings","pattern","convert","digit","char","toUpperCase","simpleMappings","mapCharacter","keycodes","keycodeGlyphs","basic","unicode","platforms","mac","win","BehaviorResolutionError","message","parseNumBindingCells","behaviorMap","standardBindingsMap","newBindingsMap","resolve","bindingsType","nextBehavior"],"sourceRoot":""}
|