Merge pull request #13229 from keymanapp/chore/merge-master-into-user-dict
chore: merge master into user-dict
2
.github/workflows/deb-packaging.yml
vendored
|
|
@ -116,7 +116,7 @@ jobs:
|
|||
strategy:
|
||||
fail-fast: true
|
||||
matrix:
|
||||
dist: [focal, jammy, noble, oracular]
|
||||
dist: [jammy, noble, oracular]
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
|
|
|
|||
91
HISTORY.md
|
|
@ -1,5 +1,84 @@
|
|||
# Keyman Version History
|
||||
|
||||
## 19.0.2 alpha 2025-02-12
|
||||
|
||||
* chore(linux): remove support of Ubuntu 20.04 Focal (#13203)
|
||||
|
||||
## 19.0.1 alpha 2025-02-11
|
||||
|
||||
* refactor(windows): rename `TKeymanMutex.MutexOwned` to `TakeOwnership` and add `ReleaseOwnership` (#13168)
|
||||
* chore: increment to alpha 19.0 (#13187)
|
||||
|
||||
## 18.0.188 alpha 2025-02-10
|
||||
|
||||
* fix(windows): check the params status flag equals ucrsUpdateReady before attempting to download the keyman setup file (#13154)
|
||||
* feat(windows): background updates go from downloading to waiting for a restart except if the `apply now` flag is set (#13159)
|
||||
* feat(developer): verify package version number format in kmc-package (#13118)
|
||||
* fix(developer): support non-US base keyboard layouts in debuggers (#13131)
|
||||
* feat(developer): improve compiler messages and user interface (#13156)
|
||||
* feat(developer): verify that packages do not contain themselves in kmc-package (#13157)
|
||||
* fix(developer): link welcome.htm in package for new projects; use v17 project format for new models (#13161)
|
||||
* fix(windows): use Automatically check for updates and download for the english xml (#13162)
|
||||
* change(linux): Implement ordered output without patched ibus (#11535)
|
||||
|
||||
## 18.0.187 alpha 2025-02-07
|
||||
|
||||
* docs(web): relocate gesture docs to web/docs/internal (#13139)
|
||||
* chore(mac): remove empty options tab from configuration (#13160)
|
||||
* chore(linux): Update debian changelog (#13143)
|
||||
|
||||
## 18.0.186 alpha 2025-02-06
|
||||
|
||||
* feat(windows): check updates and automatic update merged (#13115)
|
||||
|
||||
## 18.0.185 alpha 2025-02-05
|
||||
|
||||
* fix(developer): make kmc log options consistent across all commands (#13075)
|
||||
* feat(developer): add user interface for `kmc copy` to TIKE (#13076)
|
||||
* chore(developer): add verbose logs for project copier (#13080)
|
||||
* chore(mac, ios): build and run with xcode 16 (#13077)
|
||||
|
||||
## 18.0.184 alpha 2025-02-04
|
||||
|
||||
* fix(common): handle undefined input in `@keymanapp/langtags` lookups (#13117)
|
||||
* chore: update docs to reference node 20.0 (#13124)
|
||||
* feat(developer): include command line in kmc sentry reports (#13113)
|
||||
* fix(common/web): replace invalid StrsItem identity checks with isEqual() (#13122)
|
||||
|
||||
## 18.0.183 alpha 2025-02-03
|
||||
|
||||
* change(ios): set host-app bundle identifier in embedded Web debug-report (#13105)
|
||||
* fix(ios): prevent message-handler collision (#13037)
|
||||
* change(web): add context tracker bksp handling, alignment-offset calculations (#12911)
|
||||
* fix(web): correct edit-path ordering at source (#12925)
|
||||
* fix(web): correctly track context transitions caused by applying suggestions (#12927)
|
||||
* chore(linux): preserve log files when running tests under Docker (#13107)
|
||||
|
||||
## 18.0.182 alpha 2025-01-31
|
||||
|
||||
* feat(windows): report on processor type in tsysinfo (#13084)
|
||||
* fix(common): push branch when creating PR in version history writer (#13082)
|
||||
* refactor: move langtags to @keymanapp/langtags npm module (#13046)
|
||||
* chore(developer): use langtags.json for kmc-generate language names (#13047)
|
||||
* feat(developer): support relocation of external files in kmc-copy (#13061)
|
||||
* feat(windows): kmshell switch handling for the installing state (#12956)
|
||||
* feat(windows): add boot switch (#12995)
|
||||
* docs(web): remove `.md` in help links (#13051)
|
||||
* chore: add android platform to titles (#13033)
|
||||
* chore: add the windows platform to titles (#13026)
|
||||
* fix(mac): properly manage Input Method lifecycle (#13006)
|
||||
* chore(developer): handle forward slashes in paths in package editor (#13081)
|
||||
* chore(developer,core,resources): LDML v46 update and remove workaround for import base (#13099)
|
||||
|
||||
## 18.0.181 alpha 2025-01-30
|
||||
|
||||
* feat(windows): add localized button captions and form labels (#13025)
|
||||
* fix(web): disabled correction state should prevent predictive corrections (#13066)
|
||||
* fix(web): disabled autoaccept should not autohighlight suggestions (#13068)
|
||||
* chore(common): add 17.0.334 to version history (#13065)
|
||||
* fix(windows): add api GetContext and TIPProcessKeyEx with IsTextSelected bool (#13023)
|
||||
* fix(web): keyboard query error states should always provide informative Error objects, reports (#13048)
|
||||
|
||||
## 18.0.180 alpha 2025-01-29
|
||||
|
||||
* chore(common): Update crowdin strings for Portuguese (#13056)
|
||||
|
|
@ -1242,6 +1321,18 @@
|
|||
* chore(common): move to 18.0 alpha (#10713)
|
||||
* chore: move to 18.0 alpha
|
||||
|
||||
## 17.0.335 alpha 2025-02-06
|
||||
|
||||
* fix(android): improve resource-update tool handling of host Activity's closure (#13057)
|
||||
* fix(ios): prevent message-handler collision (#13058)
|
||||
* chore(linux): improve compatibility with Gentoo Linux (#12889)
|
||||
* chore(linux): Update debian changelog (#13062)
|
||||
* fix(web): keyboard query error states should always provide informative Error objects, reports (#13079)
|
||||
* chore: push the branch when creating PR in version history writer (#13085)
|
||||
* fix(web): disabled correction state should prevent predictive corrections (#13074)
|
||||
* change(ios): set host-app bundle identifier in embedded Web debug-report (#13112)
|
||||
* chore(mac, ios): build and run with xcode 16 (#13121)
|
||||
|
||||
## 17.0.334 stable 2025-01-27
|
||||
|
||||
* chore(linux): update copyright year (#12919)
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
18.0.181
|
||||
19.0.3
|
||||
|
|
@ -1,13 +1,13 @@
|
|||
---
|
||||
title: Guide: build an in-app keyboard
|
||||
title: Guide: build an in-app keyboard for Android with Keyman Engine
|
||||
---
|
||||
|
||||
Keyman Engine for Android allows you to use any Keyman touch keyboard in your Android app, or even to create your own
|
||||
system keyboard app for purchase in the Play Store.<br/>
|
||||
This guide will walk you through the steps for creating your first Android app with Keyman Engine for Android.
|
||||
|
||||
If you are not familiar with Android development, you will find the
|
||||
[Android Developer online training](https://developer.android.com/training/index.html) an invaluable
|
||||
If you are not familiar with Android development, you will find the
|
||||
[Android Developer online training](https://developer.android.com/training/index.html) an invaluable
|
||||
resource, and working through some of their tutorials first will help you with the rest of this guide.
|
||||
|
||||
### 1. Install Free Tools
|
||||
|
|
@ -131,5 +131,5 @@ And there you have it: your first Keyman Engine for Android app!
|
|||
## See Also
|
||||
* [Guide: Build a system keyboard app](../system-keyboard/)
|
||||
* [Keyman Developer Documentation](/developer/17.0/)
|
||||
* [Keyman Engine for Android Documentation](/developer/engine/android/18.0/)
|
||||
* [Keyman Engine for Android Documentation](/developer/engine/android/19.0/)
|
||||
* [Android Developer Home](https://developer.android.com/index.html)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
---
|
||||
title: Guide: build a system keyboard app
|
||||
title: Guide: build a system keyboard app for Android with Keyman Engine
|
||||
---
|
||||
|
||||
In [part 1](../in-app/) of this series, we looked at the steps involved
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ title: Keyman Engine for Android
|
|||
|
||||
## Overview
|
||||
|
||||
Keyman Engine for Android 18.0 is a Java library for Android 5.0 and later versions which enables a fully customisable keyboard layout, both within an app and system-wide.
|
||||
Keyman Engine for Android 19.0 is a Java library for Android 5.0 and later versions which enables a fully customisable keyboard layout, both within an app and system-wide.
|
||||
Keyboard layouts for Keyman Engine can be created with [Keyman Developer](/developer/17.0), and a [library of existing keyboard layouts](http://keyman.com/developer/keymanweb/keyboards)
|
||||
is also available.</p>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,6 @@
|
|||
---
|
||||
title: What's New in Keyman Engine 18.0 for Android
|
||||
title: What's New in Keyman Engine 19.0 for Android
|
||||
---
|
||||
|
||||
## Keyman Engine for Android Breaking Changes: ##
|
||||
|
||||
* Change package name from `com.tavultesoft.kmea` to `com.keyman.engine` #7881
|
||||
* Update to Java 11 #8543
|
||||
|
||||
## See Also
|
||||
* [Keyman Engine for Android Documentation](index)
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
---
|
||||
title: About Keyman
|
||||
title: About Keyman for Android
|
||||
---
|
||||
|
||||
* [Welcome to Keyman](welcome)
|
||||
|
|
|
|||
|
|
@ -1,9 +1,6 @@
|
|||
---
|
||||
title: What's New in Keyman 18.0 for Android
|
||||
title: What's New in Keyman 19.0 for Android
|
||||
---
|
||||
|
||||
Here are some of the new features we have added to Keyman 18.0 for Android:
|
||||
Here are some of the new features we have added to Keyman 19.0 for Android:
|
||||
|
||||
* New menu to adjust longpress delay time (#12170, #12185)
|
||||
* Support localizations for right-to-left languages (#12215)
|
||||
* Handle additional actions for ENTER key (#12125, #12315)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
---
|
||||
title: Basic Help
|
||||
title: Basic Help - Keyman for Android
|
||||
---
|
||||
|
||||
* [Using the Banner on the Keyboard](using-the-banner)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
---
|
||||
title: Gesture Hints and Tips
|
||||
title: Gesture Hints and Tips - Keyman for Android
|
||||
---
|
||||
|
||||
## Using Gestures on the Keyboard Keys
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
---
|
||||
title: Keyman for Android 18.0 Help
|
||||
title: Keyman for Android 19.0 Help
|
||||
---
|
||||
|
||||
## [About Keyman](about/)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
---
|
||||
title: How To - Enabling Keyman as a System-Wide Keyboard
|
||||
title: How To - Enabling Keyman for Android as a System-Wide Keyboard
|
||||
---
|
||||
|
||||
## Enabling System Wide Keyboards
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
---
|
||||
title: Getting Started
|
||||
title: Getting Started with Keyman for Android
|
||||
---
|
||||
|
||||
* [How To - Download and Install a Keyman Keyboard](installing-keyboards)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
---
|
||||
title: How To - Granting Storage Permission
|
||||
title: How To - Granting Storage Permission on Keyman for Android
|
||||
---
|
||||
|
||||
## Granting Storage Permission
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")"
|
|||
|
||||
builder_describe "Keyman common web modules" \
|
||||
:keyman-version \
|
||||
:langtags \
|
||||
:types \
|
||||
clean \
|
||||
configure \
|
||||
|
|
|
|||
1
common/web/langtags/.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
src/imports/
|
||||
38
common/web/langtags/README.md
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
# Keyman langtags
|
||||
|
||||
This package provides a wrapper for the
|
||||
[langtags.json](https://ldml.api.sil.org/langtags.json) dataset from
|
||||
https://github.com/silnrsi/langtags.
|
||||
|
||||
This package is published in sync with Keyman, so changes in langtags may not
|
||||
propagate immediately.
|
||||
|
||||
## Usage
|
||||
|
||||
* `getLangtagByTag(tag)`: Find a language tag from a given tag; matches on tag,
|
||||
tags, full properties, with a case-insensitive search. Returns unmodified
|
||||
object from langtags.json on match.
|
||||
|
||||
* `metadata.conformance()`: Returns script and region conformance data from
|
||||
langtags.json
|
||||
|
||||
* `metadata.globalvar()`: Returns global variant data from langtags.json
|
||||
|
||||
* `metadata.phonvar()`: Returns phonetic variant data from langtags.json
|
||||
|
||||
* `metadata.version()`: Returns version data from langtags.json
|
||||
|
||||
* `langtags`: Raw access to the langtags.json array of objects
|
||||
|
||||
## Background
|
||||
|
||||
Key documents for further reading (from langtags repository):
|
||||
|
||||
* [Overview of language tags and how this project works with them](https://github.com/silnrsi/langtags/blob/master/doc/tagging.md)
|
||||
|
||||
* [How to use langtags.json](https://github.com/silnrsi/langtags/blob/master/doc/langtags.md)
|
||||
|
||||
## License
|
||||
|
||||
* Copyright ©️ 2025 SIL Global.
|
||||
* MIT License ([License text](https://github.com/keymanapp/keyman/tree/master/LICENSE.md))
|
||||
45
common/web/langtags/build.sh
Executable file
|
|
@ -0,0 +1,45 @@
|
|||
#!/usr/bin/env bash
|
||||
## START STANDARD BUILD SCRIPT INCLUDE
|
||||
# adjust relative paths as necessary
|
||||
THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")"
|
||||
. "${THIS_SCRIPT%/*}/../../../resources/build/builder.inc.sh"
|
||||
## END STANDARD BUILD SCRIPT INCLUDE
|
||||
|
||||
. "$KEYMAN_ROOT/resources/shellHelperFunctions.sh"
|
||||
. "$KEYMAN_ROOT/resources/build/build-utils-ci.inc.sh"
|
||||
|
||||
builder_describe "Build Keyman langtags.js common module" \
|
||||
"clean" \
|
||||
"configure" \
|
||||
"build" \
|
||||
"test" \
|
||||
"publish publish to npm" \
|
||||
"--npm-publish+ For publish, do a npm publish, not npm pack (only for CI)" \
|
||||
"--dry-run,-n don't actually publish, just dry run"
|
||||
|
||||
builder_describe_outputs \
|
||||
configure /common/web/langtags/src/imports/langtags.js \
|
||||
build /common/web/langtags/build/src/main.js
|
||||
|
||||
builder_parse "$@"
|
||||
|
||||
#-------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
function compile_langtags() {
|
||||
mkdir -p src/imports
|
||||
echo 'export default ' > src/imports/langtags.js
|
||||
cat "$KEYMAN_ROOT/resources/standards-data/langtags/langtags.json" >> src/imports/langtags.js
|
||||
}
|
||||
|
||||
function do_configure() {
|
||||
verify_npm_setup
|
||||
compile_langtags
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
builder_run_action clean rm -rf ./build ./src/imports ./node_modules
|
||||
builder_run_action configure do_configure
|
||||
builder_run_action build tsc --build
|
||||
builder_run_action test echo 'no tests for langtags'
|
||||
builder_run_action publish builder_publish_npm
|
||||
39
common/web/langtags/package.json
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
{
|
||||
"name": "@keymanapp/langtags",
|
||||
"description": "Keyman bundling of language tags from langtags.json",
|
||||
"keywords": [
|
||||
"keyboard",
|
||||
"keyman",
|
||||
"ldml",
|
||||
"unicode"
|
||||
],
|
||||
"type": "module",
|
||||
"types": "./build/src/main.d.ts",
|
||||
"exports": {
|
||||
".": {
|
||||
"es6-bundling": "./src/main.ts",
|
||||
"types": "./build/src/main.d.ts",
|
||||
"default": "./build/src/main.js"
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"/build/src/"
|
||||
],
|
||||
"scripts": {
|
||||
"build": "tsc -b",
|
||||
"test": "echo no tests for langtags"
|
||||
},
|
||||
"author": "Marc Durdin <marc@keyman.com> (https://github.com/mcdurdin)",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/keymanapp/keyman/issues"
|
||||
},
|
||||
"devDependencies": {
|
||||
"typescript": "^5.4.5"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/keymanapp/keyman.git"
|
||||
},
|
||||
"sideEffects": false
|
||||
}
|
||||
122
common/web/langtags/src/main.ts
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
/*
|
||||
* Keyman is copyright (C) SIL Global. MIT License.
|
||||
*
|
||||
* Wraps langtags.json as a Javascript object
|
||||
*/
|
||||
|
||||
import langtags from './imports/langtags.js';
|
||||
|
||||
// These interfaces and types correspond to https://github.com/silnrsi/langtags/blob/master/source/langtags_schema.json
|
||||
|
||||
export type LangTagBcp47 = string; // BCP 47
|
||||
export type LangTagBcp47Variant = string; // BCP 47 variant
|
||||
export type LangTagIso639_3 = string; // ISO639-3
|
||||
export type LangTagIso3166_1 = string; // region
|
||||
export type LangTagIso15924 = string; // script
|
||||
|
||||
|
||||
export interface LangTag {
|
||||
full: string; // should be LangTagBcp47?
|
||||
iana?: string[];
|
||||
iso639_3?: LangTagIso639_3;
|
||||
latnnames?: string[];
|
||||
localname?: string;
|
||||
localnames?: string;
|
||||
macrolang?: LangTagBcp47;
|
||||
name?: string;
|
||||
names?: string[];
|
||||
nophonvars?: boolean;
|
||||
obsolete?: boolean;
|
||||
region?: LangTagIso3166_1;
|
||||
regionname?: string;
|
||||
regions?: LangTagIso3166_1[];
|
||||
rod?: string;
|
||||
script?: LangTagIso15924;
|
||||
sldr?: boolean;
|
||||
suppress?: boolean;
|
||||
tag?: LangTagBcp47;
|
||||
tags?: LangTagBcp47[];
|
||||
unwritten?: boolean;
|
||||
variants?: LangTagBcp47Variant[];
|
||||
windows?: LangTagBcp47;
|
||||
};
|
||||
|
||||
export interface LangTagConformance {
|
||||
regions: LangTagIso3166_1[];
|
||||
scripts: LangTagIso15924[];
|
||||
tag: '_conformance';
|
||||
};
|
||||
|
||||
export interface LangTagGlobalVar {
|
||||
variants: LangTagBcp47Variant[];
|
||||
tag: '_globalvar';
|
||||
};
|
||||
|
||||
export interface LangTagPhonVar {
|
||||
variants: LangTagBcp47Variant[];
|
||||
tag: '_phonvar';
|
||||
};
|
||||
|
||||
export interface LangTagVersion {
|
||||
api: string;
|
||||
date: string;
|
||||
tag: '_version';
|
||||
};
|
||||
|
||||
/**
|
||||
* A map of all language tags, lower cased
|
||||
*/
|
||||
const langtagsByTag: Map<string, any> = new Map<string, any>();
|
||||
|
||||
/* metadata variables */
|
||||
let conformance: LangTagConformance = undefined;
|
||||
let globalvar: LangTagGlobalVar = undefined;
|
||||
let phonvar: LangTagPhonVar = undefined;
|
||||
let version: LangTagVersion = undefined;
|
||||
|
||||
const metadata = {
|
||||
conformance: () => ({ regions: [...conformance.regions], scripts: [...conformance.scripts] }),
|
||||
globalvar: () => ({ variants: [...globalvar.variants] }),
|
||||
phonvar: () => ({ variants: [...phonvar.variants] }),
|
||||
version: () => ({ api: version.api, date: version.date })
|
||||
};
|
||||
|
||||
/**
|
||||
* Build a dictionary of language tags from langtags.json. This takes under 10ms
|
||||
* on a reasonable laptop.
|
||||
*/
|
||||
function preinit(): void {
|
||||
for(const tag of langtags) {
|
||||
if(tag.tag == '_conformance') {
|
||||
conformance = tag;
|
||||
} else if(tag.tag == '_globalvar') {
|
||||
globalvar = tag;
|
||||
} else if(tag.tag == '_phonvar') {
|
||||
phonvar = tag;
|
||||
} else if(tag.tag == '_version') {
|
||||
version = tag;
|
||||
} else if(tag.full && tag.tag) {
|
||||
langtagsByTag.set(tag.tag.toLowerCase(), tag);
|
||||
langtagsByTag.set(tag.full.toLowerCase(), tag);
|
||||
if(tag.tags) {
|
||||
for(const t of tag.tags) {
|
||||
langtagsByTag.set(t.toLowerCase(), tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a LangTag from a given tag; matches on tag, tags, full properties,
|
||||
* with a case-insensitive search.
|
||||
* @param tag
|
||||
* @returns LangTag or undefined if not found
|
||||
*/
|
||||
function getLangtagByTag(tag: string): LangTag {
|
||||
return langtagsByTag.get(tag?.toLowerCase());
|
||||
}
|
||||
|
||||
preinit();
|
||||
|
||||
export { langtags, getLangtagByTag, metadata };
|
||||
19
common/web/langtags/tsconfig.json
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"extends": "../../../tsconfig.base.json",
|
||||
|
||||
"compilerOptions": {
|
||||
"outDir": "build/src/",
|
||||
"rootDir": "src/",
|
||||
"baseUrl": ".",
|
||||
/*
|
||||
following two settings allow us to import langtags.js. It cannot be a .ts
|
||||
because the type is too complex for TypeScript to infer.
|
||||
*/
|
||||
"allowJs": true,
|
||||
"noImplicitAny": false,
|
||||
},
|
||||
"include": [
|
||||
"src/**/*.ts",
|
||||
"src/imports/*.js", // Import langtags.json
|
||||
],
|
||||
}
|
||||
|
|
@ -30,8 +30,8 @@ builder_parse "$@"
|
|||
function compile_schemas() {
|
||||
# We need the schema files at runtime and bundled, so always copy it for all actions except `clean`
|
||||
local schemas=(
|
||||
"$KEYMAN_ROOT/resources/standards-data/ldml-keyboards/45/ldml-keyboard3.schema.json"
|
||||
"$KEYMAN_ROOT/resources/standards-data/ldml-keyboards/45/ldml-keyboardtest3.schema.json"
|
||||
"$KEYMAN_ROOT/resources/standards-data/ldml-keyboards/46/ldml-keyboard3.schema.json"
|
||||
"$KEYMAN_ROOT/resources/standards-data/ldml-keyboards/46/ldml-keyboardtest3.schema.json"
|
||||
"$KEYMAN_ROOT/common/schemas/kvks/kvks.schema.json"
|
||||
"$KEYMAN_ROOT/common/schemas/kpj/kpj.schema.json"
|
||||
"$KEYMAN_ROOT/common/schemas/kpj-9.0/kpj-9.0.schema.json"
|
||||
|
|
|
|||
55
common/web/types/tests/kmx/kmx-plus/kmx-plus.tests.ts
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* Keyman is copyright (C) SIL Global. MIT License.
|
||||
*
|
||||
* Created by Dr Mark C. Sinclair on 2025-02-03
|
||||
*
|
||||
* Test code for kmx-plus.ts
|
||||
*/
|
||||
|
||||
import 'mocha';
|
||||
import { assert } from 'chai';
|
||||
import { Strs, StrsItem, StrsOptions, DependencySections } from '../../../src/kmx/kmx-plus/kmx-plus.js';
|
||||
|
||||
const GOTHIC_A = new StrsItem("𐌰", 0x10330);
|
||||
|
||||
describe('Test of KMX Plus file', () => {
|
||||
describe('Test of Strs', () => {
|
||||
describe('Test of implicit constructor', () => {
|
||||
it('can construct a Strs', () => {
|
||||
const strs = new Strs();
|
||||
assert.isNotNull(strs);
|
||||
assert.deepEqual(strs.strings, [new StrsItem('')]);
|
||||
assert.deepEqual(strs.allProcessedStrings, new Set<string>());
|
||||
});
|
||||
});
|
||||
describe('Test of allocString()', () => {
|
||||
it('can allocate a one-character string', () => {
|
||||
const strs = new Strs();
|
||||
strs['processString'] = stubStrsProcessString;
|
||||
const csi = strs.allocString("𐌰", { singleOk: true });
|
||||
assert.deepEqual(csi, GOTHIC_A);
|
||||
});
|
||||
it('can allocate an unknown string', () => {
|
||||
const strs = new Strs();
|
||||
strs['processString'] = stubStrsProcessString;
|
||||
const si = strs.allocString("𐌰𐌱𐌲");
|
||||
assert.deepEqual(si, new StrsItem("𐌰𐌱𐌲"));
|
||||
assert.deepEqual(strs.strings, [new StrsItem(''), new StrsItem("𐌰𐌱𐌲")]);
|
||||
});
|
||||
it('can allocate a known string', () => {
|
||||
const strs = new Strs();
|
||||
strs['processString'] = stubStrsProcessString;
|
||||
const one = strs.allocString("𐌰𐌱𐌲");
|
||||
assert.deepEqual(one, new StrsItem("𐌰𐌱𐌲"));
|
||||
assert.deepEqual(strs.strings, [new StrsItem(''), new StrsItem("𐌰𐌱𐌲")]);
|
||||
const two = strs.allocString("𐌰𐌱𐌲");
|
||||
assert.isTrue(two === one);
|
||||
assert.deepEqual(strs.strings, [new StrsItem(''), new StrsItem("𐌰𐌱𐌲")]);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function stubStrsProcessString(s: string, opts: StrsOptions, sections: DependencySections) {
|
||||
return s;
|
||||
}
|
||||
|
|
@ -314,7 +314,6 @@ const
|
|||
SRegValue_ActiveProject_Filename = 'project filename';
|
||||
SRegValue_ActiveProject_SourcePath = 'source path';
|
||||
|
||||
SRegValue_AutomaticUpdates = 'automatic updates'; //CU
|
||||
SRegValue_CheckForUpdates = 'check for updates'; // CU
|
||||
SRegValue_LastUpdateCheckTime = 'last update check time'; // CU
|
||||
SRegValue_ApplyNow = 'apply now'; // CU Start the install now even though it will require an restart
|
||||
|
|
|
|||
|
|
@ -58,6 +58,8 @@ const
|
|||
URLPath_KeymanDeveloper_KeymanForAndroidDownload = '/go/developer/'+SKeymanVersion+'/android-app';
|
||||
URLPath_KeymanDeveloper_KeymanForIosDownload = '/go/developer/'+SKeymanVersion+'/ios-app';
|
||||
|
||||
URLPath_KeymanDeveloper_KeyboardSearchForCloneKeymanCloud = '/go/developer/'+SKeymanVersion+'/clone-keyboard';
|
||||
|
||||
URLPath_Support = '/go/'+SKeymanVersion+'/support';
|
||||
URLPath_Privacy = '/go/'+SKeymanVersion+'/privacy';
|
||||
URLPath_Privacy_Presentation = '/privacy';
|
||||
|
|
@ -71,6 +73,10 @@ const
|
|||
UrlPath_RegEx_MatchKeyboardsGo = '^http(?:s)?://keyman(?:-staging)?\.com(?:\.local)?/go/windows/[^/]+/download-keyboards';
|
||||
// e.g. https://keyman-staging.com/go/windows/14.0/download-keyboards?version=14.0.146.0
|
||||
|
||||
// Cloning keyboards - Keyman Developer
|
||||
URLSubPath_KeymanDeveloper_Clone_Keyboards = '/keyboards/';
|
||||
URLSubPath_KeymanDeveloper_Clone_Keyboards_Custom = '/keyboards/h/';
|
||||
|
||||
function URLPath_PackageDownload(const PackageID, BCP47: string; IsUpdate: Boolean): string;
|
||||
|
||||
function API_Protocol: string; // = 'https';
|
||||
|
|
@ -86,6 +92,8 @@ function MakeAPIURL(path: string): string;
|
|||
|
||||
function MakeKeymanURL(const path: string): string;
|
||||
|
||||
function URL_KmcMessage(const id: string): string;
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
|
|
@ -102,6 +110,7 @@ const
|
|||
S_UserAgent_Developer = 'Keyman Developer';
|
||||
S_UserAgent_Diagnostics = 'Keyman for Windows Diagnostics';
|
||||
|
||||
S_Host_KmnSh = 'https://kmn.sh';
|
||||
S_KeymanCom = 'https://keyman.com';
|
||||
S_APIProtocol = 'https';
|
||||
S_APIServer = 'api.keyman.com';
|
||||
|
|
@ -114,6 +123,7 @@ const
|
|||
|
||||
const
|
||||
URLPath_PackageDownload_Format = '/go/package/download/%0:s?platform=windows&tier=%1:s&bcp47=%2:s&update=%3:d';
|
||||
URL_KeymanDeveloper_HelpKmcMessage_Format = S_Host_KmnSh+'/%0:s';
|
||||
|
||||
function API_UserAgent: string;
|
||||
begin
|
||||
|
|
@ -130,7 +140,6 @@ begin
|
|||
Result := S_UserAgent_Diagnostics + '/' + GetVersionString;
|
||||
end;
|
||||
|
||||
|
||||
function MakeKeymanURL(const path: string): string;
|
||||
begin
|
||||
Result := KeymanCom_Protocol_Server + path;
|
||||
|
|
@ -173,4 +182,9 @@ begin
|
|||
Result := Format(URLPath_PackageDownload_Format, [URLEncode(PackageID), URLEncode(CKeymanVersionInfo.Tier), URLEncode(BCP47), IsUpdateInt]);
|
||||
end;
|
||||
|
||||
function URL_KmcMessage(const id: string): string;
|
||||
begin
|
||||
Result := Format(URL_KeymanDeveloper_HelpKmcMessage_Format, [id.ToLower]);
|
||||
end;
|
||||
|
||||
end.
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ uses
|
|||
Winapi.Windows;
|
||||
|
||||
function GetVersionString: WideString;
|
||||
function GetMajorMinorVersionString: string;
|
||||
procedure GetVersionBuild(var vMajor, vMinor: Integer);
|
||||
function GetVersionCopyright: WideString;
|
||||
function GetFileVersionString(const FileName: WideString): WideString;
|
||||
|
|
@ -54,6 +55,12 @@ begin
|
|||
IntToStr(LoWord(VersionMinor));
|
||||
end;
|
||||
|
||||
function GetMajorMinorVersionString: string;
|
||||
begin
|
||||
Result := IntToStr(HiWord(VersionMajor)) + '.' + // I3310
|
||||
IntToStr(LoWord(VersionMajor));
|
||||
end;
|
||||
|
||||
procedure GetVersionBuild(var vMajor, vMinor: Integer);
|
||||
begin
|
||||
vMajor := VersionMajor;
|
||||
|
|
|
|||
|
|
@ -1,18 +1,18 @@
|
|||
(*
|
||||
Name: utilfiletypes
|
||||
Copyright: Copyright (C) SIL International.
|
||||
Documentation:
|
||||
Description:
|
||||
Documentation:
|
||||
Description:
|
||||
Create Date: 20 Jun 2006
|
||||
|
||||
Modified Date: 4 Dec 2006
|
||||
Authors: mcdurdin
|
||||
Related Files:
|
||||
Dependencies:
|
||||
Related Files:
|
||||
Dependencies:
|
||||
|
||||
Bugs:
|
||||
Todo:
|
||||
Notes:
|
||||
Bugs:
|
||||
Todo:
|
||||
Notes:
|
||||
History: 20 Jun 2006 - mcdurdin - Initial version
|
||||
01 Aug 2006 - mcdurdin - Refactor util functions into multiple units
|
||||
04 Dec 2006 - mcdurdin - Add XML and HTML filetypes
|
||||
|
|
@ -100,7 +100,15 @@ type
|
|||
end;
|
||||
|
||||
type
|
||||
TKeymanProjectType = (kptUnknown, kptBasic, kptLDMLKeyboard, kptImportWindowsKeyboard, kptWordlistLexicalModel);
|
||||
TKeymanProjectType = (
|
||||
kptUnknown,
|
||||
kptBasic,
|
||||
kptLDMLKeyboard,
|
||||
kptImportWindowsKeyboard,
|
||||
kptWordlistLexicalModel,
|
||||
kptCloneLocalProject,
|
||||
kptCloneKeymanCloudProject,
|
||||
kptCloneGitHubProject);
|
||||
|
||||
implementation
|
||||
|
||||
|
|
|
|||
|
|
@ -16,11 +16,11 @@
|
|||
#pragma once
|
||||
|
||||
#define LDML_BKSP_FLAGS_ERROR 0x1
|
||||
#define LDML_CLDR_IMPLIED_FORMS_IMPORT "45/scanCodes-implied.xml"
|
||||
#define LDML_CLDR_IMPLIED_KEYS_IMPORT "45/keys-Latn-implied.xml"
|
||||
#define LDML_CLDR_IMPLIED_FORMS_IMPORT "46/scanCodes-implied.xml"
|
||||
#define LDML_CLDR_IMPLIED_KEYS_IMPORT "46/keys-Latn-implied.xml"
|
||||
#define LDML_CLDR_IMPORT_BASE "cldr"
|
||||
#define LDML_CLDR_TEST_VERSION_LATEST "techpreview"
|
||||
#define LDML_CLDR_VERSION_LATEST "45"
|
||||
#define LDML_CLDR_VERSION_LATEST "46"
|
||||
#define LDML_ELEM_FLAGS_ORDER_BITSHIFT 0x10
|
||||
#define LDML_ELEM_FLAGS_ORDER_MASK 0xFF0000
|
||||
#define LDML_ELEM_FLAGS_PREBASE 0x8
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ class Constants {
|
|||
/**
|
||||
* The current CLDR version
|
||||
*/
|
||||
readonly cldr_version_latest = '45';
|
||||
readonly cldr_version_latest = '46';
|
||||
/**
|
||||
* The version for testdata files
|
||||
*/
|
||||
|
|
@ -564,8 +564,17 @@ class Constants {
|
|||
/** maximum count of markers (not including 'any') */
|
||||
readonly marker_max_count = this.marker_max_index - this.marker_min_index + 1;
|
||||
|
||||
/**
|
||||
* List of versions to treat as if they were the 'latest' version.
|
||||
*/
|
||||
treatAsLatest(version: string): boolean {
|
||||
return cldrTreatAsLatest.has(version);
|
||||
}
|
||||
};
|
||||
|
||||
/** There's no data or DTD change in 45, 46, 46.1, 47 so map them all to 46 at present. */
|
||||
const cldrTreatAsLatest: Set<string> = new Set(['45', '46.1', '47']);
|
||||
|
||||
export const constants = new Constants();
|
||||
|
||||
// }
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ working on ‘layr’, using ‘disp’ as a model from https://github.com/keyma
|
|||
|
||||
## XML changes
|
||||
|
||||
- `resources/standards-data/ldml-keyboards/45/` : update / reimport / fix fixup script if needed
|
||||
- `resources/standards-data/ldml-keyboards/46/` : update / reimport / fix fixup script if needed
|
||||
- E/C: `common/web/types/src/ldml-keyboard/ldml-keyboard-xml.ts`
|
||||
- add to `LKKeyboard` and subproperties as needed to support the structure on the XML side
|
||||
- Now would be a good time to stop and make sure everything compiles. It didn’t, there was an unrelated issue with snprintf!
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE keyboardTest3 SYSTEM "../../../../../resources/standards-data/ldml-keyboards/45/dtd/ldmlKeyboardTest3.dtd">
|
||||
<!DOCTYPE keyboardTest3 SYSTEM "../../../../../resources/standards-data/ldml-keyboards/46/dtd/ldmlKeyboardTest3.dtd">
|
||||
<keyboardTest3 conformsTo="techpreview">
|
||||
<info keyboard="k_001_tiny.xml" author="srl295" name="k_001_tiny" />
|
||||
<!-- <repertoire chars="[ħ ថា]" type="simple" name="our-little-language" /> TODO-LDML: not working yet -->
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE keyboardTest3 SYSTEM "../../../../../resources/standards-data/ldml-keyboards/45/dtd/ldmlKeyboardTest3.dtd">
|
||||
<!DOCTYPE keyboardTest3 SYSTEM "../../../../../resources/standards-data/ldml-keyboards/46/dtd/ldmlKeyboardTest3.dtd">
|
||||
<keyboardTest3 conformsTo="techpreview">
|
||||
<info keyboard="k_006_backspace.xml" author="Team Keyboard" name="backspace" />
|
||||
<tests name="backspace">
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE keyboardTest3 SYSTEM "../../../../../resources/standards-data/ldml-keyboards/45/dtd/ldmlKeyboardTest3.dtd">
|
||||
<!DOCTYPE keyboardTest3 SYSTEM "../../../../../resources/standards-data/ldml-keyboards/46/dtd/ldmlKeyboardTest3.dtd">
|
||||
<keyboardTest3 conformsTo="techpreview">
|
||||
<info keyboard="k_007_transform_rgx.xml" author="Team Keyboard" name="marker" />
|
||||
<tests name="regex-tests">
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE keyboardTest3 SYSTEM "../../../../../resources/standards-data/ldml-keyboards/45/dtd/ldmlKeyboardTest3.dtd">
|
||||
<!DOCTYPE keyboardTest3 SYSTEM "../../../../../resources/standards-data/ldml-keyboards/46/dtd/ldmlKeyboardTest3.dtd">
|
||||
<keyboardTest3 conformsTo="techpreview">
|
||||
<info keyboard="k_008_transform_norm.xml" author="Team Keyboard" name="transform-norm" />
|
||||
<tests name="regex-test-dot0">
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE keyboardTest3 SYSTEM "../../../../../resources/standards-data/ldml-keyboards/45/dtd/ldmlKeyboardTest3.dtd">
|
||||
<!DOCTYPE keyboardTest3 SYSTEM "../../../../../resources/standards-data/ldml-keyboards/46/dtd/ldmlKeyboardTest3.dtd">
|
||||
<keyboardTest3 conformsTo="techpreview">
|
||||
<info keyboard="k_009_transform_nfc.xml" author="Team Keyboard" name="transform-norm" />
|
||||
<tests name="regex-test-dot0">
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Note: similar to, but slightly ahead of, fr-t-k0-azerty -->
|
||||
<!DOCTYPE keyboardTest3 SYSTEM "../../../../../resources/standards-data/ldml-keyboards/45/dtd/ldmlKeyboardTest3.dtd">
|
||||
<!DOCTYPE keyboardTest3 SYSTEM "../../../../../resources/standards-data/ldml-keyboards/46/dtd/ldmlKeyboardTest3.dtd">
|
||||
<keyboardTest3 conformsTo="techpreview">
|
||||
<info keyboard="k_020_fr.xml" author="Team Keyboard" name="fr-test-updated" />
|
||||
<repertoire name="simple-repertoire" chars="[a b c d e \u0022]" type="simple" /> <!-- verify that these outputs are all available from simple keys on any layer, for all form factors -->
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE keyboardTest3 SYSTEM "../../../../../resources/standards-data/ldml-keyboards/45/dtd/ldmlKeyboardTest3.dtd">
|
||||
<!DOCTYPE keyboardTest3 SYSTEM "../../../../../resources/standards-data/ldml-keyboards/46/dtd/ldmlKeyboardTest3.dtd">
|
||||
<keyboardTest3 conformsTo="techpreview">
|
||||
<info keyboard="k_200_reorder_nod_Lana.xml" author="Team Keyboard" name="nod-Lana" />
|
||||
<tests name="reorder-tests">
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE keyboardTest3 SYSTEM "../../../../../resources/standards-data/ldml-keyboards/45/dtd/ldmlKeyboardTest3.dtd">
|
||||
<!DOCTYPE keyboardTest3 SYSTEM "../../../../../resources/standards-data/ldml-keyboards/46/dtd/ldmlKeyboardTest3.dtd">
|
||||
<keyboardTest3 conformsTo="techpreview">
|
||||
<info keyboard="k_201_reorder_esk.xml" author="Team Keyboard" name="esk-reorder-test" />
|
||||
<tests name="basic">
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE keyboardTest3 SYSTEM "../../../../../resources/standards-data/ldml-keyboards/45/dtd/ldmlKeyboardTest3.dtd">
|
||||
<!DOCTYPE keyboardTest3 SYSTEM "../../../../../resources/standards-data/ldml-keyboards/46/dtd/ldmlKeyboardTest3.dtd">
|
||||
<keyboardTest3 conformsTo="techpreview">
|
||||
<info keyboard="k_210_marker.xml" author="Team Keyboard" name="marker" />
|
||||
<tests name="marker-tests">
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE keyboardTest3 SYSTEM "../../../../../resources/standards-data/ldml-keyboards/45/dtd/ldmlKeyboardTest3.dtd">
|
||||
<!DOCTYPE keyboardTest3 SYSTEM "../../../../../resources/standards-data/ldml-keyboards/46/dtd/ldmlKeyboardTest3.dtd">
|
||||
<keyboardTest3 conformsTo="techpreview">
|
||||
<info keyboard="k_211_marker_escape.xml" author="Team Keyboard" name="marker" />
|
||||
<tests name="marker-escape">
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE keyboardTest3 SYSTEM "../../../../../resources/standards-data/ldml-keyboards/45/dtd/ldmlKeyboardTest3.dtd">
|
||||
<!DOCTYPE keyboardTest3 SYSTEM "../../../../../resources/standards-data/ldml-keyboards/46/dtd/ldmlKeyboardTest3.dtd">
|
||||
<keyboardTest3 conformsTo="techpreview">
|
||||
<info keyboard="k_212_marker_11057.xml" author="Team Keyboard" name="marker" />
|
||||
<tests name="regression-11057">
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE keyboardTest3 SYSTEM "../../../../../resources/standards-data/ldml-keyboards/45/dtd/ldmlKeyboardTest3.dtd">
|
||||
<!DOCTYPE keyboardTest3 SYSTEM "../../../../../resources/standards-data/ldml-keyboards/46/dtd/ldmlKeyboardTest3.dtd">
|
||||
<keyboardTest3 conformsTo="techpreview">
|
||||
<info keyboard="ldml_test.xml" author="srl295" name="test" />
|
||||
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@
|
|||
#
|
||||
|
||||
|
||||
# keyboards in resources/standards-data/ldml-keyboards/45/3.0/
|
||||
# tests in resources/standards-data/ldml-keyboards/45/test/
|
||||
# keyboards in resources/standards-data/ldml-keyboards/46/3.0/
|
||||
# tests in resources/standards-data/ldml-keyboards/46/test/
|
||||
tests_from_cldr = [
|
||||
'ja-Latn',
|
||||
'pt-t-k0-abnt2',
|
||||
|
|
@ -57,7 +57,7 @@ tests += tests_from_cldr
|
|||
# Setup kmc
|
||||
|
||||
kmc_root = meson.global_source_root() / '../developer/src/kmc'
|
||||
ldml_root = meson.global_source_root() / '../resources/standards-data/ldml-keyboards/45'
|
||||
ldml_root = meson.global_source_root() / '../resources/standards-data/ldml-keyboards/46'
|
||||
ldml_data = join_paths(ldml_root, '3.0')
|
||||
ldml_testdata = join_paths(ldml_root, 'test')
|
||||
kmc_cmd = [node, '--enable-source-maps', kmc_root]
|
||||
|
|
|
|||
|
|
@ -0,0 +1,34 @@
|
|||
---
|
||||
title: Clone GitHub Project Parameters Dialog
|
||||
---
|
||||
|
||||

|
||||
|
||||
Allows you to clone a project from a GitHub repository, giving the project a
|
||||
new id, and organizing project files following the
|
||||
[file layout](/developer/keyboards/) used in the
|
||||
[Keyman keyboards repository](https://github.com/keymanapp/keyboards).
|
||||
|
||||
Keyboard and lexical model projects can be cloned.
|
||||
|
||||
Projects can also be cloned from the command line with [`kmc copy`](kmc).
|
||||
|
||||
### Parameters
|
||||
|
||||
GitHub URL:
|
||||
: The full URL to a source project .kpj file to copy, on github.com.
|
||||
|
||||
Destination path
|
||||
: Specifies the base path where the project folder will be created.
|
||||
The project folder name will be the keyboard ID. If the folder
|
||||
already exists, then you will be prompted before Keyman Developer
|
||||
overwrites files inside it.
|
||||
|
||||
New project ID
|
||||
: The base filename of the keyboard/model, project and package. This must
|
||||
conform to the Keyman keyboard or lexical model identifier rules.
|
||||
|
||||
Relocate external files into new project folder
|
||||
: When selected, if the project references files that are not inside the same
|
||||
folder as the .kpj file, move these files into an `external` subfolder
|
||||
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
---
|
||||
title: Clone Keyman Cloud Project Parameters Dialog
|
||||
---
|
||||
|
||||

|
||||
|
||||
Allows you to clone a project from Keyman Cloud, giving the project a
|
||||
new id, and organizing project files following the
|
||||
[file layout](/developer/keyboards/) used in the
|
||||
[Keyman keyboards repository](https://github.com/keymanapp/keyboards).
|
||||
|
||||
Projects can also be cloned from the command line with [`kmc copy`](kmc).
|
||||
|
||||
Only keyboard projects can be cloned from Keyman Cloud at this time via this
|
||||
dialog. Lexical model projects can be cloned from Keyman Cloud via the command
|
||||
line.
|
||||
|
||||
Search for a keyboard using the standard keyman.com keyboard search in the upper
|
||||
pane. Once you select a keyboard, and fill in the New Project Details, the OK
|
||||
button will be enabled to allow you to finish the cloning process.
|
||||
|
||||
### Parameters
|
||||
|
||||
Destination path
|
||||
: Specifies the base path where the project folder will be created.
|
||||
The project folder name will be the keyboard ID. If the folder
|
||||
already exists, then you will be prompted before Keyman Developer
|
||||
overwrites files inside it.
|
||||
|
||||
New project ID
|
||||
: The base filename of the keyboard, project and package. This must
|
||||
conform to the Keyman keyboard identifier rules.
|
||||
|
||||
Relocate external files into new project folder
|
||||
: When selected, if the project references files that are not inside the same
|
||||
folder as the .kpj file, move these files into an `external` subfolder
|
||||
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
---
|
||||
title: Clone Local Project Parameters Dialog
|
||||
---
|
||||
|
||||

|
||||
|
||||
Allows you to clone a project from your local filesystem, giving the project a
|
||||
new id, and organizing project files following the
|
||||
[file layout](/developer/keyboards/) used in the
|
||||
[Keyman keyboards repository](https://github.com/keymanapp/keyboards).
|
||||
|
||||
Keyboard and lexical model projects can be cloned.
|
||||
|
||||
Projects can also be cloned from the command line with [`kmc copy`](kmc).
|
||||
|
||||
### Parameters
|
||||
|
||||
Source project filename
|
||||
: The full path of the source project .kpj file to copy.
|
||||
|
||||
Destination path
|
||||
: Specifies the base path where the project folder will be created.
|
||||
The project folder name will be the keyboard ID. If the folder
|
||||
already exists, then you will be prompted before Keyman Developer
|
||||
overwrites files inside it.
|
||||
|
||||
New project ID
|
||||
: The base filename of the keyboard/model, project and package. This must
|
||||
conform to the Keyman keyboard or lexical model identifier rules.
|
||||
|
||||
Relocate external files into new project folder
|
||||
: When selected, if the project references files that are not inside the same
|
||||
folder as the .kpj file, move these files into an `external` subfolder
|
||||
|
||||
|
|
@ -21,4 +21,28 @@ Creates a keyboard project that matches the folder structure used in the Keyman
|
|||
|
||||
Creates a lexical model project that matches the folder structure used in the Keyman [lexical models repository](https://github.com/keymanapp/lexical-models) and includes all basic files needed for a lexical model project. Clicking OK will open the [New Lexical Model Project Parameters dialog](new-lm-project-parameters).
|
||||
|
||||
The **Basic** and **Import Windows Keyboard** modes can also be driven by command line with [KMConvert](kmconvert).
|
||||
## Clone local project
|
||||
|
||||
Copies a Keyman keyboard or lexical model project on your local filesystem into
|
||||
a new folder, giving the project and included files a new name. Clicking OK will
|
||||
open the [Clone Local Project Parameters dialog](clone-local-project-parameters).
|
||||
|
||||
## Clone project from Keyman Cloud
|
||||
|
||||
Copies a Keyman keyboard or lexical model project from keyman.com into a new
|
||||
folder, giving the project and included files a new name. Clicking OK will
|
||||
open the [Clone Keyman Cloud Project Parameters dialog](clone-keyman-cloud-project-parameters).
|
||||
|
||||
## Clone project from GitHub
|
||||
|
||||
Copies a Keyman keyboard or lexical model project from a GitHub repository into
|
||||
a new folder, giving the project and included files a new name. Clicking OK will
|
||||
open the [Clone GitHub Project Parameters dialog](clone-github-project-parameters).
|
||||
|
||||
# Command line access
|
||||
|
||||
[`kmc generate`](kmc) can be used to generate new Keyman keyboards, LDML
|
||||
keyboards, and Wordlist lexical models from the command line.
|
||||
|
||||
[KMConvert](kmconvert) can also be used to import Windows keyboards from the
|
||||
command line.
|
||||
|
|
|
|||
|
After Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 43 KiB |
BIN
developer/docs/help/images/ui/frmCloneLocalProjectParameters.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 43 KiB After Width: | Height: | Size: 9.6 KiB |
|
|
@ -1,5 +1,5 @@
|
|||
---
|
||||
title: Keyman Developer 18.0 User Guide
|
||||
title: Keyman Developer 19.0 User Guide
|
||||
---
|
||||
|
||||
Need help using Keyman Developer to create your keyboard layouts? You'll
|
||||
|
|
@ -8,7 +8,7 @@ and tutorials, and full reference information.
|
|||
|
||||
## Guides and Tutorials
|
||||
- [What is Keyman Developer?](guides/intro)
|
||||
- [What's new in 18.0](whats-new)
|
||||
- [What's new in 19.0](whats-new)
|
||||
- [Developing Keyman keyboard layouts](guides/develop)
|
||||
- [Testing Keyman keyboards](guides/test)
|
||||
- [Distributing Keyman keyboards](guides/distribute)
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ configuration or installation is required.
|
|||
kmc is also available as an npm package,
|
||||
[@keymanapp/kmc](https://npmjs.com/package/@keymanapp/kmc).
|
||||
|
||||
You'll need [node.js](https://nodejs.org/), version 18.0 or later.
|
||||
You'll need [node.js](https://nodejs.org/), version 20.0 or later.
|
||||
|
||||
```shell
|
||||
npm install -g @keymanapp/kmc
|
||||
|
|
|
|||
|
|
@ -90,14 +90,33 @@ The following parameters are available:
|
|||
|
||||
: Prints the version number of kmc
|
||||
|
||||
`--no-error-reporting`, `--error-reporting`
|
||||
`--color`, `--no-color`
|
||||
|
||||
: Enable or disable error reporting to keyman.com, overriding [user
|
||||
settings](../../user-settings). Error reporting is for fatal errors in the
|
||||
compiler, and not errors in compiled files. No user data is sent in error
|
||||
: Controls colorization for log messages, using ANSI color controls. If both of
|
||||
these settings are omitted, kmc will attempt to detect from console, and will
|
||||
use colorization for interactive terminals, and no colorization when
|
||||
redirection is being used.
|
||||
|
||||
`--error-reporting`, `--no-error-reporting`
|
||||
|
||||
: Enable or disable error reporting to keyman.com, overriding
|
||||
[user settings](../../user-settings). Error reporting is for fatal errors in
|
||||
the compiler, and not errors in compiled files. No user data is sent in error
|
||||
reports, although some filenames and paths may be present in the diagnostic
|
||||
data attached to the report.
|
||||
|
||||
`--log-format <logFormat>`
|
||||
|
||||
: Output log format. The available options are:
|
||||
* `formatted` (default): emits log messages in a human-readable format
|
||||
* `tsv`: emits log messages in UTF-8 tab-separated format. This format will be
|
||||
stable across versions of kmc. The format has the following fields:
|
||||
* filename
|
||||
* line number
|
||||
* severity
|
||||
* code
|
||||
* message
|
||||
|
||||
`-l <logLevel>`, `--log-level <logLevel>`
|
||||
|
||||
: Controls the level of logging to console for messages relating to the
|
||||
|
|
@ -108,9 +127,12 @@ The following parameters are available:
|
|||
* `hint`: emits compilation errors, warnings, and hints
|
||||
* `info` (default): emits compilation errors, warnings, hints, and
|
||||
informational messages
|
||||
* `verbose`: emits all compilation messages, including verbose
|
||||
informational messages
|
||||
* `debug`: emits all compilation messages, plus internal debug messages
|
||||
|
||||
Logging of specific [messages](messages) can be controlled with `--message`, `-m`.
|
||||
Logging of specific [messages](messages) can be controlled with `--message`,
|
||||
`-m` (`build` command only).
|
||||
|
||||
Note that when warnings are treated as errors
|
||||
(`--compiler-warnings-as-errors`, `-w`), they will still be logged as
|
||||
|
|
@ -118,13 +140,6 @@ The following parameters are available:
|
|||
|
||||
## `kmc build` options
|
||||
|
||||
`--color`, `--no-color`
|
||||
|
||||
: Controls colorization for log messages, using ANSI color controls. If both of
|
||||
these settings are omitted, kmc will attempt to detect from console, and will
|
||||
use colorization for interactive terminals, and no colorization when
|
||||
redirection is being used.
|
||||
|
||||
`-d`, `--debug`
|
||||
|
||||
: Include debug information in output files. Debug information is used for
|
||||
|
|
@ -167,17 +182,6 @@ The following parameters are available:
|
|||
: Turns off warnings (CWARN_HeaderStatementIsDeprecated,
|
||||
CWARN_LanguageHeadersDeprecatedInKeyman10) for deprecated code styles
|
||||
|
||||
`--log-format <logFormat>`
|
||||
|
||||
: Output log format. The available options are:
|
||||
* `formatted` (default): emits log messages in a human-readable format
|
||||
* `tsv`: emits log messages in UTF-8 tab-separated format. This format will be
|
||||
stable across versions of kmc. The format has the following fields:
|
||||
* filename
|
||||
* line number
|
||||
* severity
|
||||
* code
|
||||
* message
|
||||
|
||||
`-o <filename>`, `--out-file <filename>`
|
||||
|
||||
|
|
@ -509,6 +513,12 @@ following sources:
|
|||
|
||||
: Show what would happen, without making changes
|
||||
|
||||
`-r, --relocate-external`
|
||||
|
||||
: Copy referenced files that are outside the project folder into an 'external'
|
||||
folder within the new project, rather than just referencing them in their
|
||||
current location.
|
||||
|
||||
### File copying, renaming, and structure rules
|
||||
|
||||
The **origin** project folder is the one that contains the .kpj file. When a
|
||||
|
|
|
|||
|
|
@ -1,43 +1,5 @@
|
|||
---
|
||||
title: What's new in Keyman Developer 18.0
|
||||
title: What's new in Keyman Developer 19.0
|
||||
---
|
||||
|
||||
Keyman Developer 17 has a number of significant changes:
|
||||
|
||||
* `kmcomp` has been removed and replaced with `kmc`. Learn more in our [kmcomp migration guide](reference/kmc/cli/kmcomp-migration).
|
||||
|
||||
* Windows installer packages should now be built with
|
||||
`kmc build windows-package-installer` and can no longer be built within
|
||||
the Keyman Developer IDE. More details on how to use this are in the
|
||||
[`kmc` reference documentation](reference/kmc/cli/reference#toc-kmc-build-windows-package-installer-additional-options).
|
||||
|
||||
* `.keyboard_info` files are now generated entirely from the package and
|
||||
keyboard files. Extra fields are available in packages for license file,
|
||||
welcome file, typing examples, related packages (including deprecated
|
||||
packages), and additional font files. Keyboards in the Keyman Cloud
|
||||
keyboard repository have already been updated; if you are an author of
|
||||
one of these keyboards, you should pull the changes from the repository
|
||||
before submitting future updates.
|
||||
|
||||
* Keyboard project files (.kpj) now have a new format which does not list
|
||||
individual files, but instead includes all files in the same folder and
|
||||
subfolders relative to the project file. This prevents projects from
|
||||
including unrelated files, and reduces the number of files that change
|
||||
when keyboards are updated.
|
||||
|
||||
* Keyman Developer will now open each project in a new window, allowing
|
||||
the user to rapidly switch between multiple projects at the same time.
|
||||
|
||||
* The Keyman Keyboard and Lexical Model Cloud repositories have new build
|
||||
scripts which run `kmc`. These run much, much faster than previously!
|
||||
|
||||
* The [`&displayMap`](/developer/language/reference/displaymap) store allows
|
||||
keyboard developers to specify a font mapping to PUA for the On Screen
|
||||
Keyboard and Touch Layout to resolve diacritic rendering issues.
|
||||
|
||||
* Keyman Developer has been updated to support Unicode 15.1.
|
||||
|
||||
* Additional non-printing characters have been added to the Touch Layout Editor.
|
||||
|
||||
* Virtual keys in output of rules have never worked properly or been officially
|
||||
supported; Keyman Developer will now warn if you attempt to use this pattern.
|
||||
Keyman Developer 19 has the following significant changes:
|
||||
|
|
|
|||
|
|
@ -156,6 +156,7 @@ function do_publish() {
|
|||
|
||||
./common/web/utils/build.sh publish $DRY_RUN $NPM_PUBLISH
|
||||
../../common/web/keyman-version/build.sh publish $DRY_RUN $NPM_PUBLISH
|
||||
../../common/web/langtags/build.sh publish $DRY_RUN $NPM_PUBLISH
|
||||
../../common/web/types/build.sh publish $DRY_RUN $NPM_PUBLISH
|
||||
../../core/include/ldml/build.sh publish $DRY_RUN $NPM_PUBLISH
|
||||
# end TODO
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ interface
|
|||
|
||||
type
|
||||
TLexicalModelUtils = class
|
||||
private
|
||||
public
|
||||
const SPackageNameDoesNotFollowLexicalModelConventions_Message: string =
|
||||
'The package file %0:s does not follow the recommended model filename conventions. The name should be all lower case, '+
|
||||
|
|
@ -31,6 +30,8 @@ type
|
|||
class function CleanLexicalModelIDComponent(const Name: string): string; static;
|
||||
class function IsCleanLexicalModelIDComponent(const Name: string): Boolean; static;
|
||||
|
||||
class function IsValidLexicalModelID(ID: string; EnforceCaseAndWhitespace: Boolean): Boolean; static;
|
||||
|
||||
class function ExtractFileExt(filename: string): string; static;
|
||||
class function RemoveFileExt(filename: string): string; static;
|
||||
class function ChangeFileExt(filename, ext: string): string; static;
|
||||
|
|
@ -51,11 +52,20 @@ const
|
|||
|
||||
// The model ID SHOULD adhere to this pattern (see also developer/src/kmc-model):
|
||||
// author .bcp47 .uniq
|
||||
MODEL_ID_PATTERN = '^[a-z_][a-z0-9_]*\.[a-z_][a-z0-9_-]*\.[a-z_][a-z0-9_]*$';
|
||||
MODEL_ID_PATTERN_JS = '^[a-z_][a-z0-9_]*\.[a-z_][a-z0-9_-]*\.[a-z_][a-z0-9_]*\.model\.js$';
|
||||
MODEL_ID_PATTERN_TS = '^[a-z_][a-z0-9_]*\.[a-z_][a-z0-9_-]*\.[a-z_][a-z0-9_]*\.model\.ts$';
|
||||
MODEL_ID_PATTERN_PACKAGE = '^[a-z_][a-z0-9_]*\.[a-z_][a-z0-9_-]*\.[a-z_][a-z0-9_]*\.model\.(kps|kmp)$';
|
||||
MODEL_ID_PATTERN_PROJECT = '^[a-z_][a-z0-9_]*\.[a-z_][a-z0-9_-]*\.[a-z_][a-z0-9_]*\.model\.kpj$';
|
||||
|
||||
class function TLexicalModelUtils.IsValidLexicalModelID(ID: string;
|
||||
EnforceCaseAndWhitespace: Boolean): Boolean;
|
||||
begin
|
||||
if not EnforceCaseAndWhitespace then
|
||||
ID := LowerCase(Trim(ID));
|
||||
Result := TRegEx.IsMatch(ID, MODEL_ID_PATTERN);
|
||||
end;
|
||||
|
||||
class function TLexicalModelUtils.DoesJSFilenameFollowLexicalModelConventions(
|
||||
const Name: string): Boolean;
|
||||
begin
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { CompilerError, CompilerErrorMask } from '@keymanapp/developer-utils';
|
||||
import { CompilerError, CompilerErrorMask, CompilerEvent, dedentCompilerMessageDetail } from '@keymanapp/developer-utils';
|
||||
import {assert, expect} from 'chai';
|
||||
|
||||
//
|
||||
|
|
@ -37,8 +37,24 @@ export function verifyCompilerMessagesObject(source: Record<string,any>, namespa
|
|||
const c = o[1].toUpperCase() + '_' + o[2];
|
||||
expect(m[c]).to.be.a('number', `Expected constant name ${c} to exist`);
|
||||
|
||||
const v = m[key]('','','','','','','','','','','','' /* ignore arguments*/);
|
||||
const v: CompilerEvent = m[key]('','','','','','','','','','','','' /* ignore arguments*/);
|
||||
expect(v.code).to.equal(m[c], `Function ${key} returns the wrong code`);
|
||||
|
||||
assert.isNotNull(v.message, `Function ${key} returns an invalid message: '${v.message}'`);
|
||||
assert.isNotEmpty(v.message, `Function ${key} returns an empty message: '${v.message}'`);
|
||||
|
||||
// Verify layout of compiler detail lines
|
||||
|
||||
if(v.detail) {
|
||||
const detail = dedentCompilerMessageDetail(v).split('\n');
|
||||
for(const line of detail) {
|
||||
// Prevent lines over 80 characters -- we don't rewrap at this stage
|
||||
// Don't check lines with URLs because they may be forced to go long
|
||||
if(!line.includes('http')) {
|
||||
assert.isAtMost(line.length, 80, `Function ${key} returns a message detail with at least one line longer than 80 characters: '${line}'`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(typeof m[key] == 'number') {
|
||||
const o = /^(DEBUG|VERBOSE|INFO|HINT|WARN|ERROR|FATAL)_([A-Za-z0-9_]+)$/.exec(key);
|
||||
|
|
|
|||
|
|
@ -291,10 +291,8 @@ export interface CompilerMessageOverride {
|
|||
level: CompilerErrorSeverityOverride;
|
||||
};
|
||||
|
||||
export interface CompilerCallbackOptions {
|
||||
logLevel?: CompilerLogLevel;
|
||||
logFormat?: CompilerLogFormat;
|
||||
color?: boolean; // null or undefined == use console default
|
||||
export interface CompilerCallbackOptions extends CompilerBaseOptions {
|
||||
// TODO: these overlap with CompilerOptions, should refactor
|
||||
compilerWarningsAsErrors?: boolean;
|
||||
messageOverrides?: CompilerMessageOverrideMap;
|
||||
};
|
||||
|
|
@ -401,6 +399,19 @@ export const CompilerMessageSpec = (code: number, message: string, detail?: stri
|
|||
detail,
|
||||
});
|
||||
|
||||
/**
|
||||
* Remove initial whitespace from compiler detail messages, to enable
|
||||
* indented formatting of message detail strings inside the message
|
||||
* definitions
|
||||
* @param event
|
||||
* @returns dedented event detail
|
||||
*/
|
||||
export function dedentCompilerMessageDetail(event: CompilerEvent) {
|
||||
// TODO(lowpri): dedent may be too naive -- should use least
|
||||
// non-zero whitespace line as amount to dedent
|
||||
return (event.detail ?? '').replace(/^[ ]+/gm, '');
|
||||
}
|
||||
|
||||
export const CompilerMessageDef = (param: any) => String(param ?? `<param>`);
|
||||
|
||||
export const CompilerMessageSpecWithException = (code: number, message: string, exceptionVar: any, detail?: string) : CompilerEvent => ({
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ export { defaultCompilerOptions, CompilerBaseOptions, CompilerOptions, CompilerE
|
|||
ALL_COMPILER_LOG_FORMATS, CompilerLogFormat,
|
||||
CompilerMessageOverride,
|
||||
CompilerMessageOverrideMap,
|
||||
|
||||
dedentCompilerMessageDetail,
|
||||
KeymanCompilerArtifact,
|
||||
KeymanCompilerArtifactOptional,
|
||||
KeymanCompilerArtifacts,
|
||||
|
|
|
|||
|
|
@ -231,6 +231,10 @@ export class LDMLKeyboardXMLSourceFileReader {
|
|||
this.callbacks.reportMessage(CommonTypesMessages.Error_ImportInvalidPath({base, path, subtag}));
|
||||
return false;
|
||||
}
|
||||
if (constants.treatAsLatest(paths[0])) {
|
||||
/** There's no data or DTD change in 45, 46, 46.1, 47 so map them all to 46 at present. */
|
||||
paths[0] = constants.cldr_version_latest;
|
||||
}
|
||||
importData = this.readImportFile(paths[0], paths[1]);
|
||||
} else {
|
||||
// local import
|
||||
|
|
|
|||
|
|
@ -64,11 +64,17 @@ export class KeymanSentry {
|
|||
}
|
||||
}
|
||||
|
||||
static async captureException(e: any): Promise<never> {
|
||||
/**
|
||||
* capture an exception for Sentry; note that in local environments, this will normally
|
||||
* throw the exception rather than sending to Sentry
|
||||
* @param e
|
||||
* @param force if true, reports to Sentry even in local environments
|
||||
*/
|
||||
static async captureException(e: any, force?: boolean): Promise<never> {
|
||||
if(isInit) {
|
||||
// For local development, we don't want to bury the trace; we need the cast to avoid
|
||||
// TS2367 (comparison appears to be unintentional)
|
||||
if((KEYMAN_VERSION.VERSION_ENVIRONMENT as string) == 'local') {
|
||||
if(!force && (KEYMAN_VERSION.VERSION_ENVIRONMENT as string) == 'local') {
|
||||
throw e;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,6 @@
|
|||
<keyboard3 xmlns="https://schemas.unicode.org/cldr/45/keyboard3" locale="und" conformsTo="45">
|
||||
<info author="srl295" indicator="🙀" layout="qwerty" name="Test Minimal Keyboard"/>
|
||||
<keys>
|
||||
<import base="" path="keys-Zyyy-morepunctuation.xml"/>
|
||||
<import path="keys-Zyyy-morepunctuation.xml"/>
|
||||
</keys>
|
||||
</keyboard3>
|
||||
|
|
|
|||
|
|
@ -2,6 +2,6 @@
|
|||
<keyboard3 xmlns="https://schemas.unicode.org/cldr/45/keyboard3" locale="und" conformsTo="45">
|
||||
<info author="srl295" indicator="🙀" layout="qwerty" name="Test Minimal Keyboard"/>
|
||||
<keys>
|
||||
<import base="" path="keys-Zyyy-DOESNOTEXIST.xml"/>
|
||||
<import path="keys-Zyyy-DOESNOTEXIST.xml"/>
|
||||
</keys>
|
||||
</keyboard3>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE keyboardTest3 SYSTEM "../../../../../resources/standards-data/ldml-keyboards/45/dtd/ldmlKeyboardTest3.dtd">
|
||||
<!DOCTYPE keyboardTest3 SYSTEM "../../../../../resources/standards-data/ldml-keyboards/46/dtd/ldmlKeyboardTest3.dtd">
|
||||
<keyboardTest3 conformsTo="techpreview">
|
||||
<!--
|
||||
Read by:
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Note: similar to, but slightly ahead of, fr-t-k0-azerty -->
|
||||
<!DOCTYPE keyboardTest3 SYSTEM "../../../../../resources/standards-data/ldml-keyboards/45/dtd/ldmlKeyboardTest3.dtd">
|
||||
<!DOCTYPE keyboardTest3 SYSTEM "../../../../../resources/standards-data/ldml-keyboards/46/dtd/ldmlKeyboardTest3.dtd">
|
||||
<keyboardTest3 conformsTo="techpreview">
|
||||
<info keyboard="k_020_fr.xml" author="Team Keyboard" name="fr-test-updated" />
|
||||
<repertoire name="simple-repertoire" chars="[a b c d e \u0022]" type="simple" /> <!-- verify that these outputs are all available from simple keys on any layer, for all form factors -->
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ describe('ldml keyboard xml reader tests', function () {
|
|||
instancePath: '/keyboard3/conformsTo',
|
||||
keyword: 'enum',
|
||||
message: `must be equal to one of the allowed values`,
|
||||
params: 'allowedValues="45"',
|
||||
params: 'allowedValues="45,46"', // this has to be kept in sync with the DTD
|
||||
})],
|
||||
},
|
||||
{
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@
|
|||
<Directory Id="dirNode" Name="node.js" />
|
||||
<Directory Id="dirProjects" Name="Projects" />
|
||||
<Directory Id="dir_import" Name="import">
|
||||
<Directory Id="dir_import_45" Name="45" />
|
||||
<Directory Id="dir_import_46" Name="46" />
|
||||
</Directory>
|
||||
</Directory>
|
||||
</Directory>
|
||||
|
|
@ -198,7 +198,7 @@
|
|||
</ComponentGroup>
|
||||
|
||||
<!-- LDML Imports -->
|
||||
<ComponentGroup Id="LdmlImports" Directory="dir_import_45" Source="..\..\..\resources\standards-data\ldml-keyboards\45\import">
|
||||
<ComponentGroup Id="LdmlImports" Directory="dir_import_46" Source="..\..\..\resources\standards-data\ldml-keyboards\46\import">
|
||||
<Component>
|
||||
<File Id="LdmlImportReadme" Name="README.md" KeyPath="yes" />
|
||||
</Component>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# Bundled node.js
|
||||
|
||||
We are bundling node 18.14.1 here as of Keyman 17.0.52.
|
||||
We are bundling node 20.16.1 here as of Keyman 18.0.156-alpha
|
||||
|
||||
Note that if we change the node version, we will need to
|
||||
rebuild the binary modules in /developer/src/server/src/win32/
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
* Copy a keyboard or lexical model project
|
||||
*/
|
||||
|
||||
import { CloudUrls, GitHubUrls, CompilerCallbacks, CompilerLogLevel, KeymanCompiler, KeymanCompilerArtifact, KeymanCompilerArtifacts, KeymanCompilerResult, KeymanDeveloperProject, KeymanDeveloperProjectOptions, KPJFileReader, KPJFileWriter, KpsFileReader, KpsFileWriter, ValidIds } from "@keymanapp/developer-utils";
|
||||
import { CloudUrls, GitHubUrls, CompilerCallbacks, KeymanCompiler, KeymanCompilerArtifact, KeymanCompilerArtifacts, KeymanCompilerResult, KeymanDeveloperProject, KeymanDeveloperProjectOptions, KPJFileReader, KPJFileWriter, KpsFileReader, KpsFileWriter, ValidIds, CompilerBaseOptions } from "@keymanapp/developer-utils";
|
||||
import { KeymanFileTypes } from "@keymanapp/common-types";
|
||||
|
||||
import { CopierMessages } from "./copier-messages.js";
|
||||
|
|
@ -19,12 +19,7 @@ type CopierFunction = (
|
|||
* @public
|
||||
* Options for the Keyman Developer project copier
|
||||
*/
|
||||
export interface CopierOptions /* not inheriting from CompilerBaseOptions */ {
|
||||
/**
|
||||
* Reporting level to console, used by NodeCompilerCallbacks (not used in
|
||||
* compiler modules; all messages are still reported to the internal log)
|
||||
*/
|
||||
logLevel?: CompilerLogLevel;
|
||||
export interface CopierOptions extends CompilerBaseOptions {
|
||||
/**
|
||||
* output path where project folder will be created
|
||||
*/
|
||||
|
|
@ -33,6 +28,12 @@ export interface CopierOptions /* not inheriting from CompilerBaseOptions */ {
|
|||
* dryRun: show what would happen
|
||||
*/
|
||||
dryRun: boolean;
|
||||
/**
|
||||
* Copy referenced files that are outside the project folder into an
|
||||
* 'external' folder within the new project, rather than just referencing them
|
||||
* in their current location
|
||||
*/
|
||||
relocateExternalFiles?: boolean;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -78,7 +79,6 @@ export class KeymanProjectCopier implements KeymanCompiler {
|
|||
isLocalOrigin(): boolean {
|
||||
return this.githubRef == undefined;
|
||||
}
|
||||
relocateExternalFiles: boolean = false; // TODO-COPY: support
|
||||
|
||||
public async init(callbacks: CompilerCallbacks, options: CopierOptions): Promise<boolean> {
|
||||
if(!callbacks || !options) {
|
||||
|
|
@ -357,6 +357,7 @@ export class KeymanProjectCopier implements KeymanCompiler {
|
|||
const subFilename = this.normalizePath(this.resolveFilename(project.projectFilename, normalizedFilePath));
|
||||
const copier = this.copiers[<KeymanFileTypes.Source> file.fileType] ?? this.copyGenericFile.bind(this);
|
||||
// Ignore errors because we will continue to do a best effort
|
||||
this.callbacks.reportMessage(CopierMessages.Verbose_CopyingFile({from: normalizedFilePath, to: subFilename}));
|
||||
await copier(project, subFilename, subOutputPath, source, result);
|
||||
}
|
||||
|
||||
|
|
@ -559,20 +560,25 @@ export class KeymanProjectCopier implements KeymanCompiler {
|
|||
|
||||
let subOutputPath: string;
|
||||
if(this.callbacks.path.isAbsolute(subFilenameRelative) || subFilenameRelative.startsWith('..')) {
|
||||
if(this.isLocalOrigin() && !this.relocateExternalFiles) {
|
||||
if(this.isLocalOrigin() && !this.options.relocateExternalFiles) {
|
||||
// Reference outside the project structure, do not attempt to normalize or copy,
|
||||
// but we do need to update references for the new output path
|
||||
return this.normalizePath(this.callbacks.path.relative(result.artifacts[parentFilename].filename, subFilenameAbsolute));
|
||||
const destinationFilename =
|
||||
this.normalizePath(this.callbacks.path.relative(result.artifacts[parentFilename].filename, subFilenameAbsolute));
|
||||
this.callbacks.reportMessage(CopierMessages.Verbose_CopyingFile({from: originalSubfilename, to: destinationFilename}));
|
||||
return destinationFilename;
|
||||
} else {
|
||||
// Reference outside the project structure, we will copy into a subfolder of the project;
|
||||
// should be relative to root of remote repo, e.g. release/k/khmer_angkor references release/shared/fonts/...,
|
||||
// so should go external/release/shared/fonts/...
|
||||
subOutputPath = this.normalizePath(this.callbacks.path.join(this.options.outPath, 'external', this.callbacks.path.dirname(subFilenameAbsolute)));
|
||||
const relativePath = this.callbacks.path.dirname(subFilenameRelative).replace(/\.\.[/\\]/g, '');
|
||||
subOutputPath = this.normalizePath(this.callbacks.path.join(this.options.outPath, 'external', relativePath));
|
||||
}
|
||||
} else {
|
||||
subOutputPath = this.normalizePath(this.callbacks.path.join(outputPath, this.callbacks.path.dirname(originalSubfilename)));
|
||||
}
|
||||
|
||||
this.callbacks.reportMessage(CopierMessages.Verbose_CopyingFile({from: originalSubfilename, to: subFilename}));
|
||||
await this.copyGenericFile(project, subFilename, subOutputPath, source, result);
|
||||
|
||||
// Even if the subfile is missing, we'll still continue the overall copy
|
||||
|
|
|
|||
|
|
@ -19,9 +19,10 @@ const SevFatal = CompilerErrorSeverity.Fatal | Namespace;
|
|||
*/
|
||||
export class CopierMessages {
|
||||
static FATAL_UnexpectedException = SevFatal | 0x0001;
|
||||
static Fatal_UnexpectedException = (o:{e: any}) => m(
|
||||
static Fatal_UnexpectedException = (o:{e: any}) => CompilerMessageSpecWithException(
|
||||
this.FATAL_UnexpectedException,
|
||||
null, o.e ?? 'unknown error'
|
||||
null,
|
||||
o.e ?? 'unknown error'
|
||||
);
|
||||
|
||||
static INFO_CopyingProject = SevInfo | 0x0002;
|
||||
|
|
@ -123,81 +124,90 @@ export class CopierMessages {
|
|||
static ERROR_CannotDownloadFolderFromGitHub = SevError | 0x0012;
|
||||
static Error_CannotDownloadFolderFromGitHub = (o:{ref: string, message?: string, cause?: string}) => m(
|
||||
this.ERROR_CannotDownloadFolderFromGitHub,
|
||||
`The folder '${def(o.ref)}' could not be downloaded: ${def(o.message)} ${def(o.cause)}`,
|
||||
`An error was encountered attempting to download a folder from GitHub API. Check the
|
||||
provided error details for the cause.`
|
||||
);
|
||||
`The folder '${def(o.ref)}' could not be downloaded: ${def(o.message)} ${def(o.cause)}`, `
|
||||
An error was encountered attempting to download a folder from GitHub API. Check
|
||||
the provided error details for the cause.
|
||||
`);
|
||||
|
||||
static ERROR_FolderDownloadedFromGitHubIsNotAValidFolder = SevError | 0x0013;
|
||||
static Error_FolderDownloadedFromGitHubIsNotAValidFolder = (o:{ref: string}) => m(
|
||||
this.ERROR_FolderDownloadedFromGitHubIsNotAValidFolder,
|
||||
`The path '${def(o.ref)}' does not appear to be a folder on GitHub`,
|
||||
`The provided path may be a file or may not exist. Check the reference
|
||||
before trying again.`
|
||||
);
|
||||
`The path '${def(o.ref)}' does not appear to be a folder on GitHub`, `
|
||||
The provided path may be a file or may not exist. Check the reference
|
||||
before trying again.
|
||||
`);
|
||||
|
||||
static WARN_CannotDownloadFileFromGitHub = SevWarn | 0x0014;
|
||||
static Warn_CannotDownloadFileFromGitHub = (o:{ref: string, message?: string, cause?: string}) => m(
|
||||
this.WARN_CannotDownloadFileFromGitHub,
|
||||
`The file '${def(o.ref)}' could not be downloaded: ${def(o.message)} ${def(o.cause)}`,
|
||||
`An error was encountered attempting to download a file from GitHub. Check the
|
||||
provided error details for the cause.`
|
||||
);
|
||||
`The file '${def(o.ref)}' could not be downloaded: ${def(o.message)} ${def(o.cause)}`, `
|
||||
An error was encountered attempting to download a file from GitHub. Check the
|
||||
provided error details for the cause.
|
||||
`);
|
||||
|
||||
static ERROR_InvalidCloudKeyboardId = SevError | 0x0015;
|
||||
static Error_InvalidCloudKeyboardId = (o:{id: string}) => m(
|
||||
this.ERROR_InvalidCloudKeyboardId,
|
||||
`The keyboard identifier '${def(o.id)}' is not a valid keyboard identifier`,
|
||||
`Keyboard identifiers on Keyman Cloud can only use the characters a-z, 0-9, and _.`
|
||||
);
|
||||
`The keyboard identifier '${def(o.id)}' is not a valid keyboard identifier`, `
|
||||
Keyboard identifiers on Keyman Cloud can only use the characters
|
||||
\`a\`-\`z\`, \`0\`-\`9\`, and \`_\`.
|
||||
`);
|
||||
|
||||
static ERROR_CouldNotRetrieveFromCloud = SevError | 0x0016;
|
||||
static Error_CouldNotRetrieveFromCloud = (o:{id: string, message?: string, cause?: string}) => m(
|
||||
this.ERROR_CouldNotRetrieveFromCloud,
|
||||
`Details for keyboard or model identified by '${def(o.id)}' could not be downloaded: ${def(o.message)} ${def(o.cause)}`,
|
||||
`An error was encountered attempting to retrieve keyboard or model details from Keyman Cloud API. Check the
|
||||
provided error details for the cause.`
|
||||
);
|
||||
`Details for keyboard or model identified by '${def(o.id)}' could not be `+
|
||||
`downloaded: ${def(o.message)} ${def(o.cause)}`, `
|
||||
An error was encountered attempting to retrieve keyboard or model details from
|
||||
Keyman Cloud API. Check the provided error details for the cause.
|
||||
`);
|
||||
|
||||
static ERROR_KeymanCloudReturnedInvalidData = SevError | 0x0017;
|
||||
static Error_KeymanCloudReturnedInvalidData = (o:{id: string}) => m(
|
||||
this.ERROR_KeymanCloudReturnedInvalidData,
|
||||
`Keyman Cloud API returned invalid data for keyboard or model identified by '${def(o.id)}'`,
|
||||
`There may be a network error or a server error. Retry your request later or contact
|
||||
Keyman Support for assistance.`
|
||||
);
|
||||
`Keyman Cloud API returned invalid data for keyboard or model identified by '${def(o.id)}'`, `
|
||||
There may be a network error or a server error. Retry your request later or
|
||||
contact Keyman Support for assistance.
|
||||
`);
|
||||
|
||||
static ERROR_CloudDoesNotHaveSource = SevError | 0x0018;
|
||||
static Error_CloudDoesNotHaveSource = (o:{id: string}) => m(
|
||||
this.ERROR_CloudDoesNotHaveSource,
|
||||
`The keyboard or model identified by '${def(o.id)}' does not have source available`,
|
||||
`Legacy keyboards in Keyman Cloud do not have source available. Check the Keyman keyboard catalog
|
||||
at keyman.com for further details. Some new keyboards or models may be available as binary-only.`
|
||||
);
|
||||
`The keyboard or model identified by '${def(o.id)}' does not have source available`, `
|
||||
Legacy keyboards in Keyman Cloud do not have source available. Check the Keyman
|
||||
keyboard catalog at https://keyman.com/keyboards for further details. Some new
|
||||
keyboards or models may be available as binary-only.
|
||||
`);
|
||||
|
||||
static ERROR_CannotDownloadRepoFromGitHub = SevError | 0x0019 ;
|
||||
static Error_CannotDownloadRepoFromGitHub = (o:{ref: string, message?: string, cause?: string}) => m(
|
||||
this.ERROR_CannotDownloadRepoFromGitHub,
|
||||
`The repository at '${def(o.ref)}' could not be accessed: ${def(o.message)} ${def(o.cause)}`,
|
||||
`An error was encountered attempting to download details about a repository from GitHub API.
|
||||
Check the provided error details for the cause.`
|
||||
);
|
||||
`The repository at '${def(o.ref)}' could not be accessed: ${def(o.message)} ${def(o.cause)}`, `
|
||||
An error was encountered attempting to download details about a repository
|
||||
from GitHub API. Check the provided error details for the cause.
|
||||
`);
|
||||
|
||||
//------------------------------------------------------------------------------|
|
||||
// max length of detail message lines (checked by verifyCompilerMessagesObject) |
|
||||
//------------------------------------------------------------------------------|
|
||||
|
||||
static ERROR_CouldNotFindDefaultBranchOnGitHub = SevError | 0x001A;
|
||||
static Error_CouldNotFindDefaultBranchOnGitHub = (o:{ref: string}) => m(
|
||||
this.ERROR_CouldNotFindDefaultBranchOnGitHub,
|
||||
`The default branch could not be found for the GitHub repository '${def(o.ref)}'`,
|
||||
`The repository may be private, or you may have a typo in the owner or repository name.`
|
||||
);
|
||||
`The default branch could not be found for the GitHub repository '${def(o.ref)}'`, `
|
||||
The repository may be private, or you may have a typo in the owner or
|
||||
repository name.
|
||||
`);
|
||||
|
||||
static INFO_CannotDownloadBinaryFileFromGitHub = SevInfo | 0x001B;
|
||||
static Info_CannotDownloadBinaryFileFromGitHub = (o:{ref: string, message?: string, cause?: string}) => m(
|
||||
this.INFO_CannotDownloadBinaryFileFromGitHub,
|
||||
`The Keyman binary file '${def(o.ref)}' could not be downloaded: ${def(o.message)} ${def(o.cause)}. This is not normally a problem`,
|
||||
`In most repositories, Keyman binary files such as .kmx, .kmp, .js are not included.
|
||||
This is not normally a problem, as the files can be built from the source. Check
|
||||
the provided error details for more details.`
|
||||
);
|
||||
`The Keyman binary file '${def(o.ref)}' could not be downloaded: ${def(o.message)} `+
|
||||
`${def(o.cause)}. This is not normally a problem`, `
|
||||
In most repositories, Keyman binary files such as .kmx, .kmp, .js are not
|
||||
included. This is not normally a problem, as the files can be built from the
|
||||
source. Check the provided error details for more details.
|
||||
`);
|
||||
|
||||
static VERBOSE_DownloadingFile = SevVerbose | 0x001C;
|
||||
static Verbose_DownloadingFile = (o:{filename: string, url: string}) => m(
|
||||
|
|
@ -231,4 +241,10 @@ export class CopierMessages {
|
|||
`The output file '${def(o.filename)}' has two different possible source files.`,
|
||||
);
|
||||
|
||||
static VERBOSE_CopyingFile = SevVerbose | 0x0021;
|
||||
static Verbose_CopyingFile = (o:{from: string, to: string}) => m(
|
||||
this.VERBOSE_CopyingFile,
|
||||
`Copying file '${def(o.from)}' to '${def(o.to)}'`,
|
||||
);
|
||||
|
||||
};
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import { TestCompilerCallbacks } from '@keymanapp/developer-test-helpers';
|
|||
import { KeymanProjectCopier } from '../src/KeymanProjectCopier.js';
|
||||
import { makePathToFixture } from './helpers/index.js';
|
||||
import { GitHubRef } from './cloud.js';
|
||||
import { KpsFileReader } from '@keymanapp/developer-utils';
|
||||
|
||||
const { TEST_SAVE_ARTIFACTS, TEST_SAVE_FIXTURES } = env;
|
||||
let outputRoot: string = '/an/imaginary/root/';
|
||||
|
|
@ -269,8 +270,8 @@ describe('KeymanProjectCopier', function() {
|
|||
"/release/j/jawa/source/jawa2.bmp": "source/jawa2.bmp",
|
||||
"/release/j/jawa/source/readme.htm": "source/readme.htm",
|
||||
"/release/j/jawa/source/welcome/welcome.htm": "source/welcome/welcome.htm",
|
||||
"/release/shared/fonts/noto/Java/NotoSansJavanese-Bold.ttf": "external/release/shared/fonts/noto/Java/NotoSansJavanese-Bold.ttf",
|
||||
"/release/shared/fonts/noto/Java/NotoSansJavanese-Regular.ttf": "external/release/shared/fonts/noto/Java/NotoSansJavanese-Regular.ttf",
|
||||
"/release/shared/fonts/noto/Java/NotoSansJavanese-Bold.ttf": "external/shared/fonts/noto/Java/NotoSansJavanese-Bold.ttf",
|
||||
"/release/shared/fonts/noto/Java/NotoSansJavanese-Regular.ttf": "external/shared/fonts/noto/Java/NotoSansJavanese-Regular.ttf",
|
||||
// NOTE: the following files are not included because this is a 1.0
|
||||
// project and they are not referenced by any files:
|
||||
// * HISTORY.md
|
||||
|
|
@ -523,6 +524,103 @@ describe('KeymanProjectCopier', function() {
|
|||
]);
|
||||
});
|
||||
|
||||
it('should copy external files into an "external" folder when relocateExternalFiles is true', async function() {
|
||||
const copier = new KeymanProjectCopier();
|
||||
assert.isTrue(await copier.init(callbacks, {
|
||||
dryRun: false,
|
||||
outPath: 'organized',
|
||||
relocateExternalFiles: true,
|
||||
}));
|
||||
|
||||
const result = await copier.run(makePathToFixture('projects','external','alephwithbeth','alephwithbeth.kpj'));
|
||||
assert.sameMembers(Object.keys(result.artifacts).map(k => result.artifacts[k].filename), [
|
||||
'organized', // kmc-copy:outputPath
|
||||
'organized/source/organized.keyman-touch-layout',
|
||||
'organized/source/organized.kmn',
|
||||
'organized/source/organized.ico',
|
||||
'organized/source/organized.kvks',
|
||||
'organized/source/organized.kps',
|
||||
'organized/source/readme.htm',
|
||||
// files in 'another-folder/' get moved to 'external/'
|
||||
'organized/external/another-folder/welcome/welcome.htm',
|
||||
'organized/external/another-folder/welcome/KeyboardLayout.png',
|
||||
'organized/external/another-folder/welcome/KeyboardLayoutAlt.png',
|
||||
'organized/external/another-folder/welcome/KeyboardLayoutShift.png',
|
||||
// build artifact files get moved to build/
|
||||
'organized/build/organized.js',
|
||||
'organized/build/organized.kvk',
|
||||
'organized/build/organized.kmx',
|
||||
// 'organized/build/organized.kmp', // TODO-COPY: do we need to copy this file as well?
|
||||
'organized/LICENSE.md',
|
||||
'organized/organized.kpj',
|
||||
'organized/HISTORY.md',
|
||||
'organized/README.md',
|
||||
'organized/source/help/organized.php',
|
||||
'organized/source/help/KeyboardLayout.png',
|
||||
'organized/source/help/KeyboardLayoutAlt.png',
|
||||
'organized/source/help/KeyboardLayoutShift.png',
|
||||
]);
|
||||
|
||||
// Verify that .kps has the appropriate paths
|
||||
const reader = new KpsFileReader(callbacks);
|
||||
const kpsFilename = Object.keys(result.artifacts).find(k => result.artifacts[k].filename == 'organized/source/organized.kps')!;
|
||||
const kps = reader.read(result.artifacts[kpsFilename].data);
|
||||
assert.isDefined(kps.Package.Files?.File.find(file => file.Name == '../external/another-folder/welcome/welcome.htm'));
|
||||
assert.isDefined(kps.Package.Files?.File.find(file => file.Name == '../external/another-folder/welcome/KeyboardLayout.png'));
|
||||
assert.isDefined(kps.Package.Files?.File.find(file => file.Name == '../external/another-folder/welcome/KeyboardLayoutAlt.png'));
|
||||
assert.isDefined(kps.Package.Files?.File.find(file => file.Name == '../external/another-folder/welcome/KeyboardLayoutShift.png'));
|
||||
});
|
||||
|
||||
it('should leave external files in their original location when relocateExternalFiles is false', async function() {
|
||||
const copier = new KeymanProjectCopier();
|
||||
assert.isTrue(await copier.init(callbacks, {
|
||||
dryRun: false,
|
||||
outPath: 'organized',
|
||||
relocateExternalFiles: false,
|
||||
}));
|
||||
|
||||
const result = await copier.run(makePathToFixture('projects','external','alephwithbeth','alephwithbeth.kpj'));
|
||||
assert.sameMembers(Object.keys(result.artifacts).map(k => result.artifacts[k].filename), [
|
||||
'organized', // kmc-copy:outputPath
|
||||
'organized/source/organized.keyman-touch-layout',
|
||||
'organized/source/organized.kmn',
|
||||
'organized/source/organized.ico',
|
||||
'organized/source/organized.kvks',
|
||||
'organized/source/organized.kps',
|
||||
'organized/source/readme.htm',
|
||||
|
||||
// files in 'another-folder/' stay there, so they are not referenced
|
||||
// 'organized/external/welcome.htm',
|
||||
// 'organized/external/KeyboardLayout.png',
|
||||
// 'organized/external/KeyboardLayoutAlt.png',
|
||||
// 'organized/external/KeyboardLayoutShift.png',
|
||||
|
||||
// build artifact files get moved to build/
|
||||
'organized/build/organized.js',
|
||||
'organized/build/organized.kvk',
|
||||
'organized/build/organized.kmx',
|
||||
// 'organized/build/organized.kmp', // TODO-COPY: do we need to copy this file as well?
|
||||
'organized/LICENSE.md',
|
||||
'organized/organized.kpj',
|
||||
'organized/HISTORY.md',
|
||||
'organized/README.md',
|
||||
'organized/source/help/organized.php',
|
||||
'organized/source/help/KeyboardLayout.png',
|
||||
'organized/source/help/KeyboardLayoutAlt.png',
|
||||
'organized/source/help/KeyboardLayoutShift.png',
|
||||
]);
|
||||
|
||||
// we'll check the .kps for its references, these are relative to the test/organized/source? folder
|
||||
const reader = new KpsFileReader(callbacks);
|
||||
const kpsFilename = Object.keys(result.artifacts).find(k => result.artifacts[k].filename == 'organized/source/organized.kps')!;
|
||||
const kps = reader.read(result.artifacts[kpsFilename].data);
|
||||
|
||||
assert.isDefined(kps.Package.Files?.File.find(file => file.Name == '../../../test/fixtures/projects/external/another-folder/welcome/welcome.htm'));
|
||||
assert.isDefined(kps.Package.Files?.File.find(file => file.Name == '../../../test/fixtures/projects/external/another-folder/welcome/KeyboardLayout.png'));
|
||||
assert.isDefined(kps.Package.Files?.File.find(file => file.Name == '../../../test/fixtures/projects/external/another-folder/welcome/KeyboardLayoutAlt.png'));
|
||||
assert.isDefined(kps.Package.Files?.File.find(file => file.Name == '../../../test/fixtures/projects/external/another-folder/welcome/KeyboardLayoutShift.png'));
|
||||
});
|
||||
|
||||
// TODO-COPY: additional tests
|
||||
it.skip('should copy a standalone .kmn into a new project', async function() {});
|
||||
it.skip('should copy a standalone .kmn and .kps into a new project', async function() {});
|
||||
|
|
|
|||
35
developer/src/kmc-copy/test/fixtures/projects/external/alephwithbeth/HISTORY.md
vendored
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
alephwithbeth Change History
|
||||
====================
|
||||
|
||||
1.0.6 (2024-06-11)
|
||||
------------------
|
||||
* Remove source files from package
|
||||
|
||||
1.0.5 (2023-02-28)
|
||||
------------------
|
||||
* replaced hyphen with maqef
|
||||
* added a touch-optimized keyboard layout for phone
|
||||
|
||||
1.0.4 (2023-02-13)
|
||||
------------------
|
||||
* Removed unnecessary version numbers.
|
||||
* added description
|
||||
|
||||
1.0.3 (2023-02-11)
|
||||
------------------
|
||||
* Removed the faulty auto correct feature.
|
||||
* Captialized all words of the title.
|
||||
* Added title to .kmn
|
||||
|
||||
1.0.2 (2023-02-09)
|
||||
------------------
|
||||
* Renamed keyboard to "Aleph with Beth"
|
||||
|
||||
1.0.1 (2023-02-08)
|
||||
----------------
|
||||
* Updated author and website (in kps)
|
||||
* Added copyrights where needed.
|
||||
|
||||
1.0 (2023-01-28)
|
||||
----------------
|
||||
* Created by Cameron Briggs
|
||||
21
developer/src/kmc-copy/test/fixtures/projects/external/alephwithbeth/LICENSE.md
vendored
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright © 2023-2024 Cameron Briggs
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
25
developer/src/kmc-copy/test/fixtures/projects/external/alephwithbeth/README.md
vendored
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
alephwithbeth keyboard
|
||||
==============
|
||||
|
||||
Description
|
||||
-----------
|
||||
A Hebrew keyboard designed to intuitively match the standard QWERTY layout.
|
||||
|
||||
Copyright
|
||||
---------
|
||||
See [LICENSE.md](LICENSE.md)
|
||||
|
||||
Supported Platforms
|
||||
-------------------
|
||||
* Windows
|
||||
* macOS
|
||||
* Linux
|
||||
* Web
|
||||
* iPhone
|
||||
* iPad
|
||||
* Android phone
|
||||
* Android tablet
|
||||
* Mobile devices
|
||||
* Desktop devices
|
||||
* Tablet devices
|
||||
|
||||
9
developer/src/kmc-copy/test/fixtures/projects/external/alephwithbeth/alephwithbeth.kpj
vendored
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<KeymanDeveloperProject>
|
||||
<Options>
|
||||
<Version>2.0</Version>
|
||||
<BuildPath>$PROJECTPATH\build</BuildPath>
|
||||
<CompilerWarningsAsErrors>True</CompilerWarningsAsErrors>
|
||||
<CheckFilenameConventions>True</CheckFilenameConventions>
|
||||
</Options>
|
||||
</KeymanDeveloperProject>
|
||||
1
developer/src/kmc-copy/test/fixtures/projects/external/alephwithbeth/build/alephwithbeth.js
vendored
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
{
|
||||
"id": "alephwithbeth",
|
||||
"name": "Aleph With Beth",
|
||||
"license": "mit",
|
||||
"isRTL": true,
|
||||
"authorName": "Cameron Briggs",
|
||||
"description": "<p>alephwithbeth keyboard</p>",
|
||||
"languages": {
|
||||
"he": {
|
||||
"examples": [],
|
||||
"languageName": "Hebrew",
|
||||
"displayName": "Hebrew"
|
||||
}
|
||||
},
|
||||
"lastModifiedDate": "2025-01-27T23:04:56.765Z",
|
||||
"packageFilename": "alephwithbeth.kmp",
|
||||
"packageFileSize": 244476,
|
||||
"jsFilename": "alephwithbeth.js",
|
||||
"jsFileSize": 23534,
|
||||
"packageIncludes": [
|
||||
"documentation",
|
||||
"welcome",
|
||||
"visualKeyboard"
|
||||
],
|
||||
"version": "1.0.6",
|
||||
"encodings": [
|
||||
"unicode"
|
||||
],
|
||||
"platformSupport": {
|
||||
"windows": "full",
|
||||
"macos": "full",
|
||||
"linux": "full",
|
||||
"desktopWeb": "full",
|
||||
"ios": "full",
|
||||
"android": "full",
|
||||
"mobileWeb": "full"
|
||||
},
|
||||
"minKeymanVersion": "14.0",
|
||||
"helpLink": "https://help.keyman.com/keyboard/alephwithbeth"
|
||||
}
|
||||
BIN
developer/src/kmc-copy/test/fixtures/projects/external/alephwithbeth/build/alephwithbeth.kmp
vendored
Normal file
BIN
developer/src/kmc-copy/test/fixtures/projects/external/alephwithbeth/build/alephwithbeth.kmx
vendored
Normal file
BIN
developer/src/kmc-copy/test/fixtures/projects/external/alephwithbeth/build/alephwithbeth.kvk
vendored
Normal file
BIN
developer/src/kmc-copy/test/fixtures/projects/external/alephwithbeth/source/alephwithbeth.ico
vendored
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
215
developer/src/kmc-copy/test/fixtures/projects/external/alephwithbeth/source/alephwithbeth.kmn
vendored
Normal file
|
|
@ -0,0 +1,215 @@
|
|||
store(&TARGETS) 'any'
|
||||
store(&NAME) 'Aleph With Beth'
|
||||
store(&BITMAP) 'alephwithbeth.ico'
|
||||
store(&VISUALKEYBOARD) 'alephwithbeth.kvks'
|
||||
|
||||
store(letters-with-final-forms) "כמנפצ"
|
||||
store(sofit-forms-of-letters) "ךםןףץ"
|
||||
store(presentation-dageshed-letters-with-final-forms) "כּפּ"
|
||||
store(presentation-dageshed-sofit-forms-of-letters) "ךּףּ"
|
||||
store(dagesh) 'ּ'
|
||||
c store(vowels) "ְֱֲֳִֵֶַׇׇָֹֻׅ"
|
||||
|
||||
store(normal-dageshed-letters-with-final-forms) "מּנּצּ"
|
||||
store(normal-undageshed-sofit-forms-of-letters) "םןץ"
|
||||
|
||||
store(punctuation) U+0591 .. U+05AF U+05BD .. U+05BF U+05C0 U+05C4
|
||||
store(whitespace) [K_SPACE] [K_ENTER] [K_TAB]
|
||||
|
||||
store(&KMW_RTL) '1'
|
||||
store(&LAYOUTFILE) 'alephwithbeth.keyman-touch-layout'
|
||||
store(©RIGHT) '© Cameron Briggs'
|
||||
store(&KEYBOARDVERSION) '1.0.6'
|
||||
store(&KMW_HELPTEXT) 'Aleph With Beth'
|
||||
|
||||
begin Unicode > use(main)
|
||||
|
||||
group(main) using keys
|
||||
+ [SHIFT K_I] > nul
|
||||
+ [ALT K_BKQUOTE] > nul
|
||||
+ [ALT K_B] > nul
|
||||
+ [ALT K_V] > nul
|
||||
+ [ALT K_C] > nul
|
||||
+ [ALT K_Z] > nul
|
||||
+ [ALT K_L] > nul
|
||||
+ [ALT K_J] > nul
|
||||
+ [ALT K_F] > nul
|
||||
+ [ALT K_D] > nul
|
||||
+ [ALT K_S] > nul
|
||||
+ [ALT K_U] > nul
|
||||
+ [ALT K_Y] > nul
|
||||
+ [ALT K_T] > nul
|
||||
+ [ALT K_R] > nul
|
||||
+ [ALT K_W] > nul
|
||||
+ [ALT K_Q] > nul
|
||||
+ [SHIFT K_BKSLASH] > '|'
|
||||
+ [SHIFT K_EQUAL] > '+'
|
||||
+ [SHIFT K_HYPHEN] > '_'
|
||||
+ [SHIFT K_0] > ')'
|
||||
+ [SHIFT K_9] > '('
|
||||
+ [SHIFT K_SLASH] > '?'
|
||||
+ [SHIFT K_QUOTE] > '"'
|
||||
+ [SHIFT K_BKQUOTE] > nul
|
||||
+ [K_EQUAL] > '='
|
||||
+ [K_HYPHEN] > '־'
|
||||
+ [K_0] > '0'
|
||||
+ [K_9] > '9'
|
||||
+ [K_8] > '8'
|
||||
+ [K_7] > '7'
|
||||
+ [K_6] > '6'
|
||||
+ [K_5] > '5'
|
||||
+ [K_4] > '4'
|
||||
+ [K_3] > '3'
|
||||
+ [K_2] > '2'
|
||||
+ [K_1] > '1'
|
||||
+ [K_PERIOD] > '.'
|
||||
+ [K_SLASH] > '/'
|
||||
+ [K_QUOTE] > U+0027
|
||||
+ [SHIFT K_COLON] > '״'
|
||||
+ [ALT K_A] > 'ֲ'
|
||||
+ [SHIFT K_RBRKT] > '}'
|
||||
+ [SHIFT K_LBRKT] > '{'
|
||||
+ [K_BKSLASH] > '\'
|
||||
+ [K_RBRKT] > ']'
|
||||
+ [K_LBRKT] > '['
|
||||
+ [SHIFT K_R] > 'רּ'
|
||||
+ [SHIFT CTRL K_SPACE] > ' '
|
||||
+ [SHIFT K_SPACE] > ' '
|
||||
+ [K_SPACE] > ' '
|
||||
+ [ALT K_SPACE] > ' '
|
||||
+ [SHIFT K_8] > '֝'
|
||||
+ [SHIFT K_7] > '֬'
|
||||
+ [SHIFT K_6] > '֔'
|
||||
+ [SHIFT K_5] > '֞'
|
||||
+ [SHIFT K_4] > '֜'
|
||||
+ [SHIFT K_3] > '֨'
|
||||
+ [SHIFT K_2] > '֘'
|
||||
+ [SHIFT K_1] > '!'
|
||||
+ [ALT K_SLASH] > '״'
|
||||
+ [ALT K_PERIOD] > '̈'
|
||||
+ [ALT K_COMMA] > '֫'
|
||||
+ [ALT K_QUOTE] > 'ׄ'
|
||||
+ [ALT K_COLON] > '׃'
|
||||
+ [ALT K_H] > '̊'
|
||||
+ [ALT K_G] > '•'
|
||||
+ [ALT K_BKSLASH] > '֫'
|
||||
+ [ALT K_RBRKT] > '֒'
|
||||
+ [ALT K_LBRKT] > '֔'
|
||||
+ [ALT K_I] > 'ֽ'
|
||||
+ [ALT K_O] > 'ֳ'
|
||||
+ [ALT K_E] > 'ֱ'
|
||||
+ [ALT K_EQUAL] > '◌'
|
||||
+ [ALT K_HYPHEN] > 'ֿ'
|
||||
+ [ALT K_0] > '֯'
|
||||
+ [ALT K_9] > '֓'
|
||||
+ [ALT K_8] > '֕'
|
||||
+ [ALT K_7] > '֡'
|
||||
+ [ALT K_6] > '֟'
|
||||
+ [ALT K_5] > '֩'
|
||||
+ [ALT K_4] > '֠'
|
||||
+ [ALT K_3] > '֙'
|
||||
+ [ALT K_2] > '֮'
|
||||
+ [ALT K_1] > '֗'
|
||||
+ [ALT K_N] > 'ן'
|
||||
+ [ALT K_P] > 'ף'
|
||||
+ [ALT K_K] > 'ך'
|
||||
+ [ALT K_M] > 'ם'
|
||||
+ [ALT K_X] > 'ץ'
|
||||
+ [SHIFT K_PERIOD] > 'ּ'
|
||||
+ [SHIFT K_COMMA] > nul
|
||||
+ [SHIFT K_M] > 'מּ'
|
||||
+ [SHIFT K_N] > 'נּ'
|
||||
+ [SHIFT K_B] > 'בּ'
|
||||
+ [SHIFT K_V] > 'שּׁ'
|
||||
+ [SHIFT K_C] > 'שּׂ'
|
||||
+ [SHIFT K_X] > 'צּ'
|
||||
+ [SHIFT K_Z] > 'זּ'
|
||||
+ [SHIFT K_L] > 'לּ'
|
||||
+ [SHIFT K_K] > 'כּ'
|
||||
+ [SHIFT K_J] > 'וַיּ'
|
||||
+ [SHIFT K_H] > 'הּ'
|
||||
+ [SHIFT K_G] > 'גּ'
|
||||
+ [SHIFT K_F] > 'טּ'
|
||||
+ [SHIFT K_D] > 'דּ'
|
||||
+ [SHIFT K_S] > 'סּ'
|
||||
+ [SHIFT K_A] > 'ָ'
|
||||
+ [SHIFT K_P] > 'פּ'
|
||||
+ [SHIFT K_O] > 'וֹ'
|
||||
+ [SHIFT K_U] > 'ֻ'
|
||||
+ [SHIFT K_Y] > 'יּ'
|
||||
+ [SHIFT K_T] > 'תּ'
|
||||
+ [SHIFT K_E] > 'ֵ'
|
||||
+ [SHIFT K_W] > 'וּ'
|
||||
+ [SHIFT K_Q] > 'קּ'
|
||||
+ [K_BKQUOTE] > '֑'
|
||||
+ [K_COMMA] > 'א'
|
||||
+ [K_M] > 'מ'
|
||||
+ [K_N] > 'נ'
|
||||
+ [K_B] > 'ב'
|
||||
+ [K_V] > 'שׁ'
|
||||
+ [K_C] > 'שׂ'
|
||||
+ [K_X] > 'צ'
|
||||
+ [K_Z] > 'ז'
|
||||
+ [K_COLON] > 'ְ'
|
||||
+ [K_L] > 'ל'
|
||||
+ [K_K] > 'כ'
|
||||
+ [K_J] > 'ח'
|
||||
+ [K_H] > 'ה'
|
||||
+ [K_G] > 'ג'
|
||||
+ [K_F] > 'ט'
|
||||
+ [K_D] > 'ד'
|
||||
+ [K_S] > 'ס'
|
||||
+ [K_A] > 'ַ'
|
||||
+ [K_P] > 'פ'
|
||||
+ [K_O] > 'ֹ'
|
||||
+ [K_I] > 'ִ'
|
||||
+ [K_U] > 'ע'
|
||||
+ [K_Y] > 'י'
|
||||
+ [K_T] > 'ת'
|
||||
+ [K_R] > 'ר'
|
||||
+ [K_E] > 'ֶ'
|
||||
+ [K_W] > 'ו'
|
||||
+ [K_Q] > 'ק'
|
||||
c Transform final letters
|
||||
any(letters-with-final-forms) + any(whitespace) > index(sofit-forms-of-letters,1)
|
||||
|
||||
c Transform final letters with a dagesh
|
||||
any(letters-with-final-forms) $dagesh + any(whitespace) > index(sofit-forms-of-letters,1) $dagesh
|
||||
any(presentation-dageshed-letters-with-final-forms) + any(whitespace) > index(presentation-dageshed-sofit-forms-of-letters,1)
|
||||
any(normal-dageshed-letters-with-final-forms) + any(whitespace) > index(normal-undageshed-sofit-forms-of-letters,1) $dagesh
|
||||
|
||||
c Transform final letters with a vowel
|
||||
c any(letters-with-final-forms) any(vowels) + any(whitespace) > index(sofit-forms-of-letters,1) index(vowels,2)
|
||||
|
||||
c Transform final letters with a vowel and a dagesh
|
||||
c any(letters-with-final-forms) any(vowels) $dagesh + any(whitespace) > index(sofit-forms-of-letters,1) index(vowels,2) $dagesh
|
||||
c any(letters-with-final-forms) $dagesh any(vowels) + any(whitespace) > index(sofit-forms-of-letters,1) $dagesh index(vowels,3)
|
||||
c any(presentation-dageshed-letters-with-final-forms) any(vowels) + any(whitespace) > index(presentation-dageshed-sofit-forms-of-letters,1) index(vowels,2)
|
||||
c any(normal-dageshed-letters-with-final-forms) any(vowels) + any(whitespace) > index(normal-undageshed-sofit-forms-of-letters,1) $dagesh index(vowels,2)
|
||||
|
||||
c Transform final letters with punctuation
|
||||
any(letters-with-final-forms) any(punctuation) + any(whitespace) > index(sofit-forms-of-letters,1) index(punctuation,2)
|
||||
|
||||
c Transform final letters with punctuation and a dagesh
|
||||
any(letters-with-final-forms) any(punctuation) $dagesh + any(whitespace) > index(sofit-forms-of-letters,1) index(punctuation,2) $dagesh
|
||||
any(letters-with-final-forms) $dagesh any(punctuation) + any(whitespace) > index(sofit-forms-of-letters,1) $dagesh index(punctuation,3)
|
||||
any(presentation-dageshed-letters-with-final-forms) any(punctuation) + any(whitespace) > index(presentation-dageshed-sofit-forms-of-letters,1) index(punctuation,2)
|
||||
any(normal-dageshed-letters-with-final-forms) any(punctuation) + any(whitespace) > index(normal-undageshed-sofit-forms-of-letters,1) $dagesh index(punctuation,2)
|
||||
|
||||
c Transfrom final letters with a punctuation and a vowel
|
||||
c any(letters-with-final-forms) any(punctuation) any(vowels) + any(whitespace) > index(sofit-forms-of-letters,1) index(punctuation,2) index(vowels,3)
|
||||
c any(letters-with-final-forms) any(vowels) any(punctuation) + any(whitespace) > index(sofit-forms-of-letters,1) index(vowels,2) index(punctuation,3)
|
||||
|
||||
c Transform final letters with punctuation, a vowel, and a dagesh (phew!)
|
||||
c any(letters-with-final-forms) any(punctuation) any(vowels) $dagesh + any(whitespace) > index(sofit-forms-of-letters,1) index(punctuation,2) index(vowels,3) $dagesh
|
||||
c any(letters-with-final-forms) any(punctuation) $dagesh any(vowels) + any(whitespace) > index(sofit-forms-of-letters,1) index(punctuation,2) $dagesh index(vowels,4)
|
||||
c any(letters-with-final-forms) any(vowels) any(punctuation) $dagesh + any(whitespace) > index(sofit-forms-of-letters,1) index(vowels,2) index(punctuation,3) $dagesh
|
||||
c any(letters-with-final-forms) any(vowels) $dagesh any(punctuation) + any(whitespace) > index(sofit-forms-of-letters,1) index(vowels,2) $dagesh index(punctuation,4)
|
||||
c any(letters-with-final-forms) $dagesh any(punctuation) any(vowels) + any(whitespace) > index(sofit-forms-of-letters,1) $dagesh index(punctuation,3) index(vowels,4)
|
||||
c any(letters-with-final-forms) $dagesh any(vowels) any(punctuation) + any(whitespace) > index(sofit-forms-of-letters,1) $dagesh index(vowels,3) index(punctuation,4)
|
||||
|
||||
|
||||
c any(presentation-dageshed-letters-with-final-forms) any(punctuation) any(vowels) + any(whitespace) > index(presentation-dageshed-sofit-forms-of-letters,1) index(punctuation,2) index(vowels,3)
|
||||
c any(presentation-dageshed-letters-with-final-forms) any(vowels) any(punctuation) + any(whitespace) > index(presentation-dageshed-sofit-forms-of-letters,1) index(vowels,2) index(punctuation,3)
|
||||
c any(normal-dageshed-letters-with-final-forms) any(punctuation) any(vowels) + any(whitespace) > index(normal-undageshed-sofit-forms-of-letters,1) $dagesh index(punctuation,2) index(vowels,3)
|
||||
c any(normal-dageshed-letters-with-final-forms) any(vowels) any(punctuation) + any(whitespace) > index(normal-undageshed-sofit-forms-of-letters,1) $dagesh index(vowels,2) index(punctuation,3)
|
||||
95
developer/src/kmc-copy/test/fixtures/projects/external/alephwithbeth/source/alephwithbeth.kps
vendored
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Package>
|
||||
<System>
|
||||
<KeymanDeveloperVersion>17.0.325.0</KeymanDeveloperVersion>
|
||||
<FileVersion>7.0</FileVersion>
|
||||
</System>
|
||||
<Options>
|
||||
<ExecuteProgram></ExecuteProgram>
|
||||
<ReadMeFile>readme.htm</ReadMeFile>
|
||||
<LicenseFile>..\LICENSE.md</LicenseFile>
|
||||
<WelcomeFile>..\..\another-folder\welcome\welcome.htm</WelcomeFile>
|
||||
<MSIFileName></MSIFileName>
|
||||
<MSIOptions></MSIOptions>
|
||||
<FollowKeyboardVersion/>
|
||||
</Options>
|
||||
<StartMenu>
|
||||
<Folder></Folder>
|
||||
<Items/>
|
||||
</StartMenu>
|
||||
<Info>
|
||||
<Version URL=""></Version>
|
||||
<Name URL="">Aleph With Beth</Name>
|
||||
<Copyright URL="">© Cameron Briggs</Copyright>
|
||||
<Author URL="">Cameron Briggs</Author>
|
||||
<WebSite URL="https://freehebrew.online">https://freehebrew.online</WebSite>
|
||||
<Description URL="">alephwithbeth keyboard</Description>
|
||||
</Info>
|
||||
<Files>
|
||||
<File>
|
||||
<Name>readme.htm</Name>
|
||||
<Description>File readme.htm</Description>
|
||||
<CopyLocation>0</CopyLocation>
|
||||
<FileType>.htm</FileType>
|
||||
</File>
|
||||
<File>
|
||||
<Name>..\..\another-folder\welcome\welcome.htm</Name>
|
||||
<Description>File welcome.htm</Description>
|
||||
<CopyLocation>0</CopyLocation>
|
||||
<FileType>.htm</FileType>
|
||||
</File>
|
||||
<File>
|
||||
<Name>..\build\alephwithbeth.js</Name>
|
||||
<Description>File alephwithbeth.js</Description>
|
||||
<CopyLocation>0</CopyLocation>
|
||||
<FileType>.js</FileType>
|
||||
</File>
|
||||
<File>
|
||||
<Name>..\build\alephwithbeth.kvk</Name>
|
||||
<Description>File alephwithbeth.kvk</Description>
|
||||
<CopyLocation>0</CopyLocation>
|
||||
<FileType>.kvk</FileType>
|
||||
</File>
|
||||
<File>
|
||||
<Name>..\build\alephwithbeth.kmx</Name>
|
||||
<Description>Keyboard alephwithbeth</Description>
|
||||
<CopyLocation>0</CopyLocation>
|
||||
<FileType>.kmx</FileType>
|
||||
</File>
|
||||
<File>
|
||||
<Name>..\..\another-folder\welcome\KeyboardLayout.png</Name>
|
||||
<Description>File KeyboardLayout.png</Description>
|
||||
<CopyLocation>0</CopyLocation>
|
||||
<FileType>.png</FileType>
|
||||
</File>
|
||||
<File>
|
||||
<Name>..\..\another-folder\welcome\KeyboardLayoutAlt.png</Name>
|
||||
<Description>File KeyboardLayoutAlt.png</Description>
|
||||
<CopyLocation>0</CopyLocation>
|
||||
<FileType>.png</FileType>
|
||||
</File>
|
||||
<File>
|
||||
<Name>..\..\another-folder\welcome\KeyboardLayoutShift.png</Name>
|
||||
<Description>File KeyboardLayoutShift.png</Description>
|
||||
<CopyLocation>0</CopyLocation>
|
||||
<FileType>.png</FileType>
|
||||
</File>
|
||||
<File>
|
||||
<Name>..\LICENSE.md</Name>
|
||||
<Description></Description>
|
||||
<CopyLocation>0</CopyLocation>
|
||||
<FileType>.md</FileType>
|
||||
</File>
|
||||
</Files>
|
||||
<Keyboards>
|
||||
<Keyboard>
|
||||
<Name>Aleph With Beth</Name>
|
||||
<ID>alephwithbeth</ID>
|
||||
<Version>1.0.4</Version>
|
||||
<Languages>
|
||||
<Language ID="he">Hebrew</Language>
|
||||
</Languages>
|
||||
</Keyboard>
|
||||
</Keyboards>
|
||||
<Strings/>
|
||||
</Package>
|
||||
138
developer/src/kmc-copy/test/fixtures/projects/external/alephwithbeth/source/alephwithbeth.kvks
vendored
Normal file
|
|
@ -0,0 +1,138 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<visualkeyboard>
|
||||
<header>
|
||||
<version>10.0</version>
|
||||
<kbdname>alephwithbeth</kbdname>
|
||||
<flags/>
|
||||
</header>
|
||||
<encoding name="unicode" fontname="Arial" fontsize="-12">
|
||||
<layer shift="S">
|
||||
<key vkey="K_1">!</key>
|
||||
<key vkey="K_QUOTE">"</key>
|
||||
<key vkey="K_3">֨</key>
|
||||
<key vkey="K_4">֜</key>
|
||||
<key vkey="K_5">֞</key>
|
||||
<key vkey="K_7">֬</key>
|
||||
<key vkey="K_9">(</key>
|
||||
<key vkey="K_0">)</key>
|
||||
<key vkey="K_8">֝</key>
|
||||
<key vkey="K_EQUAL">+</key>
|
||||
<key vkey="K_COLON">״</key>
|
||||
<key vkey="K_PERIOD">ּ</key>
|
||||
<key vkey="K_SLASH">?</key>
|
||||
<key vkey="K_2">֘</key>
|
||||
<key vkey="K_A">ָ</key>
|
||||
<key vkey="K_B">בּ</key>
|
||||
<key vkey="K_C">שּׂ</key>
|
||||
<key vkey="K_D">דּ</key>
|
||||
<key vkey="K_E">ֵ</key>
|
||||
<key vkey="K_F">טּ</key>
|
||||
<key vkey="K_G">גּ</key>
|
||||
<key vkey="K_H">הּ</key>
|
||||
<key vkey="K_J">וַיּ</key>
|
||||
<key vkey="K_K">כּ</key>
|
||||
<key vkey="K_L">לּ</key>
|
||||
<key vkey="K_M">מּ</key>
|
||||
<key vkey="K_N">נּ</key>
|
||||
<key vkey="K_O">וֹ</key>
|
||||
<key vkey="K_P">פּ</key>
|
||||
<key vkey="K_Q">קּ</key>
|
||||
<key vkey="K_R">רּ</key>
|
||||
<key vkey="K_S">סּ</key>
|
||||
<key vkey="K_T">תּ</key>
|
||||
<key vkey="K_U">ֻ</key>
|
||||
<key vkey="K_V">שּׁ</key>
|
||||
<key vkey="K_W">וּ</key>
|
||||
<key vkey="K_X">צּ</key>
|
||||
<key vkey="K_Y">יּ</key>
|
||||
<key vkey="K_Z">זּ</key>
|
||||
<key vkey="K_6">֔</key>
|
||||
<key vkey="K_HYPHEN">_</key>
|
||||
<key vkey="K_LBRKT">{</key>
|
||||
<key vkey="K_BKSLASH">|</key>
|
||||
<key vkey="K_RBRKT">}</key>
|
||||
</layer>
|
||||
<layer shift="">
|
||||
<key vkey="K_QUOTE">'</key>
|
||||
<key vkey="K_COMMA">א</key>
|
||||
<key vkey="K_PERIOD">.</key>
|
||||
<key vkey="K_SLASH">/</key>
|
||||
<key vkey="K_1">1</key>
|
||||
<key vkey="K_2">2</key>
|
||||
<key vkey="K_3">3</key>
|
||||
<key vkey="K_4">4</key>
|
||||
<key vkey="K_5">5</key>
|
||||
<key vkey="K_6">6</key>
|
||||
<key vkey="K_7">7</key>
|
||||
<key vkey="K_8">8</key>
|
||||
<key vkey="K_9">9</key>
|
||||
<key vkey="K_COLON">ְ</key>
|
||||
<key vkey="K_EQUAL">=</key>
|
||||
<key vkey="K_LBRKT">[</key>
|
||||
<key vkey="K_BKSLASH">\</key>
|
||||
<key vkey="K_RBRKT">]</key>
|
||||
<key vkey="K_BKQUOTE">֑</key>
|
||||
<key vkey="K_A">ַ</key>
|
||||
<key vkey="K_B">ב</key>
|
||||
<key vkey="K_C">שׂ</key>
|
||||
<key vkey="K_D">ד</key>
|
||||
<key vkey="K_E">ֶ</key>
|
||||
<key vkey="K_F">ט</key>
|
||||
<key vkey="K_G">ג</key>
|
||||
<key vkey="K_H">ה</key>
|
||||
<key vkey="K_I">ִ</key>
|
||||
<key vkey="K_J">ח</key>
|
||||
<key vkey="K_K">כ</key>
|
||||
<key vkey="K_L">ל</key>
|
||||
<key vkey="K_M">מ</key>
|
||||
<key vkey="K_N">נ</key>
|
||||
<key vkey="K_O">ֹ</key>
|
||||
<key vkey="K_P">פ</key>
|
||||
<key vkey="K_Q">ק</key>
|
||||
<key vkey="K_R">ר</key>
|
||||
<key vkey="K_S">ס</key>
|
||||
<key vkey="K_T">ת</key>
|
||||
<key vkey="K_U">ע</key>
|
||||
<key vkey="K_V">שׁ</key>
|
||||
<key vkey="K_W">ו</key>
|
||||
<key vkey="K_X">צ</key>
|
||||
<key vkey="K_Y">י</key>
|
||||
<key vkey="K_Z">ז</key>
|
||||
<key vkey="K_HYPHEN">־</key>
|
||||
<key vkey="K_0">0</key>
|
||||
</layer>
|
||||
<layer shift="A">
|
||||
<key vkey="K_QUOTE">ׄ</key>
|
||||
<key vkey="K_COMMA">֫</key>
|
||||
<key vkey="K_HYPHEN">ֿ</key>
|
||||
<key vkey="K_PERIOD">̈</key>
|
||||
<key vkey="K_SLASH">״</key>
|
||||
<key vkey="K_0">֯</key>
|
||||
<key vkey="K_1">֗</key>
|
||||
<key vkey="K_2">֮</key>
|
||||
<key vkey="K_3">֙</key>
|
||||
<key vkey="K_4">֠</key>
|
||||
<key vkey="K_5">֩</key>
|
||||
<key vkey="K_6">֟</key>
|
||||
<key vkey="K_7">֡</key>
|
||||
<key vkey="K_8">֕</key>
|
||||
<key vkey="K_9">֓</key>
|
||||
<key vkey="K_COLON">׃</key>
|
||||
<key vkey="K_EQUAL">◌</key>
|
||||
<key vkey="K_LBRKT">֔</key>
|
||||
<key vkey="K_BKSLASH">֫</key>
|
||||
<key vkey="K_RBRKT">֒</key>
|
||||
<key vkey="K_A">ֲ</key>
|
||||
<key vkey="K_E">ֱ</key>
|
||||
<key vkey="K_G">•</key>
|
||||
<key vkey="K_H">̊</key>
|
||||
<key vkey="K_I">ֽ</key>
|
||||
<key vkey="K_K">ך</key>
|
||||
<key vkey="K_M">ם</key>
|
||||
<key vkey="K_N">ן</key>
|
||||
<key vkey="K_O">ֳ</key>
|
||||
<key vkey="K_P">ף</key>
|
||||
<key vkey="K_X">ץ</key>
|
||||
</layer>
|
||||
</encoding>
|
||||
</visualkeyboard>
|
||||
BIN
developer/src/kmc-copy/test/fixtures/projects/external/alephwithbeth/source/help/KeyboardLayout.png
vendored
Normal file
|
After Width: | Height: | Size: 95 KiB |
|
After Width: | Height: | Size: 60 KiB |
|
After Width: | Height: | Size: 83 KiB |
|
|
@ -0,0 +1,22 @@
|
|||
<?php
|
||||
$pagename = 'Aleph with Beth Keyboard Help';
|
||||
$pagetitle = $pagename;
|
||||
$pagestyle = <<<END
|
||||
.center { display: block; margin-left: auto; margin-right: auto; width: 75%; }
|
||||
END;
|
||||
|
||||
require_once('header.php');
|
||||
?>
|
||||
<body>
|
||||
|
||||
<h1>Start Using Aleph with Beth</h1>
|
||||
|
||||
<h1>Desktop Layout</h1>
|
||||
|
||||
<h2>Base layout</h2>
|
||||
<img src="KeyboardLayout.png" alt="Keyboard layout" class="center">
|
||||
<h2>Layout when shift is pressed</h2>
|
||||
<img src="KeyboardLayoutShift.png" alt="Keyboard layout (when shift key is pressed)" class="center">
|
||||
<h2>Layout when alt is pressed</h2>
|
||||
<img src="KeyboardLayoutAlt.png" alt="Keyboard layout (when alt key is pressed)" class="center">
|
||||
|
||||
22
developer/src/kmc-copy/test/fixtures/projects/external/alephwithbeth/source/readme.htm
vendored
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>alephwithbeth</title>
|
||||
<style type="text/css">
|
||||
p { font: 10pt Tahoma; }
|
||||
h1 { font: bold 16pt Tahoma; color: #4444cc; margin-bottom: 2px }
|
||||
h2 { font: bold 12pt Tahoma; color: #4444cc; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h1>Aleph With Beth</h1>
|
||||
|
||||
<p>A Hebrew keyboard designed to intuitively match the standard QWERTY layout.</p>
|
||||
|
||||
<p>© Cameron Briggs</p>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
BIN
developer/src/kmc-copy/test/fixtures/projects/external/another-folder/welcome/KeyboardLayout.png
vendored
Normal file
|
After Width: | Height: | Size: 95 KiB |
BIN
developer/src/kmc-copy/test/fixtures/projects/external/another-folder/welcome/KeyboardLayoutAlt.png
vendored
Normal file
|
After Width: | Height: | Size: 60 KiB |
|
After Width: | Height: | Size: 83 KiB |
28
developer/src/kmc-copy/test/fixtures/projects/external/another-folder/welcome/welcome.htm
vendored
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Start Using alephwithbeth</title>
|
||||
<style type="text/css">
|
||||
p { font: 10pt Tahoma; }
|
||||
h1 { font: bold 16pt Tahoma; color: #4444cc; margin-bottom: 2px }
|
||||
h2 { font: bold 12pt Tahoma; color: #4444cc; }
|
||||
.center { display: block; margin-left: auto; margin-right: auto; width: 75%; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h1>Start Using Aleph With Beth</h1>
|
||||
|
||||
<h1>Keyboard Layouts</h1>
|
||||
|
||||
<h2>Base layout</h2>
|
||||
<img src="KeyboardLayout.png" alt="Keyboard layout" class="center">
|
||||
<h2>Layout when shift is pressed</h2>
|
||||
<img src="KeyboardLayoutShift.png" alt="Keyboard layout (when shift key is pressed)" class="center">
|
||||
<h2>Layout when alt is pressed</h2>
|
||||
<img src="KeyboardLayoutAlt.png" alt="Keyboard layout (when alt key is pressed)" class="center">
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -13,6 +13,7 @@ THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")"
|
|||
|
||||
builder_describe "Build Keyman kmc-generate module" \
|
||||
"@/common/web/keyman-version" \
|
||||
"@/common/web/langtags" \
|
||||
"@/common/web/types" \
|
||||
"@/developer/src/common/web/test-helpers" \
|
||||
"@/developer/src/common/web/utils" \
|
||||
|
|
|
|||
|
|
@ -27,7 +27,8 @@
|
|||
"dependencies": {
|
||||
"@keymanapp/common-types": "*",
|
||||
"@keymanapp/developer-utils": "*",
|
||||
"@keymanapp/keyman-version": "*"
|
||||
"@keymanapp/keyman-version": "*",
|
||||
"@keymanapp/langtags": "*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@keymanapp/developer-test-helpers": "*",
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
* Base interfaces and classes for generating Keyman Developer source files
|
||||
*/
|
||||
|
||||
import { CompilerCallbacks, CompilerLogLevel, KeymanCompilerArtifact, KeymanCompilerArtifacts, KeymanCompilerResult } from "@keymanapp/developer-utils";
|
||||
import { CompilerBaseOptions, CompilerCallbacks, KeymanCompilerArtifact, KeymanCompilerArtifacts, KeymanCompilerResult } from "@keymanapp/developer-utils";
|
||||
import { GeneratorMessages } from './generator-messages.js';
|
||||
import { KeymanTargets } from "@keymanapp/common-types";
|
||||
|
||||
|
|
@ -13,12 +13,7 @@ import { KeymanTargets } from "@keymanapp/common-types";
|
|||
* @public
|
||||
* Options for the Keyman Developer project generator
|
||||
*/
|
||||
export interface GeneratorOptions /* not inheriting from CompilerBaseOptions */ {
|
||||
/**
|
||||
* Reporting level to console, used by NodeCompilerCallbacks (not used in
|
||||
* compiler modules; all messages are still reported to the internal log)
|
||||
*/
|
||||
logLevel?: CompilerLogLevel;
|
||||
export interface GeneratorOptions extends CompilerBaseOptions {
|
||||
/**
|
||||
* identifier (basename) of the keyboard or model
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
import { KeymanTargets } from "@keymanapp/common-types";
|
||||
import KEYMAN_VERSION from "@keymanapp/keyman-version";
|
||||
import { getLangtagByTag } from "@keymanapp/langtags";
|
||||
import { AbstractGenerator, GeneratorArtifacts } from "./abstract-generator.js";
|
||||
import { GeneratorMessages } from "./generator-messages.js";
|
||||
|
||||
|
|
@ -26,13 +27,13 @@ export class BasicGenerator extends AbstractGenerator {
|
|||
protected preGenerate() {
|
||||
const dt = new Date();
|
||||
|
||||
this.languageTags = this.options.languageTags.length
|
||||
this.languageTags = this.options.languageTags?.length
|
||||
? this.options.languageTags.map(tag => new Intl.Locale(tag).minimize().toString())
|
||||
: [this.DEFAULT_LOCALE];
|
||||
|
||||
// Verify that targets passed in are valid
|
||||
let failed = false;
|
||||
for(const target of this.options.targets) {
|
||||
for(const target of this.options.targets ?? []) {
|
||||
if(!KeymanTargets.AllKeymanTargets.includes(target)) {
|
||||
this.callbacks.reportMessage(GeneratorMessages.Error_InvalidTarget({target}));
|
||||
failed = true;
|
||||
|
|
@ -42,7 +43,7 @@ export class BasicGenerator extends AbstractGenerator {
|
|||
return false;
|
||||
}
|
||||
|
||||
if(this.options.targets.includes(KeymanTargets.KeymanTarget.any) || this.options.targets.length == 0) {
|
||||
if(this.options.targets?.includes(KeymanTargets.KeymanTarget.any) || !this.options.targets?.length) {
|
||||
this.resolvedTargets = KeymanTargets.AllKeymanTargets.filter(target => target != KeymanTargets.KeymanTarget.any);
|
||||
} else {
|
||||
this.resolvedTargets = [].concat(this.options.targets);
|
||||
|
|
@ -72,8 +73,12 @@ export class BasicGenerator extends AbstractGenerator {
|
|||
}
|
||||
|
||||
private getLanguageName(tag: string) {
|
||||
// TODO-GENERATE: probably need to use langtags.json
|
||||
return new Intl.Locale(tag).language;
|
||||
const langtag = getLangtagByTag(tag);
|
||||
if(!langtag) {
|
||||
// Fallback to Intl.Locale, probably will be undefined
|
||||
return new Intl.Locale(tag).language;
|
||||
}
|
||||
return langtag.name;
|
||||
}
|
||||
|
||||
private generateLanguageListForPackage(): string {
|
||||
|
|
|
|||