mirror of
https://github.com/keymanapp/keyman.git
synced 2026-10-22 05:47:41 +00:00
Merge branch 'epic/autocorrect' into refactor/web/compute-distance-helper
This commit is contained in:
commit
785b139b17
62 changed files with 5409 additions and 640 deletions
10
.github/workflows/api-verification.yml
vendored
10
.github/workflows/api-verification.yml
vendored
|
|
@ -23,6 +23,7 @@ jobs:
|
|||
GIT_BRANCH: ${{ steps.environment_step.outputs.GIT_BRANCH }}
|
||||
GIT_BASE_BRANCH: ${{ steps.environment_step.outputs.GIT_BASE_BRANCH }}
|
||||
GIT_USER: ${{ steps.environment_step.outputs.GIT_USER }}
|
||||
SKIP_API_CHECK: ${{ steps.environment_step.outputs.SKIP_API_CHECK }}
|
||||
|
||||
steps:
|
||||
- name: Restore artifacts
|
||||
|
|
@ -40,7 +41,7 @@ jobs:
|
|||
|
||||
- name: Set pending status on PR builds
|
||||
id: set_status
|
||||
if: steps.environment_step.outputs.IS_TEST_BUILD == 'true'
|
||||
if: steps.environment_step.outputs.IS_TEST_BUILD == 'true' && steps.environment_step.outputs.SKIP_API_CHECK != 'true'
|
||||
shell: bash
|
||||
run: |
|
||||
gh api \
|
||||
|
|
@ -53,6 +54,7 @@ jobs:
|
|||
-f context="$STATUS_CONTEXT"
|
||||
|
||||
- name: Checkout
|
||||
if: steps.environment_step.outputs.SKIP_API_CHECK != 'true'
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.2.2
|
||||
with:
|
||||
ref: '${{ steps.environment_step.outputs.GIT_SHA }}'
|
||||
|
|
@ -61,11 +63,13 @@ jobs:
|
|||
path: ${{ github.workspace }}/keyman/
|
||||
|
||||
- name: Install devscripts
|
||||
if: steps.environment_step.outputs.SKIP_API_CHECK != 'true'
|
||||
uses: ./keyman/.github/actions/apt-install
|
||||
with:
|
||||
packages: devscripts equivs
|
||||
|
||||
- name: "Verify API for libkeymancore*.so (${{ steps.environment_step.outputs.GIT_BRANCH }}, branch ${{ steps.environment_step.outputs.GIT_BASE_BRANCH }}, by ${{ steps.environment_step.outputs.GIT_USER }})"
|
||||
if: steps.environment_step.outputs.SKIP_API_CHECK != 'true'
|
||||
run: |
|
||||
echo "Verify API for libkeymancore*.so (${{ steps.environment_step.outputs.GIT_BRANCH }}, branch ${{ steps.environment_step.outputs.GIT_BASE_BRANCH }}, by ${{ steps.environment_step.outputs.GIT_USER }}):" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
|
|
@ -79,17 +83,17 @@ jobs:
|
|||
verify 2>> $GITHUB_STEP_SUMMARY
|
||||
|
||||
- name: Archive .symbols file
|
||||
if: steps.environment_step.outputs.SKIP_API_CHECK != 'true' && always()
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||
with:
|
||||
name: libkeymancore.symbols
|
||||
path: ${{ github.workspace }}/keyman/linux/debian/tmp/DEBIAN/symbols
|
||||
if: always()
|
||||
|
||||
set_status:
|
||||
name: Set result status on PR builds
|
||||
needs: [api_verification]
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ always() && needs.api_verification.outputs.IS_TEST_BUILD == 'true' }}
|
||||
if: ${{ always() && needs.api_verification.outputs.IS_TEST_BUILD == 'true' && needs.api_verification.outputs.SKIP_API_CHECK != 'true' }}
|
||||
steps:
|
||||
- name: Set success
|
||||
if: needs.api_verification.result == 'success'
|
||||
|
|
|
|||
90
.github/workflows/build-test-publish-docker.yml
vendored
Normal file
90
.github/workflows/build-test-publish-docker.yml
vendored
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
# This workflow runs the build, test and publish steps for the
|
||||
# Keyman build Docker images.
|
||||
# It is triggered by a schedule and repository_dispatch event.
|
||||
|
||||
name: "Build, test, and publish Docker images"
|
||||
run-name: "Build, test, and publish Docker images (branch ${{ github.ref_name }} on ${{ github.event_name }}/${{ github.event.action }} by ${{ github.actor }})"
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
on:
|
||||
schedule:
|
||||
#run every Fri, 3 pm UTC
|
||||
- cron: '0 15 * * 5'
|
||||
|
||||
repository_dispatch:
|
||||
types: ['build-test-publish-docker:*']
|
||||
|
||||
env:
|
||||
REGISTRY: ghcr.io
|
||||
USERNAME: "${{ github.actor }}"
|
||||
PASSWORD: "${{ github.token }}"
|
||||
|
||||
jobs:
|
||||
|
||||
message:
|
||||
name: Print message
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.event.act }}
|
||||
|
||||
steps:
|
||||
- name: Print message
|
||||
id: print-message
|
||||
run: |
|
||||
echo "Build, test, and publish Docker images (branch ${{ github.ref_name }} on ${{ github.event_name }}/${{ github.event.action }} by ${{ github.actor }})"
|
||||
|
||||
build:
|
||||
name: Build Docker images
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
id: checkout
|
||||
uses: actions/checkout@v4
|
||||
- name: Build Docker images
|
||||
id: build
|
||||
run: |
|
||||
if [ -z "${{ env.USERNAME }}" ]; then
|
||||
resources/docker-images/build.sh build: --registry ${{ env.REGISTRY }}
|
||||
else
|
||||
echo ${{ env.PASSWORD }} | resources/docker-images/build.sh build: --registry ${{ env.REGISTRY }} --username ${{ env.USERNAME }}
|
||||
fi
|
||||
|
||||
publish:
|
||||
name: Publish Docker images
|
||||
runs-on: ubuntu-latest
|
||||
needs: build
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
id: checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Publish Docker images
|
||||
id: publish
|
||||
run: |
|
||||
if [ -z "${{ env.USERNAME }}" ]; then
|
||||
resources/docker-images/build.sh publish: --registry ${{ env.REGISTRY }}
|
||||
else
|
||||
echo ${{ env.PASSWORD }} | resources/docker-images/build.sh publish: --registry ${{ env.REGISTRY }} --username ${{ env.USERNAME }}
|
||||
fi
|
||||
|
||||
test:
|
||||
name: Test Docker images
|
||||
runs-on: ubuntu-latest
|
||||
needs: publish
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
id: checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Test Docker images
|
||||
id: test
|
||||
run: |
|
||||
if [ -z "${{ env.USERNAME }}" ]; then
|
||||
resources/docker-images/build.sh test: --registry ${{ env.REGISTRY }}
|
||||
else
|
||||
echo ${{ env.PASSWORD }} | resources/docker-images/build.sh test: --registry ${{ env.REGISTRY }} --username ${{ env.USERNAME }}
|
||||
fi
|
||||
2
.github/workflows/deb-packaging.yml
vendored
2
.github/workflows/deb-packaging.yml
vendored
|
|
@ -23,6 +23,7 @@ on:
|
|||
# baseRef: The ref of the previous commit. For a PR the same as `baseBranch`.
|
||||
# user: The user that triggered the build or created the PR
|
||||
# isTestBuild: false for Releases, otherwise true
|
||||
# skipApiCheck: true to skip the API check, otherwise false
|
||||
|
||||
env:
|
||||
COLOR_GREEN: "\e[32m"
|
||||
|
|
@ -332,6 +333,7 @@ jobs:
|
|||
echo "GIT_BRANCH=${{ github.event.client_payload.branch }}" >> artifacts/env
|
||||
echo "GIT_BASE_BRANCH=${{ github.event.client_payload.baseBranch }}" >> artifacts/env
|
||||
echo "GIT_USER=${{ github.event.client_payload.user }}" >> artifacts/env
|
||||
echo "SKIP_API_CHECK=${{ github.event.client_payload.skipApiCheck }}" >> artifacts/env
|
||||
|
||||
- name: Cache artifacts
|
||||
uses: actions/cache/save@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
|
||||
|
|
|
|||
19
.github/workflows/delete-build-containers.yml
vendored
Normal file
19
.github/workflows/delete-build-containers.yml
vendored
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
|
||||
|
||||
on:
|
||||
schedule:
|
||||
#run every Fri, 6 pm UTC
|
||||
- cron: '0 18 * * 5' #
|
||||
|
||||
jobs:
|
||||
cleanup-images:
|
||||
name: ghcr.io cleanup action
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: dataaxiom/ghcr-cleanup-action@cd0cdb900b5dbf3a6f2cc869f0dbb0b8211f50c4 # v1.0.16
|
||||
with:
|
||||
dry-run: true
|
||||
expand-packages: true
|
||||
packages: keyman-*-ci
|
||||
delete-untagged: true
|
||||
364
.github/workflows/pr-build-status.yml
vendored
364
.github/workflows/pr-build-status.yml
vendored
|
|
@ -1,4 +1,4 @@
|
|||
# GENERATED FILE - DO NOT EDIT!
|
||||
# GENERATED FILE - DO NOT EDIT!
|
||||
#
|
||||
# Keyman is copyright (C) SIL Global. MIT License.
|
||||
#
|
||||
|
|
@ -35,174 +35,194 @@ jobs:
|
|||
id: run_pr_build_status_script
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
// This code is copied out of resources/build/pr-build-status/pr-build-status.mjs
|
||||
// where it is tested. It is copied inline here in order to avoid requiring the
|
||||
// repository to be checked out, which dramatically reduces the run time of the
|
||||
// check.
|
||||
//
|
||||
// Note: we don't currently look at check runs, only statuses
|
||||
//
|
||||
// Verify the following statuses:
|
||||
// 'user_testing'
|
||||
// 'API Verification' (github-actions[bot])
|
||||
//
|
||||
// At least 1 of the following statuses must be found:
|
||||
// 'Test*' (keyman-server), e.g. 'Test Build (Keyman)'
|
||||
// 'Ubuntu Packaging' (github-actions[bot])
|
||||
//
|
||||
// Ignore the following statuses:
|
||||
// check/web/file-size
|
||||
//
|
||||
|
||||
function reduceStatuses(statuses) {
|
||||
const filtered_statuses = statuses.reduce((o, status) => {
|
||||
if(status.creator?.login == 'keyman-server' && status.context.startsWith('Test')) {
|
||||
if(!o[status.context]) o[status.context] = {type: 'build', state: status.state};
|
||||
} else if(status.creator?.login == 'keymanapp-test-bot[bot]' && status.context == 'user_testing') {
|
||||
if(!o[status.context]) o[status.context] = {type: 'user-test', state: status.state};;
|
||||
} else if(status.context == 'API Verification') {
|
||||
if(!o[status.context]) o[status.context] = {type: 'check', state: status.state};
|
||||
} else if(status.context == 'Ubuntu Packaging') {
|
||||
if(!o[status.context]) o[status.context] = {type: 'build', state: status.state};
|
||||
} else if(status.context == 'check/web/file-size') {
|
||||
// Ignore check/web/file-size -- we won't block automerge for this at this point
|
||||
} else {
|
||||
// We fail with an 'unknown status' response if we get a new status check
|
||||
// so we can be sure we are not skipping known status checks
|
||||
o[status.context] = {type: 'unknown', state: status.state};
|
||||
}
|
||||
return o;
|
||||
|
||||
}, {});
|
||||
return filtered_statuses;
|
||||
}
|
||||
|
||||
//
|
||||
// Given the collection of status checks we care about, return
|
||||
// an aggregate status -- error, failed, pending, or success,
|
||||
// and a summary description
|
||||
//
|
||||
function calculateFinalStatus(filtered_statuses) {
|
||||
const counts = {};
|
||||
let hasBuilds = false;
|
||||
for(const context of Object.keys(filtered_statuses)) {
|
||||
const { state, type } = filtered_statuses[context];
|
||||
if(type == 'unknown') {
|
||||
// We special-case for unknown status checks, and never permit them
|
||||
return [
|
||||
'error', `An unknown context ${context} was found, cannot calculate build status.`
|
||||
];
|
||||
}
|
||||
if(type == 'build') {
|
||||
hasBuilds = true;
|
||||
}
|
||||
counts[state] = counts[state] ? counts[state] + 1 : 1;
|
||||
}
|
||||
|
||||
// If we do not have any statuses yet, we wait
|
||||
if(Object.keys(filtered_statuses).length == 0 || !hasBuilds) {
|
||||
return ['pending', 'Builds have not yet been triggered ⌛'];
|
||||
}
|
||||
|
||||
const state =
|
||||
counts.error ? 'error' :
|
||||
counts.failed ? 'failed' :
|
||||
counts.pending ? 'pending' :
|
||||
'success';
|
||||
|
||||
let description = '';
|
||||
function appendDescription(count, state) {
|
||||
if(!count) return;
|
||||
if(description != '') description += '; ';
|
||||
description += `${count} check${count == 1 ? '' : 's'} ${state}`;
|
||||
}
|
||||
appendDescription(counts.error, 'in an error state ❌');
|
||||
appendDescription(counts.failed, 'failed ❌');
|
||||
appendDescription(counts.pending, 'pending ⌛');
|
||||
appendDescription(counts.success, 'completed successfully ✅');
|
||||
|
||||
return [ state, description ];
|
||||
}
|
||||
|
||||
async function getCommitStatuses(github, owner, repo, sha) {
|
||||
const statuses = await github.paginate('GET /repos/{owner}/{repo}/commits/{sha}/statuses', {
|
||||
owner,
|
||||
repo,
|
||||
sha,
|
||||
headers: {
|
||||
'X-GitHub-Api-Version': '2022-11-28'
|
||||
}
|
||||
});
|
||||
return statuses;
|
||||
}
|
||||
|
||||
async function getCommitCheckRuns(github, owner, repo, sha) {
|
||||
const statuses = await github.paginate('GET /repos/{owner}/{repo}/commits/{sha}/check-runs', {
|
||||
owner,
|
||||
repo,
|
||||
sha,
|
||||
headers: {
|
||||
'X-GitHub-Api-Version': '2022-11-28'
|
||||
}
|
||||
});
|
||||
return statuses;
|
||||
}
|
||||
|
||||
function calculateCheckResult(statuses) {
|
||||
if(!Array.isArray(statuses)) {
|
||||
return ['error', 'Failed to retrieve status checks from GitHub ❌'];
|
||||
}
|
||||
|
||||
const filtered_statuses = reduceStatuses(statuses);
|
||||
|
||||
const result = calculateFinalStatus(filtered_statuses);
|
||||
return result;
|
||||
}
|
||||
|
||||
async function test(github, owner, repo, sha) {
|
||||
// Get statuses from sha
|
||||
const statuses = await getCommitStatuses(github, owner, repo, sha);
|
||||
return calculateCheckResult(statuses);
|
||||
}
|
||||
|
||||
async function createCheck(github, owner, repo, sha) {
|
||||
const check = await github.rest.checks.create({
|
||||
owner,
|
||||
repo,
|
||||
head_sha: sha,
|
||||
name: 'Build Outcome',
|
||||
status: 'in_progress',
|
||||
});
|
||||
return check.data.id;
|
||||
}
|
||||
|
||||
async function updateCheck(github, owner, repo, checkRunId, status, description) {
|
||||
const checkStatus = status == 'pending' ? 'in_progress' : 'completed';
|
||||
const conclusion = checkStatus == 'in_progress' ? undefined : (status == 'success' ? 'success' : 'failure');
|
||||
|
||||
await github.rest.checks.update({
|
||||
owner,
|
||||
repo,
|
||||
check_run_id: checkRunId,
|
||||
status: checkStatus,
|
||||
conclusion,
|
||||
output: {
|
||||
title: description,
|
||||
summary: ''
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const { owner, repo } = context.repo;
|
||||
const sha =
|
||||
context.payload?.check_suite?.sha || /* check run completed */
|
||||
context.payload?.inputs?.commit || /* manual run */
|
||||
context.payload?.after || /* push */
|
||||
context.payload?.commit?.sha || /* status */
|
||||
context.sha; /* probably 'master'! */
|
||||
|
||||
const checkRunId = await createCheck(github, owner, repo, sha);
|
||||
const res = await test(github, owner, repo, sha);
|
||||
await updateCheck(github, owner, repo, checkRunId, res[0], res[1]);
|
||||
|
||||
script: |
|
||||
// This code is copied out of resources/build/pr-build-status/pr-build-status.mjs
|
||||
// where it is tested. It is copied inline here in order to avoid requiring the
|
||||
// repository to be checked out, which dramatically reduces the run time of the
|
||||
// check.
|
||||
//
|
||||
// Note: we don't currently look at check runs, only statuses
|
||||
//
|
||||
// Verify the following statuses:
|
||||
// 'user_testing'
|
||||
// 'API Verification' (github-actions[bot])
|
||||
//
|
||||
// At least 1 of the following statuses must be found:
|
||||
// 'Test*' (keyman-server), e.g. 'Test Build (Keyman)'
|
||||
// 'Ubuntu Packaging' (github-actions[bot])
|
||||
//
|
||||
// Ignore the following statuses:
|
||||
// check/web/file-size
|
||||
//
|
||||
|
||||
function addLog(message) {
|
||||
console.log(message);
|
||||
return message + String.fromCharCode(10);
|
||||
}
|
||||
|
||||
function addStatus(o, type, context, state) {
|
||||
if(!o[context]) {
|
||||
o[context] = {type, state};
|
||||
return addLog(`Found ${context}: ${state}`);
|
||||
} else {
|
||||
return addLog(`Skipping repeated ${context}: ${state}`);
|
||||
}
|
||||
}
|
||||
|
||||
function reduceStatuses(statuses) {
|
||||
let summary = '';
|
||||
const filtered_statuses = statuses.reduce((o, status) => {
|
||||
if(status.creator?.login == 'keyman-server' && status.context.startsWith('Test')) {
|
||||
summary += addStatus(o, 'build', status.context, status.state);
|
||||
} else if(status.creator?.login == 'keymanapp-test-bot[bot]' && status.context == 'user_testing') {
|
||||
summary += addStatus(o, 'user-test', status.context, status.state);
|
||||
} else if(status.context == 'API Verification') {
|
||||
summary += addStatus(o, 'check', status.context, status.state);
|
||||
} else if(status.context == 'Ubuntu Packaging') {
|
||||
summary += addStatus(o, 'build', status.context, status.state);
|
||||
} else if(status.context == 'check/web/file-size') {
|
||||
// Ignore check/web/file-size -- we won't block automerge for this at this point
|
||||
summary += addLog(`Skipping ${status.context}`);
|
||||
} else {
|
||||
// We fail with an 'unknown status' response if we get a new status check
|
||||
// so we can be sure we are not skipping known status checks
|
||||
summary += addLog(`Found unknown ${status.context}: ${status.state}`);
|
||||
o[status.context] = {type: 'unknown', state: status.state};
|
||||
}
|
||||
return o;
|
||||
|
||||
}, {});
|
||||
return { filtered_statuses, summary };
|
||||
}
|
||||
|
||||
//
|
||||
// Given the collection of status checks we care about, return
|
||||
// an aggregate status -- error, failure, pending, or success,
|
||||
// and a summary description
|
||||
//
|
||||
function calculateFinalStatus(filtered_statuses, summary) {
|
||||
const counts = {};
|
||||
let hasBuilds = false;
|
||||
for(const context of Object.keys(filtered_statuses)) {
|
||||
const { state, type } = filtered_statuses[context];
|
||||
if(type == 'unknown') {
|
||||
// We special-case for unknown status checks, and never permit them
|
||||
console.error(`An unknown context ${context} was found, cannot calculate build status.`);
|
||||
return [
|
||||
'error', `An unknown context ${context} was found, cannot calculate build status.`, summary
|
||||
];
|
||||
}
|
||||
if(type == 'build') {
|
||||
hasBuilds = true;
|
||||
}
|
||||
counts[state] = counts[state] ? counts[state] + 1 : 1;
|
||||
}
|
||||
|
||||
// If we do not have any statuses yet, we wait
|
||||
if(Object.keys(filtered_statuses).length == 0 || !hasBuilds) {
|
||||
console.log(`Builds not yet triggered`);
|
||||
return ['pending', 'Builds have not yet been triggered ⌛', summary];
|
||||
}
|
||||
|
||||
const state =
|
||||
counts.error ? 'error' :
|
||||
counts.failure ? 'failure' :
|
||||
counts.pending ? 'pending' :
|
||||
'success';
|
||||
|
||||
let description = '';
|
||||
function appendDescription(count, state) {
|
||||
if(!count) return;
|
||||
if(description != '') description += '; ';
|
||||
description += `${count} check${count == 1 ? '' : 's'} ${state}`;
|
||||
}
|
||||
appendDescription(counts.error, 'in an error state ❌');
|
||||
appendDescription(counts.failure, 'failed ❌');
|
||||
appendDescription(counts.pending, 'pending ⌛');
|
||||
appendDescription(counts.success, 'completed successfully ✅');
|
||||
|
||||
console.log(`Finished filtering and reviewing status checks: ${state}: ${description}`);
|
||||
return [ state, description, summary ];
|
||||
}
|
||||
|
||||
async function getCommitStatuses(github, owner, repo, sha) {
|
||||
console.log(`Getting commit statuses for ${sha}`);
|
||||
const statuses = await github.paginate('GET /repos/{owner}/{repo}/commits/{sha}/statuses', {
|
||||
owner,
|
||||
repo,
|
||||
sha,
|
||||
headers: {
|
||||
'X-GitHub-Api-Version': '2022-11-28'
|
||||
}
|
||||
});
|
||||
return statuses;
|
||||
}
|
||||
|
||||
async function getCommitCheckRuns(github, owner, repo, sha) {
|
||||
console.log(`Getting commit check runs for ${sha}`);
|
||||
const statuses = await github.paginate('GET /repos/{owner}/{repo}/commits/{sha}/check-runs', {
|
||||
owner,
|
||||
repo,
|
||||
sha,
|
||||
headers: {
|
||||
'X-GitHub-Api-Version': '2022-11-28'
|
||||
}
|
||||
});
|
||||
return statuses;
|
||||
}
|
||||
|
||||
function calculateCheckResult(statuses) {
|
||||
if(!Array.isArray(statuses)) {
|
||||
return ['error', 'Failed to retrieve status checks from GitHub ❌', 'statuses is not an array'];
|
||||
}
|
||||
|
||||
const { filtered_statuses, summary } = reduceStatuses(statuses);
|
||||
return calculateFinalStatus(filtered_statuses, summary);
|
||||
}
|
||||
|
||||
async function test(github, owner, repo, sha) {
|
||||
// Get statuses from sha
|
||||
const statuses = await getCommitStatuses(github, owner, repo, sha);
|
||||
return calculateCheckResult(statuses);
|
||||
}
|
||||
|
||||
async function createCheck(github, owner, repo, sha) {
|
||||
const check = await github.rest.checks.create({
|
||||
owner,
|
||||
repo,
|
||||
head_sha: sha,
|
||||
name: 'Build Outcome',
|
||||
status: 'in_progress',
|
||||
});
|
||||
return check.data.id;
|
||||
}
|
||||
|
||||
async function updateCheck(github, owner, repo, checkRunId, status, description, summary) {
|
||||
const checkStatus = status == 'pending' ? 'in_progress' : 'completed';
|
||||
const conclusion = checkStatus == 'in_progress' ? undefined : (status == 'success' ? 'success' : 'failure');
|
||||
|
||||
await github.rest.checks.update({
|
||||
owner,
|
||||
repo,
|
||||
check_run_id: checkRunId,
|
||||
status: checkStatus,
|
||||
conclusion,
|
||||
output: {
|
||||
title: description,
|
||||
summary
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const { owner, repo } = context.repo;
|
||||
const sha =
|
||||
context.payload?.check_suite?.sha || /* check run completed */
|
||||
context.payload?.inputs?.commit || /* manual run */
|
||||
context.payload?.after || /* push */
|
||||
context.payload?.commit?.sha || /* status */
|
||||
context.sha; /* probably 'master'! */
|
||||
|
||||
const checkRunId = await createCheck(github, owner, repo, sha);
|
||||
const res = await test(github, owner, repo, sha);
|
||||
await updateCheck(github, owner, repo, checkRunId, res[0], res[1], res[2]);
|
||||
|
||||
|
|
|
|||
45
HISTORY.md
45
HISTORY.md
|
|
@ -1,5 +1,50 @@
|
|||
# Keyman Version History
|
||||
|
||||
## 19.0.117 alpha 2025-09-11
|
||||
|
||||
* fix(resources): ignore KEYMAN_VERSION_FOR_FILENAME in test (#14730)
|
||||
* fix(resources): pr build status - find 'failure' state in status checks and log (#14732)
|
||||
|
||||
## 19.0.116 alpha 2025-09-10
|
||||
|
||||
* fix(windows): kmshell continues when sm is in waitingrestart and returns to idle (#14644)
|
||||
* maint(linux): allow to skip API check (#14699)
|
||||
* maint(resources): adding GitHub actions workflow for Docker builds (#14674)
|
||||
* maint(developer): use versioned filenames for PR artifacts (#14701)
|
||||
* maint(windows): use versioned filenames for PR artifacts (#14702)
|
||||
* maint(android): use versioned filenames for PR artifacts (#14703)
|
||||
* maint(ios): use versioned filenames for PR artifacts (#14704)
|
||||
* maint(mac): use versioned filenames for PR artifacts (#14705)
|
||||
* maint(resources): rename KEYMAN_VERSION_FOR_PR_FILENAME (#14720)
|
||||
|
||||
## 19.0.115 alpha 2025-09-09
|
||||
|
||||
* fix(linux): don't crash if `kmp.json` is missing `keyboards` section (#14708)
|
||||
|
||||
## 19.0.114 alpha 2025-09-08
|
||||
|
||||
* docs(web): Improve empty What's New page for Web (#14660)
|
||||
* maint(linux): remove obsolete Makefile (#14694)
|
||||
* maint(resources): honor configure comment character in commit message (#14695)
|
||||
* fix(web): fix error trying to calculate style scaling effects (#14684)
|
||||
* refactor(resources): remove shellcheck warnings (#14698)
|
||||
|
||||
## 19.0.113 alpha 2025-09-04
|
||||
|
||||
* fix(android): Update KMSample1 layout when changing orientation (#14678)
|
||||
|
||||
## 19.0.112 alpha 2025-09-03
|
||||
|
||||
* fix(developer): add clear messages about validation failures to New LM Project Parameters form (#14659)
|
||||
* docs(developer): tweak get-started for kmc and add entry to HISTORY.md (#14667)
|
||||
* fix(android): Cleanup list layout in Engine and FirstVoices for edge to edge (#14655)
|
||||
* docs(common): update license date and owner (#14668)
|
||||
* maint(linux): skip tarball creation for `Build-bot: build` buildLevel (#14671)
|
||||
* docs(common): update docs Keyman Desktop → Keyman for Windows (#14669)
|
||||
* feat(web): adds transform cataloging methods to predictive-text worker (#14581)
|
||||
* feat(web): batch correction-search paths by related subsets (#14592)
|
||||
* refactor(web): simplify edit-distance calculation-object inputs (#14618)
|
||||
|
||||
## 19.0.111 alpha 2025-09-02
|
||||
|
||||
* change(developer): update SIL logo (#14656)
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
19.0.112
|
||||
19.0.118
|
||||
|
|
@ -46,7 +46,7 @@ MODEL_PACKAGE_ID="nrc.en.mtnt"
|
|||
MODELS_TARGET="android/KMAPro/kMAPro/src/main/assets/${MODEL_PACKAGE_ID}.model.kmp"
|
||||
builder_describe_outputs \
|
||||
configure "/${MODELS_TARGET}" \
|
||||
build /android/KMAPro/kMAPro/build/outputs/apk/$CONFIG/keyman-${KEYMAN_VERSION}.apk
|
||||
build /android/KMAPro/kMAPro/build/outputs/apk/$CONFIG/keyman-${KEYMAN_VERSION_FOR_FILENAME}.apk
|
||||
|
||||
#### Build
|
||||
|
||||
|
|
@ -77,13 +77,15 @@ if builder_start_action build; then
|
|||
|
||||
# Copy Keyman Engine for Android
|
||||
cp "${KEYMAN_ROOT}/android/KMEA/app/build/outputs/aar/keyman-engine-${CONFIG}.aar" "${KEYMAN_ROOT}/android/KMAPro/kMAPro/libs/keyman-engine.aar"
|
||||
|
||||
|
||||
# Convert markdown to html for offline help
|
||||
build_help_html android KMAPro/kMAPro/src/main/assets/info
|
||||
|
||||
echo "BUILD_FLAGS $BUILD_FLAGS"
|
||||
./gradlew $DAEMON_FLAG clean $BUILD_FLAGS
|
||||
|
||||
mv "${KEYMAN_ROOT}/android/KMAPro/kMAPro/build/outputs/apk/$CONFIG/keyman-${KEYMAN_VERSION}.apk" "${KEYMAN_ROOT}/android/KMAPro/kMAPro/build/outputs/apk/$CONFIG/keyman-${KEYMAN_VERSION_FOR_FILENAME}.apk"
|
||||
|
||||
builder_finish_action success build
|
||||
fi
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,9 @@ package com.keyman.kmsample1;
|
|||
|
||||
import android.content.Context;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.Point;
|
||||
import android.os.Bundle;
|
||||
import android.util.TypedValue;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
|
||||
|
|
@ -25,6 +27,7 @@ public class MainActivity extends BaseActivity implements OnKeyboardEventListene
|
|||
public static Context context;
|
||||
private ConstraintLayout constraintLayout;
|
||||
private KMTextView textView;
|
||||
private int lastOrientation = Configuration.ORIENTATION_UNDEFINED;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
|
|
@ -99,6 +102,18 @@ public class MainActivity extends BaseActivity implements OnKeyboardEventListene
|
|||
protected void onResume() {
|
||||
super.onResume();
|
||||
KMManager.onResume();
|
||||
|
||||
// onConfigurationChanged() only triggers when device is rotated while app is in foreground
|
||||
// This handles when device is rotated while app is in background
|
||||
// using KMManager.getOrientation() since getConfiguration().orientation is unreliable #10241
|
||||
int newOrientation = KMManager.getOrientation(context);
|
||||
if (newOrientation != lastOrientation) {
|
||||
lastOrientation = newOrientation;
|
||||
Configuration newConfig = this.getResources().getConfiguration();
|
||||
KMManager.onConfigurationChanged(newConfig);
|
||||
}
|
||||
resizeTextView(textView.isKeyboardVisible());
|
||||
|
||||
KMManager.addKeyboardEventListener(this);
|
||||
KMKeyboardDownloaderActivity.addKeyboardDownloadEventListener(this);
|
||||
}
|
||||
|
|
@ -116,6 +131,10 @@ public class MainActivity extends BaseActivity implements OnKeyboardEventListene
|
|||
@Override
|
||||
public void onConfigurationChanged(Configuration newConfig) {
|
||||
super.onConfigurationChanged(newConfig);
|
||||
KMManager.onConfigurationChanged(newConfig);
|
||||
|
||||
resizeTextView(textView.isKeyboardVisible());
|
||||
lastOrientation = newConfig.orientation;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -131,11 +150,44 @@ public class MainActivity extends BaseActivity implements OnKeyboardEventListene
|
|||
@Override
|
||||
public void onKeyboardShown() {
|
||||
// Handle Keyman keyboard shown event here if needed
|
||||
resizeTextView(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onKeyboardDismissed() {
|
||||
// Handle Keyman keyboard dismissed event here if needed
|
||||
resizeTextView(false);
|
||||
}
|
||||
|
||||
public void resizeTextView(boolean isKeyboardVisible) {
|
||||
int bannerHeight = 0;
|
||||
int keyboardHeight = 0;
|
||||
if (isKeyboardVisible) {
|
||||
bannerHeight = KMManager.getBannerHeight(this);
|
||||
keyboardHeight = KMManager.getKeyboardHeight(this);
|
||||
}
|
||||
|
||||
TypedValue outValue = new TypedValue();
|
||||
getTheme().resolveAttribute(android.R.attr.actionBarSize, outValue, true);
|
||||
int actionBarHeight = getResources().getDimensionPixelSize(outValue.resourceId);
|
||||
|
||||
// *** TO DO: Try to check if status bar is visible, set statusBarHeight to 0 if it is not visible ***
|
||||
int statusBarHeight = 0;
|
||||
int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
|
||||
if (resourceId > 0)
|
||||
statusBarHeight = getResources().getDimensionPixelSize(resourceId);
|
||||
|
||||
// Navigation bar height
|
||||
int navigationBarHeight = 0;
|
||||
resourceId = getResources().getIdentifier("navigation_bar_height", "dimen", "android");
|
||||
if (resourceId > 0) {
|
||||
navigationBarHeight = getResources().getDimensionPixelSize(resourceId);
|
||||
}
|
||||
|
||||
Point size = KMManager.getWindowSize(context);
|
||||
int screenHeight = size.y;
|
||||
textView.setHeight(
|
||||
screenHeight - statusBarHeight - actionBarHeight - bannerHeight - keyboardHeight - navigationBarHeight);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -62,11 +62,12 @@ function do_test_help() {
|
|||
|
||||
function archive_artifacts() {
|
||||
local UPLOAD_PATH KEYMAN_ENGINE_ANDROID_ZIP KEYMAN_APK FIRSTVOICES_APK
|
||||
local KEYMAN_FULLY_VERSIONED_APK FIRSTVOICES_FULLY_VERSIONED_APK
|
||||
|
||||
UPLOAD_PATH="${KEYMAN_ROOT}/android/upload/${KEYMAN_VERSION}"
|
||||
KEYMAN_ENGINE_ANDROID_ZIP="keyman-engine-android-${KEYMAN_VERSION}.zip"
|
||||
KEYMAN_APK="keyman-${KEYMAN_VERSION}.apk"
|
||||
FIRSTVOICES_APK="firstvoices-${KEYMAN_VERSION}.apk"
|
||||
KEYMAN_APK="keyman-${KEYMAN_VERSION_FOR_FILENAME}.apk"
|
||||
FIRSTVOICES_APK="firstvoices-${KEYMAN_VERSION_FOR_FILENAME}.apk"
|
||||
|
||||
rm -rf "${UPLOAD_PATH}"
|
||||
mkdir -p "${UPLOAD_PATH}"
|
||||
|
|
@ -87,12 +88,12 @@ function archive_artifacts() {
|
|||
)
|
||||
|
||||
# Copy release APK
|
||||
cp "${KEYMAN_ROOT}/android/KMAPro/kMAPro/build/outputs/apk/release/${KEYMAN_APK}" "${UPLOAD_PATH}"
|
||||
cp "${KEYMAN_ROOT}/android/KMAPro/kMAPro/build/outputs/apk/release/${KEYMAN_APK}" "${UPLOAD_PATH}/${KEYMAN_APK}"
|
||||
|
||||
# FirstVoices app
|
||||
|
||||
if [[ "${RELEASE_OEM_FIRSTVOICES-false}" = true ]]; then
|
||||
cp "${KEYMAN_ROOT}/oem/firstvoices/android/app/build/outputs/apk/release/${FIRSTVOICES_APK}" "${UPLOAD_PATH}"
|
||||
cp "${KEYMAN_ROOT}/oem/firstvoices/android/app/build/outputs/apk/release/${FIRSTVOICES_APK}" "${UPLOAD_PATH}/${FIRSTVOICES_APK}"
|
||||
fi
|
||||
|
||||
#
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ and tutorials, and full reference information.
|
|||
|
||||
## Guides and Tutorials
|
||||
- [What is Keyman Developer?](guides/intro)
|
||||
- [What's new in 19.0](whats-new)
|
||||
- [What's new in 19.0](whatsnew)
|
||||
- [Developing Keyman keyboard layouts](guides/develop)
|
||||
- [Testing Keyman keyboards](guides/test)
|
||||
- [Distributing Keyman keyboards](guides/distribute)
|
||||
|
|
@ -35,4 +35,4 @@ and tutorials, and full reference information.
|
|||
- [Keyman Engine for Windows](/developer/engine/windows/current-version/)
|
||||
- [Keyman Engine for Web](/developer/engine/web/)
|
||||
- [Keyman Engine for iPhone and iPad](/developer/engine/iphone-and-ipad/current-version/)
|
||||
- [Keyman Engine for Android](/developer/engine/android/current-version/)
|
||||
- [Keyman Engine for Android](/developer/engine/android/current-version/)
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ builder_describe "Installation files for Keyman Developer" \
|
|||
# after all other builds complete
|
||||
|
||||
builder_describe_outputs \
|
||||
publish /developer/src/inst/keymandeveloper-${KEYMAN_VERSION}.exe
|
||||
publish /developer/src/inst/keymandeveloper-${KEYMAN_VERSION_FOR_FILENAME}.exe
|
||||
|
||||
builder_parse "$@"
|
||||
|
||||
|
|
@ -78,7 +78,7 @@ function do_publish() {
|
|||
# Copy the installation archive
|
||||
#
|
||||
|
||||
copy-kmdev
|
||||
copy-keymandeveloper-installer-to-artifacts
|
||||
|
||||
builder_if_release_build_level verify-installer-signatures
|
||||
}
|
||||
|
|
@ -87,8 +87,8 @@ function do_test() {
|
|||
verify-node-installer-version
|
||||
}
|
||||
|
||||
function copy-kmdev() {
|
||||
builder_heading copy-kmdev
|
||||
function copy-keymandeveloper-installer-to-artifacts() {
|
||||
builder_heading copy-keymandeveloper-installer-to-artifacts
|
||||
|
||||
mkdir -p "$DEVELOPER_ROOT/release/${KEYMAN_VERSION}"
|
||||
|
||||
|
|
@ -96,7 +96,7 @@ function copy-kmdev() {
|
|||
make-kmc-install-zip
|
||||
|
||||
cp -f "$DEVELOPER_ROOT/src/inst/keymandeveloper.msi" "$DEVELOPER_ROOT/release/${KEYMAN_VERSION}/keymandeveloper.msi"
|
||||
cp -f "$DEVELOPER_ROOT/src/inst/keymandeveloper-${KEYMAN_VERSION}.exe" "$DEVELOPER_ROOT/release/${KEYMAN_VERSION}/keymandeveloper-${KEYMAN_VERSION}.exe"
|
||||
cp -f "$DEVELOPER_ROOT/src/inst/keymandeveloper-${KEYMAN_VERSION_FOR_FILENAME}.exe" "$DEVELOPER_ROOT/release/${KEYMAN_VERSION}/keymandeveloper-${KEYMAN_VERSION_FOR_FILENAME}.exe"
|
||||
}
|
||||
|
||||
function verify-program-signatures() {
|
||||
|
|
@ -234,8 +234,8 @@ function make-installer() {
|
|||
echo "MSIFileName=keymandeveloper.msi" >> setup.inf
|
||||
echo "Title=Keyman Developer ${KEYMAN_VERSION_WITH_TAG}" >>setup.inf
|
||||
add_zip_files setup.zip keymandeveloper.msi setup.inf
|
||||
cat "$DEVELOPER_PROGRAM/setup.exe" setup.zip > "keymandeveloper-$KEYMAN_VERSION.exe"
|
||||
wrap-signcode //d "Keyman Developer" "keymandeveloper-$KEYMAN_VERSION.exe"
|
||||
cat "$DEVELOPER_PROGRAM/setup.exe" setup.zip > "keymandeveloper-$KEYMAN_VERSION_FOR_FILENAME.exe"
|
||||
wrap-signcode //d "Keyman Developer" "keymandeveloper-$KEYMAN_VERSION_FOR_FILENAME.exe"
|
||||
|
||||
#
|
||||
# Zip the files we distribute as part of the standalone kmc distro into release\$Version\kmcomp-$Version.zip
|
||||
|
|
@ -251,7 +251,7 @@ function make-kmc-install-zip() {
|
|||
cd "${DEVELOPER_ROOT}/bin"
|
||||
|
||||
# TODO: rename this to keyman-developer-cli-$Version.zip
|
||||
local KMCOMP_ZIP="${DEVELOPER_ROOT}/release/${KEYMAN_VERSION}/kmcomp-${KEYMAN_VERSION}.zip"
|
||||
local KMCOMP_ZIP="${DEVELOPER_ROOT}/release/${KEYMAN_VERSION}/kmcomp-${KEYMAN_VERSION_FOR_FILENAME}.zip"
|
||||
|
||||
add_zip_files "${KMCOMP_ZIP}" -q -r \
|
||||
kmconvert.exe \
|
||||
|
|
|
|||
|
|
@ -99,6 +99,17 @@ the API version number in `CORE_API_VERSION.md`. If the API version
|
|||
numbers in `CORE_API_VERSION.md` and in `libkeymancore.symbols` don't
|
||||
match the API verification will fail.
|
||||
|
||||
## Skipping the API check
|
||||
|
||||
Sometimes we have a PR that intentionally does not change the API version
|
||||
number. To skip the API checks in this case, the trailer
|
||||
|
||||
```text
|
||||
Keyman-Api-Check: skip
|
||||
```
|
||||
|
||||
can be added to the PR description.
|
||||
|
||||
## How this works
|
||||
|
||||
`.github/workflows/api-verification.yml` contains a `Verify API` step
|
||||
|
|
|
|||
|
|
@ -73,6 +73,6 @@ https://help.keyman.com/developer/engine/android/latest-version/
|
|||
| KEYMAN_VERSION_JAVA | 21 |
|
||||
| KEYMAN_VERSION_LANGTAGS | 2025-02-18 |
|
||||
| KEYMAN_VERSION_LANGUAGE_SUBTAG_REGISTRY | 2025-03-10 |
|
||||
| KEYMAN_VERSION_UNICODE | 16.0.0 |
|
||||
| KEYMAN_VERSION_UNICODE | 17.0.0 |
|
||||
|
||||
> ### This file is auto-generated by publish-minimum-versions.sh. Do not modify
|
||||
|
|
|
|||
|
|
@ -29,8 +29,7 @@ fi
|
|||
. $KEYMAN_ROOT/resources/build/history/history-utils.sh #includes the following
|
||||
#. ../resources/build/utils.inc.sh
|
||||
|
||||
BUILD_NUMBER=`cat ../VERSION.md`
|
||||
KEYMAN_TIER=`cat ../TIER.md`
|
||||
BUILD_NUMBER="${KEYMAN_VERSION}"
|
||||
|
||||
KEYMAN_CHANGELOG="changelog-${BUILD_NUMBER}-${KEYMAN_TIER}.txt"
|
||||
CHANGELOG_PATH="upload/$BUILD_NUMBER/$KEYMAN_CHANGELOG"
|
||||
|
|
@ -59,7 +58,7 @@ mv -f "$CHANGELOG_PATH.1" "$CHANGELOG_PATH"
|
|||
# Keyman Engine
|
||||
#
|
||||
|
||||
KMEI_DST_NAME="keyman-engine-ios-${BUILD_NUMBER}.zip"
|
||||
KMEI_DST_NAME="keyman-engine-ios-${KEYMAN_VERSION_FOR_FILENAME}.zip"
|
||||
KMEI_DST="${WORK_DIR}/${UPLOAD_DIR}/${KMEI_DST_NAME}"
|
||||
|
||||
KMEI_FRAMEWORK_BASE="build/Build/Products/Release/"
|
||||
|
|
@ -87,14 +86,14 @@ cd "$WORK_DIR"
|
|||
#
|
||||
|
||||
KEYMANAPP_IPA="build/Build/Products/Release-iphoneos/Keyman.ipa"
|
||||
KEYMANAPP_IPA_DST="keyman-ios-${BUILD_NUMBER}.ipa"
|
||||
KEYMANAPP_IPA_DST="keyman-ios-${KEYMAN_VERSION_FOR_FILENAME}.ipa"
|
||||
|
||||
echo "Copying Keyman IPA ${KEYMANAPP_IPA} => ${UPLOAD_DIR}/${KEYMANAPP_IPA_DST}..."
|
||||
cp "${KEYMANAPP_IPA}" "${WORK_DIR}/${UPLOAD_DIR}/${KEYMANAPP_IPA_DST}"
|
||||
|
||||
KEYMANAPP_SIM_FOLDER="build/Build/Products/Release-iphonesimulator"
|
||||
KEYMANAPP_SIM_APP="$KEYMANAPP_SIM_FOLDER/Keyman.app"
|
||||
KEYMANAPP_SIM_APP_DST="keyman-ios-simulator-${BUILD_NUMBER}.app.zip"
|
||||
KEYMANAPP_SIM_APP_DST="keyman-ios-simulator-${KEYMAN_VERSION_FOR_FILENAME}.app.zip"
|
||||
|
||||
echo "Zipping Keyman simulator artifact ${KEYMANAPP_SIM_APP} => ${UPLOAD_DIR}/${KEYMANAPP_SIM_APP_DST}..."
|
||||
cd "${KEYMANAPP_SIM_FOLDER}"
|
||||
|
|
@ -108,14 +107,14 @@ cd "$WORK_DIR"
|
|||
|
||||
if [ "${RELEASE_OEM_FIRSTVOICES}" = true ]; then
|
||||
FIRSTVOICESAPP_IPA="../oem/firstvoices/ios/build/Build/Products/Release-iphoneos/FirstVoices.ipa"
|
||||
FIRSTVOICESAPP_IPA_DST="firstvoices-ios-${BUILD_NUMBER}.ipa"
|
||||
FIRSTVOICESAPP_IPA_DST="firstvoices-ios-${KEYMAN_VERSION_FOR_FILENAME}.ipa"
|
||||
|
||||
echo "Copying FirstVoices IPA ${FIRSTVOICESAPP_IPA} => ${UPLOAD_DIR}/${FIRSTVOICESAPP_IPA_DST}..."
|
||||
cp "${FIRSTVOICESAPP_IPA}" "${WORK_DIR}/${UPLOAD_DIR}/${FIRSTVOICESAPP_IPA_DST}"
|
||||
|
||||
FIRSTVOICESAPP_SIM_FOLDER="../oem/firstvoices/ios/build/Build/Products/Release-iphonesimulator/"
|
||||
FIRSTVOICESAPP_SIM_APP="$FIRSTVOICESAPP_SIM_FOLDER/FirstVoices.app"
|
||||
FIRSTVOICESAPP_SIM_APP_DST="firstvoices-ios-simulator-${BUILD_NUMBER}.app.zip"
|
||||
FIRSTVOICESAPP_SIM_APP_DST="firstvoices-ios-simulator-${KEYMAN_VERSION_FOR_FILENAME}.app.zip"
|
||||
|
||||
echo "Zipping FirstVoices simulator artifact ${FIRSTVOICESAPP_SIM_APP} => ${UPLOAD_DIR}/${KEYMANAPP_SIM_APP_DST}..."
|
||||
cd "${FIRSTVOICESAPP_SIM_FOLDER}"
|
||||
|
|
|
|||
|
|
@ -1,49 +0,0 @@
|
|||
#!/usr/bin/make
|
||||
|
||||
default: # builds only
|
||||
BUILDONLY="yes" ./scripts/build.sh
|
||||
|
||||
clean:
|
||||
rm -rf build-*
|
||||
|
||||
reconf: clean
|
||||
./scripts/reconf.sh
|
||||
|
||||
configure:
|
||||
CONFIGUREONLY="yes" ./scripts/build.sh
|
||||
|
||||
fullbuild: # configure and build
|
||||
./scripts/build.sh
|
||||
|
||||
tmpinstall: reconf
|
||||
INSTALLDIR="/tmp/keyman" ./scripts/build.sh
|
||||
INSTALLDIR="/tmp/keyman" ./scripts/install.sh
|
||||
|
||||
install: # run as sudo
|
||||
SUDOINSTALL="yes" ./scripts/install.sh
|
||||
|
||||
uninstall: # run as sudo
|
||||
SUDOINSTALL="uninstall" ./scripts/install.sh
|
||||
|
||||
sources:
|
||||
./scripts/dist.sh
|
||||
|
||||
tmpsources:
|
||||
PKG_CONFIG_PATH="../../core/build/arch/release/meson-private" ./scripts/dist.sh
|
||||
|
||||
origdist:
|
||||
./scripts/dist.sh origdist
|
||||
|
||||
sourcepackage: reconf origdist
|
||||
./scripts/deb.sh
|
||||
|
||||
nightlydist: reconf sources
|
||||
echo "Built nightly source release in dist/"
|
||||
|
||||
check:
|
||||
cd keyman-config && ./run-tests.sh
|
||||
cd ibus-keyman && ./build.sh test
|
||||
|
||||
tmpcheck: check
|
||||
|
||||
tests: check
|
||||
|
|
@ -178,9 +178,9 @@ class InstallKmp():
|
|||
logging.info("Converting %s to LDML and installing both as as keyman file",
|
||||
f['name'])
|
||||
name, ext = os.path.splitext(f['name'])
|
||||
ldml = convert_kvk_to_ldml(name, fpath)
|
||||
ldmlfile = os.path.join(self.packageDir, f"{name}.ldml")
|
||||
output_ldml(ldmlfile, ldml)
|
||||
if ldml := convert_kvk_to_ldml(name, fpath):
|
||||
ldmlfile = os.path.join(self.packageDir, f"{name}.ldml")
|
||||
output_ldml(ldmlfile, ldml)
|
||||
elif ftype == KMFileTypes.KM_ICON:
|
||||
# Special handling of icon to convert to PNG
|
||||
logging.info("Converting %s to PNG and installing both as keyman files",
|
||||
|
|
|
|||
|
|
@ -366,14 +366,17 @@ def convert_ldml(keyboardName, kvkData, kmpJsonFilename):
|
|||
|
||||
info, system, options, keyboards, files = parsemetadata(kmpJsonFilename)
|
||||
|
||||
if not keyboards:
|
||||
return None
|
||||
|
||||
ldml = etree.Element("keyboard", locale="zzz-keyman")
|
||||
|
||||
for keyboard in keyboards:
|
||||
if keyboard['id'] != keyboardName:
|
||||
continue
|
||||
if 'oskFont' in keyboard:
|
||||
fontFile = os.path.join(os.path.dirname(kmpJsonFilename), keyboard['oskFont'])
|
||||
font = _fontFacename(fontFile)
|
||||
if font:
|
||||
if font := _fontFacename(fontFile):
|
||||
ldml.set('keymanFacename', font)
|
||||
break
|
||||
|
||||
|
|
|
|||
|
|
@ -8,31 +8,34 @@ import unittest
|
|||
from keyman_config.kvk2ldml import KVKData, NFont, convert_ldml
|
||||
|
||||
class Kvk2LdmlTests(unittest.TestCase):
|
||||
def _createKmpJson(self, packagedir):
|
||||
def _createKmpJson(self, packagedir, add_keyboards=True):
|
||||
kmpJsonFilename = os.path.join(packagedir, 'kmp.json')
|
||||
system = '''"system": {
|
||||
"keymanDeveloperVersion": "18.0",
|
||||
"fileVersion": "7.0"
|
||||
}'''
|
||||
files = '''"files": [ {
|
||||
"name": "khmer_angkor.kmx",
|
||||
"description": "Keyboard Khmer Angkor"
|
||||
}, {
|
||||
"name": "kmp.json",
|
||||
"description": "Package information (JSON)"
|
||||
} ]'''
|
||||
if add_keyboards:
|
||||
keyboards = '''"keyboards": [ {
|
||||
"name": "Khmer Angkor",
|
||||
"id": "khmer_angkor",
|
||||
"version": "1.5",
|
||||
"oskFont": "keymanweb-osk.ttf",
|
||||
"languages": [ {
|
||||
"name": "Central Khmer (Khmer, Cambodia)",
|
||||
"id": "km"
|
||||
} ]}
|
||||
]'''
|
||||
else:
|
||||
keyboards = ''
|
||||
with open(kmpJsonFilename, 'w') as file:
|
||||
file.write('''{
|
||||
"system": {
|
||||
"keymanDeveloperVersion": "18.0",
|
||||
"fileVersion": "7.0"
|
||||
},
|
||||
"files": [ {
|
||||
"name": "khmer_angkor.kmx",
|
||||
"description": "Keyboard Khmer Angkor"
|
||||
}, {
|
||||
"name": "kmp.json",
|
||||
"description": "Package information (JSON)"
|
||||
} ],
|
||||
"keyboards": [ {
|
||||
"name": "Khmer Angkor",
|
||||
"id": "khmer_angkor",
|
||||
"version": "1.5",
|
||||
"oskFont": "keymanweb-osk.ttf",
|
||||
"languages": [ {
|
||||
"name": "Central Khmer (Khmer, Cambodia)",
|
||||
"id": "km"
|
||||
} ]}
|
||||
]}''')
|
||||
file.write(f'{{ {system}, {files}, {keyboards} }}')
|
||||
return kmpJsonFilename
|
||||
|
||||
def test_convert_ldml__adds_keymanFacename(self):
|
||||
|
|
@ -56,3 +59,20 @@ class Kvk2LdmlTests(unittest.TestCase):
|
|||
self.assertEqual(ldml.get('keymanFacename'), 'SymChar')
|
||||
|
||||
workdir.cleanup()
|
||||
|
||||
def test_convert_ldml__no_crash_without_keyboards(self):
|
||||
# Setup
|
||||
keyboardName = 'khmer_angkor'
|
||||
kvkData = KVKData()
|
||||
kvkData.AssociatedKeyboard = keyboardName
|
||||
|
||||
workdir = tempfile.TemporaryDirectory()
|
||||
kmpJsonFilename = self._createKmpJson(workdir.name, add_keyboards=False)
|
||||
|
||||
# Execute
|
||||
ldml = convert_ldml(keyboardName, kvkData, kmpJsonFilename)
|
||||
|
||||
# Verify
|
||||
self.assertIsNone(ldml)
|
||||
|
||||
workdir.cleanup()
|
||||
|
|
|
|||
|
|
@ -212,7 +212,7 @@ if (( DETACH_SUCCESS < 999 )); then
|
|||
fi
|
||||
|
||||
# Step 5 - Convert image to a compressed readonly DMG image
|
||||
DMG_FILE_PATH="$DEST_DIR/keyman-$KEYMAN_VERSION.dmg"
|
||||
DMG_FILE_PATH="$DEST_DIR/keyman-$KEYMAN_VERSION_FOR_FILENAME.dmg"
|
||||
builder_echo info "Converting/compressing image to create \"$DMG_FILE_PATH\""
|
||||
if [[ -e "$DMG_FILE_PATH" ]] ; then
|
||||
if [[ "$VERBOSITY" != "-quiet" ]] ; then
|
||||
|
|
|
|||
|
|
@ -293,7 +293,7 @@ do_publish() {
|
|||
"${KM4MIM_BASE_PATH}/make-km-dmg.sh"
|
||||
|
||||
local UPLOAD_PATH="${KM4MIM_BASE_PATH}/output/upload/${KEYMAN_VERSION}"
|
||||
write_download_info "${UPLOAD_PATH}" "keyman-${KEYMAN_VERSION}.dmg" "Keyman4MacIM" dmg mac
|
||||
write_download_info "${UPLOAD_PATH}" "keyman-${KEYMAN_VERSION_FOR_FILENAME}.dmg" "Keyman4MacIM" dmg mac
|
||||
|
||||
if builder_is_ci_build && builder_is_ci_build_level_release; then
|
||||
do_sentry
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ if builder_is_debug_build; then
|
|||
TEST_FLAGS="-x assembleDebug lintDebug testDebug"
|
||||
fi
|
||||
|
||||
ARTIFACT="firstvoices-$KEYMAN_VERSION.apk"
|
||||
ARTIFACT="firstvoices-${KEYMAN_VERSION_FOR_FILENAME}.apk"
|
||||
|
||||
KEYBOARD_PACKAGE_ID="fv_all"
|
||||
KEYBOARDS_TARGET="oem/firstvoices/android/app/src/main/assets/${KEYBOARD_PACKAGE_ID}.kmp"
|
||||
|
|
@ -76,6 +76,8 @@ if builder_start_action build; then
|
|||
echo "BUILD_FLAGS: $BUILD_FLAGS"
|
||||
./gradlew $DAEMON_FLAG clean $BUILD_FLAGS
|
||||
|
||||
mv "${KEYMAN_ROOT}/oem/firstvoices/android/app/build/outputs/apk/$CONFIG/firstvoices-${KEYMAN_VERSION}.apk" "${KEYMAN_ROOT}/oem/firstvoices/android/app/build/outputs/apk/$CONFIG/${ARTIFACT}"
|
||||
|
||||
builder_finish_action success build
|
||||
fi
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ builder_describe "Installation files for FirstVoices Keyboards" \
|
|||
# after all other builds complete
|
||||
|
||||
builder_if_release_build_level builder_describe_outputs \
|
||||
publish /windows/release/${KEYMAN_VERSION}/firstvoices-${KEYMAN_VERSION}.exe
|
||||
publish /windows/release/${KEYMAN_VERSION}/firstvoices-${KEYMAN_VERSION_FOR_FILENAME}.exe
|
||||
|
||||
builder_parse "$@"
|
||||
|
||||
|
|
@ -103,7 +103,7 @@ function copy-installer() {
|
|||
|
||||
mkdir -p "$KEYMAN_ROOT/windows/release/${KEYMAN_VERSION}"
|
||||
cp firstvoices.msi "$KEYMAN_ROOT/windows/release/${KEYMAN_VERSION}/firstvoices.msi"
|
||||
cp firstvoices.exe "$KEYMAN_ROOT/windows/release/${KEYMAN_VERSION}/firstvoices-${KEYMAN_VERSION}.exe"
|
||||
cp firstvoices.exe "$KEYMAN_ROOT/windows/release/${KEYMAN_VERSION}/firstvoices-${KEYMAN_VERSION_FOR_FILENAME}.exe"
|
||||
|
||||
verify-installer-signatures
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
# KEYMAN_VERSION_GIT_TAG: Git tag for the release, "release@$KEYMAN_VERSION_WITH_TAG", e.g. "release@14.0.1-alpha-test-1234"
|
||||
# KEYMAN_ROOT: fully resolved root path of Keyman repository
|
||||
# KEYMAN_VERSION_ENVIRONMENT: One of: local, test, alpha, beta, stable
|
||||
# KEYMAN_VERSION_FOR_FILENAME: KEYMAN_VERSION, for release builds, or KEYMAN_VERSION_WITH_TAG, for PR and local builds; see #10521
|
||||
# UPLOAD_SENTRY: true - if KEYMAN_VERSION_ENVIRONMENT is one of alpha, beta, stable
|
||||
# false - if local, test. Indicates if debug artifacts should be uploaded to Sentry
|
||||
# BUILDER_OS: win|mac|linux -- current build environment
|
||||
|
|
@ -115,6 +116,16 @@ function _builder_basic_find_version() {
|
|||
KEYMAN_VERSION_WITH_TAG="$KEYMAN_VERSION$KEYMAN_VERSION_TAG"
|
||||
KEYMAN_VERSION_GIT_TAG="release@$KEYMAN_VERSION_WITH_TAG"
|
||||
|
||||
# For local builds, and for PR builds, we will use a filename including the tag
|
||||
# but for release builds, we omit the tag for now. In the future, we may include
|
||||
# the tag but that involves changing a number of other websites as dealing with
|
||||
# the rename there too.
|
||||
if builder_is_ci_release_build; then
|
||||
KEYMAN_VERSION_FOR_FILENAME="${KEYMAN_VERSION}"
|
||||
else
|
||||
KEYMAN_VERSION_FOR_FILENAME="${KEYMAN_VERSION_WITH_TAG}"
|
||||
fi
|
||||
|
||||
readonly KEYMAN_VERSION
|
||||
readonly KEYMAN_VERSION_MAJOR
|
||||
readonly KEYMAN_VERSION_MINOR
|
||||
|
|
@ -125,6 +136,7 @@ function _builder_basic_find_version() {
|
|||
readonly KEYMAN_VERSION_WITH_TAG
|
||||
readonly KEYMAN_VERSION_ENVIRONMENT
|
||||
readonly KEYMAN_VERSION_GIT_TAG
|
||||
readonly KEYMAN_VERSION_FOR_FILENAME
|
||||
|
||||
# Export version strings so places like version.gradle can access them
|
||||
export KEYMAN_VERSION
|
||||
|
|
@ -137,6 +149,7 @@ function _builder_basic_find_version() {
|
|||
export KEYMAN_VERSION_WITH_TAG
|
||||
export KEYMAN_VERSION_ENVIRONMENT
|
||||
export KEYMAN_VERSION_GIT_TAG
|
||||
export KEYMAN_VERSION_FOR_FILENAME
|
||||
}
|
||||
|
||||
function _builder_basic_find_tier() {
|
||||
|
|
@ -163,18 +176,19 @@ function _builder_basic_print_build_number_for_teamcity() {
|
|||
}
|
||||
|
||||
function _builder_basic_print_version_utils_debug() {
|
||||
echo "KEYMAN_ROOT: $KEYMAN_ROOT"
|
||||
echo "KEYMAN_VERSION: $KEYMAN_VERSION"
|
||||
echo "KEYMAN_VERSION_WIN: $KEYMAN_VERSION_WIN"
|
||||
echo "KEYMAN_VERSION_RELEASE: $KEYMAN_VERSION_RELEASE"
|
||||
echo "KEYMAN_VERSION_MAJOR: $KEYMAN_VERSION_MAJOR"
|
||||
echo "KEYMAN_VERSION_MINOR: $KEYMAN_VERSION_MINOR"
|
||||
echo "KEYMAN_VERSION_PATCH: $KEYMAN_VERSION_PATCH"
|
||||
echo "KEYMAN_TIER: $KEYMAN_TIER"
|
||||
echo "KEYMAN_VERSION_TAG: $KEYMAN_VERSION_TAG"
|
||||
echo "KEYMAN_VERSION_WITH_TAG: $KEYMAN_VERSION_WITH_TAG"
|
||||
echo "KEYMAN_VERSION_GIT_TAG: $KEYMAN_VERSION_GIT_TAG"
|
||||
echo "KEYMAN_VERSION_ENVIRONMENT: $KEYMAN_VERSION_ENVIRONMENT"
|
||||
echo "KEYMAN_ROOT: $KEYMAN_ROOT"
|
||||
echo "KEYMAN_VERSION: $KEYMAN_VERSION"
|
||||
echo "KEYMAN_VERSION_WIN: $KEYMAN_VERSION_WIN"
|
||||
echo "KEYMAN_VERSION_RELEASE: $KEYMAN_VERSION_RELEASE"
|
||||
echo "KEYMAN_VERSION_MAJOR: $KEYMAN_VERSION_MAJOR"
|
||||
echo "KEYMAN_VERSION_MINOR: $KEYMAN_VERSION_MINOR"
|
||||
echo "KEYMAN_VERSION_PATCH: $KEYMAN_VERSION_PATCH"
|
||||
echo "KEYMAN_TIER: $KEYMAN_TIER"
|
||||
echo "KEYMAN_VERSION_TAG: $KEYMAN_VERSION_TAG"
|
||||
echo "KEYMAN_VERSION_WITH_TAG: $KEYMAN_VERSION_WITH_TAG"
|
||||
echo "KEYMAN_VERSION_GIT_TAG: $KEYMAN_VERSION_GIT_TAG"
|
||||
echo "KEYMAN_VERSION_ENVIRONMENT: $KEYMAN_VERSION_ENVIRONMENT"
|
||||
echo "KEYMAN_VERSION_FOR_FILENAME: $KEYMAN_VERSION_FOR_FILENAME"
|
||||
}
|
||||
|
||||
# TODO: consolidate with buildLevel, see #14285
|
||||
|
|
@ -209,6 +223,7 @@ replaceVersionStrings() {
|
|||
s/\$KEYMAN_VERSION_GIT_TAG/$KEYMAN_VERSION_GIT_TAG/g;
|
||||
s/\$KEYMAN_VERSION_ENVIRONMENT/$KEYMAN_VERSION_ENVIRONMENT/g;
|
||||
s/\$KEYMAN_VERSION/$KEYMAN_VERSION/g;
|
||||
s/\$KEYMAN_VERSION_FOR_FILENAME/$KEYMAN_VERSION_FOR_FILENAME/g;
|
||||
" "$infile" > "$outfile"
|
||||
}
|
||||
|
||||
|
|
@ -249,6 +264,7 @@ replaceVersionStrings_Mkver() {
|
|||
s/\$KEYMAN_VERSION_WITH_TAG/$KEYMAN_VERSION_WITH_TAG/g;
|
||||
s/\$KEYMAN_VERSION_GIT_TAG/$KEYMAN_VERSION_GIT_TAG/g;
|
||||
s/\$KEYMAN_VERSION_ENVIRONMENT/$KEYMAN_VERSION_ENVIRONMENT/g;
|
||||
s/\$KEYMAN_VERSION_FOR_FILENAME/$KEYMAN_VERSION_FOR_FILENAME/g;
|
||||
|
||||
s/\$KEYMAN_VERSION/$KEYMAN_VERSION_WIN/g;
|
||||
|
||||
|
|
|
|||
|
|
@ -39,6 +39,34 @@ function test_bot_check_pr_body() {
|
|||
fi
|
||||
}
|
||||
|
||||
#
|
||||
# Check the Keyman-Api-Check command whether or not to run API checks.
|
||||
# Any value other than 'skip' or no Keyman-Api-Check command will run
|
||||
# the API checks.
|
||||
#
|
||||
# Parameters:
|
||||
# 1: PR number (not currently used)
|
||||
# 2: PR JSON data from api.github.com/repos/keymanapp/keyman/pulls/#
|
||||
#
|
||||
function is_skip_keyman_api_check() {
|
||||
local PRNUM=$1
|
||||
local prinfo="$2"
|
||||
local prbody prApiCheck
|
||||
|
||||
set -o noglob
|
||||
IFS=$'\n'
|
||||
prbody="$(echo "${prinfo}" | "${JQ}" -r '.body')"
|
||||
prApiCheck="$(echo -e "${prbody}" | grep '^Keyman-Api-Check:' | cut -d: -f 2 - | tr -d '[:space:]')"
|
||||
unset IFS
|
||||
set +o noglob
|
||||
|
||||
if [[ "${prApiCheck}" == "skip" ]]; then
|
||||
echo "true"
|
||||
else
|
||||
echo "false"
|
||||
fi
|
||||
}
|
||||
|
||||
#
|
||||
# Check PR commit messages for Build-bot commands. Later commands override
|
||||
# earlier ones. Also checks PR body for any overriding commands. Note, only
|
||||
|
|
|
|||
|
|
@ -84,31 +84,34 @@ function triggerTeamCityBuild() {
|
|||
# 2: 'skip' - don't run build; 'build' - run build and unit tests; 'test' - run build, unit tests, and deploy
|
||||
# 3: Action name
|
||||
# 4: branch name in git
|
||||
# 5: 'true' to skip API checks, 'false' to run them (optional, default 'false')
|
||||
#
|
||||
function triggerGitHubActionsBuild() {
|
||||
local IS_TEST_BUILD="$1"
|
||||
local BUILD_LEVEL="$2"
|
||||
local GITHUB_ACTION="$3"
|
||||
local GIT_BRANCH="$4"
|
||||
local SKIP_API_CHECK="${5:-"false"}"
|
||||
local GIT_BASE_BRANCH="${GIT_BRANCH}"
|
||||
local GIT_USER="keyman-server"
|
||||
local GIT_BUILD_SHA GIT_BASE_REF JSON
|
||||
|
||||
local GITHUB_SERVER=https://api.github.com/repos/keymanapp/keyman
|
||||
|
||||
if [ "${action:-""}" == "commit" ]; then
|
||||
if [[ "${action:-""}" == "commit" ]]; then
|
||||
# This will only be true if we created and pushed a tag
|
||||
GIT_BUILD_SHA="$(git rev-parse "refs/tags/release@$KEYMAN_VERSION_WITH_TAG")"
|
||||
GIT_BUILD_SHA="$(git rev-parse "refs/tags/release@${KEYMAN_VERSION_WITH_TAG}")"
|
||||
GIT_BASE_REF="$(git rev-parse "${GIT_BUILD_SHA}^")"
|
||||
GIT_EVENT_TYPE="${GITHUB_ACTION}: release@${KEYMAN_VERSION_WITH_TAG}"
|
||||
elif [[ $GIT_BRANCH =~ ^[0-9]+$ ]]; then
|
||||
elif [[ ${GIT_BRANCH} =~ ^[0-9]+$ ]]; then
|
||||
# pull request
|
||||
local JSON=$(call_curl "${GITHUB_SERVER}/pulls/${GIT_BRANCH}" --header "Authorization: token $GITHUB_TOKEN")
|
||||
GIT_BUILD_SHA="$(echo "$JSON" | $JQ -r '.head.sha')"
|
||||
local JSON
|
||||
JSON=$(call_curl "${GITHUB_SERVER}/pulls/${GIT_BRANCH}" --header "Authorization: token ${GITHUB_TOKEN}")
|
||||
GIT_BUILD_SHA="$(echo "${JSON}" | ${JQ} -r '.head.sha')"
|
||||
GIT_EVENT_TYPE="${GITHUB_ACTION}: PR #${GIT_BRANCH}"
|
||||
GIT_USER="$(echo "$JSON" | $JQ -r '.user.login')"
|
||||
GIT_BASE_BRANCH="$(echo "$JSON" | $JQ -r '.base.ref')"
|
||||
GIT_BASE_REF="$(echo "$JSON" | $JQ -r '.base.sha')"
|
||||
GIT_USER="$(echo "${JSON}" | ${JQ} -r '.user.login')"
|
||||
GIT_BASE_BRANCH="$(echo "${JSON}" | ${JQ} -r '.base.ref')"
|
||||
GIT_BASE_REF="$(echo "${JSON}" | ${JQ} -r '.base.sha')"
|
||||
GIT_BRANCH="PR-${GIT_BRANCH}"
|
||||
else
|
||||
# another branch: stable-x.y, beta, or master
|
||||
|
|
@ -118,20 +121,21 @@ function triggerGitHubActionsBuild() {
|
|||
fi
|
||||
|
||||
local DATA="{
|
||||
\"event_type\": \"$GIT_EVENT_TYPE\", \
|
||||
\"event_type\": \"${GIT_EVENT_TYPE}\", \
|
||||
\"client_payload\": { \
|
||||
\"buildSha\": \"$GIT_BUILD_SHA\", \
|
||||
\"branch\": \"$GIT_BRANCH\", \
|
||||
\"baseBranch\": \"$GIT_BASE_BRANCH\", \
|
||||
\"baseRef\": \"$GIT_BASE_REF\", \
|
||||
\"user\": \"$GIT_USER\", \
|
||||
\"isTestBuild\": \"$IS_TEST_BUILD\", \
|
||||
\"buildLevel\": \"$BUILD_LEVEL\" \
|
||||
\"buildSha\": \"${GIT_BUILD_SHA}\", \
|
||||
\"branch\": \"${GIT_BRANCH}\", \
|
||||
\"baseBranch\": \"${GIT_BASE_BRANCH}\", \
|
||||
\"baseRef\": \"${GIT_BASE_REF}\", \
|
||||
\"user\": \"${GIT_USER}\", \
|
||||
\"isTestBuild\": \"${IS_TEST_BUILD}\", \
|
||||
\"buildLevel\": \"${BUILD_LEVEL}\", \
|
||||
\"skipApiCheck\": \"${SKIP_API_CHECK}\" \
|
||||
}}"
|
||||
|
||||
echo "GitHub Action Data: $DATA"
|
||||
echo "GitHub Action Data: ${DATA}"
|
||||
|
||||
if [[ "$GIT_BUILD_SHA" == null ]]; then
|
||||
if [[ "${GIT_BUILD_SHA}" == null ]]; then
|
||||
echo "Invalid GIT_BUILD_SHA"
|
||||
exit 1
|
||||
fi
|
||||
|
|
@ -141,8 +145,8 @@ function triggerGitHubActionsBuild() {
|
|||
call_curl "${GITHUB_SERVER}/dispatches" \
|
||||
--request POST \
|
||||
--header "Accept: application/vnd.github+json" \
|
||||
--header "Authorization: token $GITHUB_TOKEN" \
|
||||
--data "$DATA"
|
||||
--header "Authorization: token ${GITHUB_TOKEN}" \
|
||||
--data "${DATA}"
|
||||
echo
|
||||
}
|
||||
|
||||
|
|
@ -157,31 +161,32 @@ function call_curl() {
|
|||
|
||||
local curl_result
|
||||
local http_code
|
||||
local output_file=$(mktemp)
|
||||
local output_file
|
||||
output_file=$(mktemp)
|
||||
|
||||
set +e
|
||||
if [[ $# -gt 0 ]]; then
|
||||
http_code=$(curl --silent --output $output_file --no-progress-meter --write-out "%{http_code}" "$@" "$url")
|
||||
http_code=$(curl --silent --output "${output_file}" --no-progress-meter --write-out "%{http_code}" "$@" "${url}")
|
||||
else
|
||||
http_code=$(curl --silent --output $output_file --no-progress-meter --write-out "%{http_code}" "$url")
|
||||
http_code=$(curl --silent --output "${output_file}" --no-progress-meter --write-out "%{http_code}" "${url}")
|
||||
fi
|
||||
curl_result=$?
|
||||
if [[ ${curl_result} != 0 ]]; then
|
||||
echo "curl call to '${url}' failed with code '${curl_result}'" >& 2
|
||||
>&2 cat $output_file
|
||||
rm -f $output_file
|
||||
exit $curl_result
|
||||
>&2 cat "${output_file}"
|
||||
rm -f "${output_file}"
|
||||
exit ${curl_result}
|
||||
fi
|
||||
|
||||
if [[ ${http_code} -lt 200 || ${http_code} -gt 299 ]] ; then
|
||||
echo "curl call to '${url}' failed with HTTP error code '${http_code}'" >& 2
|
||||
>&2 cat $output_file
|
||||
rm -f $output_file
|
||||
>&2 cat "${output_file}"
|
||||
rm -f "${output_file}"
|
||||
exit 22
|
||||
fi
|
||||
|
||||
set -e
|
||||
|
||||
cat $output_file
|
||||
rm -f $output_file
|
||||
cat "${output_file}"
|
||||
rm -f "${output_file}"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -112,7 +112,7 @@ vcs_test=HttpsGithubComKeymanappKeymanPRs
|
|||
|
||||
bc_master_android=(KeymanAndroid_Build)
|
||||
bc_master_ios=(Keyman_iOS_Master)
|
||||
bc_master_linux=(KeymanLinux_Master deb-release-packaging_GitHub)
|
||||
bc_master_linux=(KeymanLinux_Master deb-release-packaging_GitHub build-test-publish-docker_GitHub)
|
||||
bc_master_mac=(KeymanMac_Master)
|
||||
bc_master_windows=(Keyman_Build)
|
||||
bc_master_web=(Keymanweb_Build)
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
# This is a list of minimum, maximum, and specific versions of any external
|
||||
# components or dependencies found in Keyman.
|
||||
#
|
||||
# Original (outdated) reference
|
||||
# Original (outdated) reference
|
||||
# https://docs.google.com/document/d/1Uy3U2YXeA4rCEbUbT7O6QzUGJDZBeViFecL8fjUOLkE/edit?usp=sharing
|
||||
|
||||
# NOTE: After changing any values, you should run publish-minimum-versions.sh.
|
||||
|
|
@ -50,4 +50,4 @@ KEYMAN_VERSION_CLDR=46 # LDML Keyboards version
|
|||
KEYMAN_VERSION_ISO639_3=2024-05-22 # Date of last import
|
||||
KEYMAN_VERSION_LANGTAGS=2025-02-18 # _version value
|
||||
KEYMAN_VERSION_LANGUAGE_SUBTAG_REGISTRY=2025-03-10 # Date from first line of language-subtag-registry
|
||||
KEYMAN_VERSION_UNICODE=16.0.0 # UCD + related data
|
||||
KEYMAN_VERSION_UNICODE=17.0.0 # UCD + related data
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ function do_build() {
|
|||
local YML_PREFIX=$(cat "$YML_PREFIX_FILE")
|
||||
local SCRIPT_CLONE=$(sed -n '/CLONE:START/,/CLONE:END/{//!p}' < "$MJS_FILE")
|
||||
local SCRIPT_SUFFIX=$(sed -n '/CLONE-COMMENTED:START/,/CLONE-COMMENTED:END/{//!p}' < "$MJS_FILE" | sed 's/\/\/ //g')
|
||||
echo -e "# GENERATED FILE - DO NOT EDIT!\n$YML_PREFIX\n$SCRIPT_CLONE\n$SCRIPT_SUFFIX\n" > "$YML_FILE"
|
||||
echo $'# GENERATED FILE - DO NOT EDIT!\n'"$YML_PREFIX"$'\n'"$SCRIPT_CLONE"$'\n'"$SCRIPT_SUFFIX"$'\n' > "$YML_FILE"
|
||||
}
|
||||
|
||||
builder_run_action build do_build
|
||||
|
|
|
|||
|
|
@ -0,0 +1,660 @@
|
|||
[
|
||||
{
|
||||
"id": 50109411782,
|
||||
"name": "Build Outcome",
|
||||
"node_id": "CR_kwDOAY2xT88AAAALqsDxxg",
|
||||
"head_sha": "390a5bc6dba73cd32bc8c7290ac73321f6504deb",
|
||||
"external_id": "",
|
||||
"url": "https://api.github.com/repos/keymanapp/keyman/check-runs/50109411782",
|
||||
"html_url": "https://github.com/keymanapp/keyman/runs/50109411782",
|
||||
"details_url": "https://github.com/keymanapp/keyman/runs/50109411782",
|
||||
"status": "completed",
|
||||
"conclusion": "success",
|
||||
"started_at": "2025-09-11T05:29:44Z",
|
||||
"completed_at": "2025-09-11T05:29:45Z",
|
||||
"output": {
|
||||
"title": "21 checks completed successfully ✅",
|
||||
"summary": "",
|
||||
"text": null,
|
||||
"annotations_count": 0,
|
||||
"annotations_url": "https://api.github.com/repos/keymanapp/keyman/check-runs/50109411782/annotations"
|
||||
},
|
||||
"check_suite": {
|
||||
"id": 45240794914
|
||||
},
|
||||
"app": {
|
||||
"id": 15368,
|
||||
"client_id": "Iv1.05c79e9ad1f6bdfa",
|
||||
"slug": "github-actions",
|
||||
"node_id": "MDM6QXBwMTUzNjg=",
|
||||
"owner": {
|
||||
"login": "github",
|
||||
"id": 9919,
|
||||
"node_id": "MDEyOk9yZ2FuaXphdGlvbjk5MTk=",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/9919?v=4",
|
||||
"gravatar_id": "",
|
||||
"url": "https://api.github.com/users/github",
|
||||
"html_url": "https://github.com/github",
|
||||
"followers_url": "https://api.github.com/users/github/followers",
|
||||
"following_url": "https://api.github.com/users/github/following{/other_user}",
|
||||
"gists_url": "https://api.github.com/users/github/gists{/gist_id}",
|
||||
"starred_url": "https://api.github.com/users/github/starred{/owner}{/repo}",
|
||||
"subscriptions_url": "https://api.github.com/users/github/subscriptions",
|
||||
"organizations_url": "https://api.github.com/users/github/orgs",
|
||||
"repos_url": "https://api.github.com/users/github/repos",
|
||||
"events_url": "https://api.github.com/users/github/events{/privacy}",
|
||||
"received_events_url": "https://api.github.com/users/github/received_events",
|
||||
"type": "Organization",
|
||||
"user_view_type": "public",
|
||||
"site_admin": false
|
||||
},
|
||||
"name": "GitHub Actions",
|
||||
"description": "Automate your workflow from idea to production",
|
||||
"external_url": "https://help.github.com/en/actions",
|
||||
"html_url": "https://github.com/apps/github-actions",
|
||||
"created_at": "2018-07-30T09:30:17Z",
|
||||
"updated_at": "2025-03-07T16:35:00Z",
|
||||
"permissions": {
|
||||
"actions": "write",
|
||||
"administration": "read",
|
||||
"attestations": "write",
|
||||
"checks": "write",
|
||||
"contents": "write",
|
||||
"deployments": "write",
|
||||
"discussions": "write",
|
||||
"issues": "write",
|
||||
"merge_queues": "write",
|
||||
"metadata": "read",
|
||||
"models": "read",
|
||||
"packages": "write",
|
||||
"pages": "write",
|
||||
"pull_requests": "write",
|
||||
"repository_hooks": "write",
|
||||
"repository_projects": "write",
|
||||
"security_events": "write",
|
||||
"statuses": "write",
|
||||
"vulnerability_alerts": "read"
|
||||
},
|
||||
"events": [
|
||||
"branch_protection_rule",
|
||||
"check_run",
|
||||
"check_suite",
|
||||
"create",
|
||||
"delete",
|
||||
"deployment",
|
||||
"deployment_status",
|
||||
"discussion",
|
||||
"discussion_comment",
|
||||
"fork",
|
||||
"gollum",
|
||||
"issues",
|
||||
"issue_comment",
|
||||
"label",
|
||||
"merge_group",
|
||||
"milestone",
|
||||
"page_build",
|
||||
"project",
|
||||
"project_card",
|
||||
"project_column",
|
||||
"public",
|
||||
"pull_request",
|
||||
"pull_request_review",
|
||||
"pull_request_review_comment",
|
||||
"push",
|
||||
"registry_package",
|
||||
"release",
|
||||
"repository",
|
||||
"repository_dispatch",
|
||||
"status",
|
||||
"watch",
|
||||
"workflow_dispatch",
|
||||
"workflow_run"
|
||||
]
|
||||
},
|
||||
"pull_requests": [
|
||||
{
|
||||
"url": "https://api.github.com/repos/keymanapp/keyman/pulls/14728",
|
||||
"id": 2817549354,
|
||||
"number": 14728,
|
||||
"head": {
|
||||
"ref": "chore/common/unicode-17",
|
||||
"sha": "ebeacc83d0b5cfd7ab523874631e5740721f1f2f",
|
||||
"repo": {
|
||||
"id": 26063183,
|
||||
"url": "https://api.github.com/repos/keymanapp/keyman",
|
||||
"name": "keyman"
|
||||
}
|
||||
},
|
||||
"base": {
|
||||
"ref": "master",
|
||||
"sha": "898cd340a33f29b766b08da66a519be7e3d79fe6",
|
||||
"repo": {
|
||||
"id": 26063183,
|
||||
"url": "https://api.github.com/repos/keymanapp/keyman",
|
||||
"name": "keyman"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 50107239504,
|
||||
"name": "GitGuardian Security Checks",
|
||||
"node_id": "CR_kwDOAY2xT88AAAALqp_MUA",
|
||||
"head_sha": "390a5bc6dba73cd32bc8c7290ac73321f6504deb",
|
||||
"external_id": "",
|
||||
"url": "https://api.github.com/repos/keymanapp/keyman/check-runs/50107239504",
|
||||
"html_url": "https://github.com/keymanapp/keyman/runs/50107239504",
|
||||
"details_url": "https://dashboard.gitguardian.com",
|
||||
"status": "completed",
|
||||
"conclusion": "success",
|
||||
"started_at": "2025-09-11T04:38:47Z",
|
||||
"completed_at": "2025-09-11T04:38:48Z",
|
||||
"output": {
|
||||
"title": "No secrets detected ✅",
|
||||
"summary": "**2** commits were scanned without uncovering any secrets.\n",
|
||||
"text": "Commits scanned: **2**\n\n\n\n- Pull request #14728: `chore/common/unicode-17` 👉 `master`\n \n\n🦉 [GitGuardian](https://dashboard.gitguardian.com/auth/login/?utm_medium=checkruns&utm_source=github&utm_campaign=cr1) detects secrets in your source code to help developers and security teams secure the modern development process. You are seeing this because you or someone else with access to this repository has authorized GitGuardian to scan your pull request.<br/>\n",
|
||||
"annotations_count": 0,
|
||||
"annotations_url": "https://api.github.com/repos/keymanapp/keyman/check-runs/50107239504/annotations"
|
||||
},
|
||||
"check_suite": {
|
||||
"id": 45240794052
|
||||
},
|
||||
"app": {
|
||||
"id": 46505,
|
||||
"client_id": "Iv1.ec3c001966b4cc5a",
|
||||
"slug": "gitguardian",
|
||||
"node_id": "MDM6QXBwNDY1MDU=",
|
||||
"owner": {
|
||||
"login": "GitGuardian",
|
||||
"id": 27360172,
|
||||
"node_id": "MDEyOk9yZ2FuaXphdGlvbjI3MzYwMTcy",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/27360172?v=4",
|
||||
"gravatar_id": "",
|
||||
"url": "https://api.github.com/users/GitGuardian",
|
||||
"html_url": "https://github.com/GitGuardian",
|
||||
"followers_url": "https://api.github.com/users/GitGuardian/followers",
|
||||
"following_url": "https://api.github.com/users/GitGuardian/following{/other_user}",
|
||||
"gists_url": "https://api.github.com/users/GitGuardian/gists{/gist_id}",
|
||||
"starred_url": "https://api.github.com/users/GitGuardian/starred{/owner}{/repo}",
|
||||
"subscriptions_url": "https://api.github.com/users/GitGuardian/subscriptions",
|
||||
"organizations_url": "https://api.github.com/users/GitGuardian/orgs",
|
||||
"repos_url": "https://api.github.com/users/GitGuardian/repos",
|
||||
"events_url": "https://api.github.com/users/GitGuardian/events{/privacy}",
|
||||
"received_events_url": "https://api.github.com/users/GitGuardian/received_events",
|
||||
"type": "Organization",
|
||||
"user_view_type": "public",
|
||||
"site_admin": false
|
||||
},
|
||||
"name": "GitGuardian",
|
||||
"description": "# 🦉 What is GitGuardian?\r\n\r\nGitGuardian Secrets Detection detects and fixes vulnerabilities in source code at every step of the software development lifecycle, covering 350+ types of secrets like API keys, database connection strings, private keys, certificates, and more. The platform’s policy engine enables security teams to monitor and enforce rules across their VCS, DevOps tools, and infrastructure-as-code configurations. Our automated remediation playbooks and collaboration features bring security and development teams together to resolve incidents fast and in full.\r\n\r\n## 1. Scan your codebase for 350+ types of secrets\r\nGitGuardian scans your GitHub repositories and raises alerts only for critical secrets, such as API keys or other credentials. At scale, GitGuardian’s detection algorithm has been battle-tested on over three years of activity in all public GitHub repositories – totaling over 1 billion scanned commits!\r\n\r\n## 2. Quickly remediate your hard-coded secrets\r\nIf you ever experience a leak involving a credential, we have a complete remediation guide used by 100k+ developers each year. We’ll show you how to revoke the secret and remove it from your git history.\r\n\r\n## 3. Prevent secrets from reaching GitHub\r\nInstall ggshield, the GitGuardian CLI, and add secrets detection to your local development workflow using pre-commit and pre-push git hooks integrations.\r\n\r\n# 🙋♂️ FAQ\r\n\r\n**What is your pricing?**\r\nGitGuardian is free for teams under 25 developers and offers a 30-day trial for larger teams.\r\n\r\n**How can I be sure that GitGuardian won’t raise too many false positives?**\r\nWe have scanned billions of commits, sent millions of alerts since 2018, and integrated each feedback to improve our algorithm. Our alerts currently receive 91% “true positive” feedback from developers.\r\n\r\n**My repositories are private; why should I install automated secret detection?**\r\nImagine if there were a plain text file with all your credit card numbers inside, you wouldn’t put this file inside your company’s git repository. Secrets are just as sensitive and should be handled with special care.\r\n\r\n**Is GitGuardian available to be installed on-premise?**\r\nYes, you can contact one of our security specialists to look over the possibility of installing GitGuardian on-premise on your repositories.\r\n\r\n# ⚒️ Installation notes \r\n\r\nYou should install GitGuardian directly through your [GitGuardian](https://dashboard.gitguardian.com/) workspace on the Integration settings page. \r\n\r\nSo that you know, your GitHub organization or GitHub account can only be associated with a single GitGuardian workspace.\r\n\r\n# 👋 Support\r\n\r\nIf you experience any difficulties or have any questions, please reach out to us by email ([support@gitguardian.com](mailto:support@gitguardian.com)).",
|
||||
"external_url": "https://dashboard.gitguardian.com",
|
||||
"html_url": "https://github.com/apps/gitguardian",
|
||||
"created_at": "2019-11-12T15:44:31Z",
|
||||
"updated_at": "2023-07-18T09:06:22Z",
|
||||
"permissions": {
|
||||
"checks": "write",
|
||||
"contents": "read",
|
||||
"emails": "read",
|
||||
"issues": "write",
|
||||
"members": "read",
|
||||
"metadata": "read",
|
||||
"organization_hooks": "write",
|
||||
"pull_requests": "write"
|
||||
},
|
||||
"events": [
|
||||
"check_run",
|
||||
"check_suite",
|
||||
"commit_comment",
|
||||
"create",
|
||||
"delete",
|
||||
"organization",
|
||||
"public",
|
||||
"pull_request",
|
||||
"pull_request_review",
|
||||
"pull_request_review_comment",
|
||||
"push",
|
||||
"repository"
|
||||
]
|
||||
},
|
||||
"pull_requests": [
|
||||
{
|
||||
"url": "https://api.github.com/repos/keymanapp/keyman/pulls/14728",
|
||||
"id": 2817549354,
|
||||
"number": 14728,
|
||||
"head": {
|
||||
"ref": "chore/common/unicode-17",
|
||||
"sha": "ebeacc83d0b5cfd7ab523874631e5740721f1f2f",
|
||||
"repo": {
|
||||
"id": 26063183,
|
||||
"url": "https://api.github.com/repos/keymanapp/keyman",
|
||||
"name": "keyman"
|
||||
}
|
||||
},
|
||||
"base": {
|
||||
"ref": "master",
|
||||
"sha": "898cd340a33f29b766b08da66a519be7e3d79fe6",
|
||||
"repo": {
|
||||
"id": 26063183,
|
||||
"url": "https://api.github.com/repos/keymanapp/keyman",
|
||||
"name": "keyman"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 50107238217,
|
||||
"name": "build",
|
||||
"node_id": "CR_kwDOAY2xT88AAAALqp_HSQ",
|
||||
"head_sha": "390a5bc6dba73cd32bc8c7290ac73321f6504deb",
|
||||
"external_id": "584213e9-9caa-5e7a-be2b-4a4fb7afc574",
|
||||
"url": "https://api.github.com/repos/keymanapp/keyman/check-runs/50107238217",
|
||||
"html_url": "https://github.com/keymanapp/keyman/actions/runs/17634180116/job/50107238217",
|
||||
"details_url": "https://github.com/keymanapp/keyman/actions/runs/17634180116/job/50107238217",
|
||||
"status": "completed",
|
||||
"conclusion": "skipped",
|
||||
"started_at": "2025-09-11T04:38:46Z",
|
||||
"completed_at": "2025-09-11T04:38:45Z",
|
||||
"output": {
|
||||
"title": null,
|
||||
"summary": null,
|
||||
"text": null,
|
||||
"annotations_count": 0,
|
||||
"annotations_url": "https://api.github.com/repos/keymanapp/keyman/check-runs/50107238217/annotations"
|
||||
},
|
||||
"check_suite": {
|
||||
"id": 45240899113
|
||||
},
|
||||
"app": {
|
||||
"id": 15368,
|
||||
"client_id": "Iv1.05c79e9ad1f6bdfa",
|
||||
"slug": "github-actions",
|
||||
"node_id": "MDM6QXBwMTUzNjg=",
|
||||
"owner": {
|
||||
"login": "github",
|
||||
"id": 9919,
|
||||
"node_id": "MDEyOk9yZ2FuaXphdGlvbjk5MTk=",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/9919?v=4",
|
||||
"gravatar_id": "",
|
||||
"url": "https://api.github.com/users/github",
|
||||
"html_url": "https://github.com/github",
|
||||
"followers_url": "https://api.github.com/users/github/followers",
|
||||
"following_url": "https://api.github.com/users/github/following{/other_user}",
|
||||
"gists_url": "https://api.github.com/users/github/gists{/gist_id}",
|
||||
"starred_url": "https://api.github.com/users/github/starred{/owner}{/repo}",
|
||||
"subscriptions_url": "https://api.github.com/users/github/subscriptions",
|
||||
"organizations_url": "https://api.github.com/users/github/orgs",
|
||||
"repos_url": "https://api.github.com/users/github/repos",
|
||||
"events_url": "https://api.github.com/users/github/events{/privacy}",
|
||||
"received_events_url": "https://api.github.com/users/github/received_events",
|
||||
"type": "Organization",
|
||||
"user_view_type": "public",
|
||||
"site_admin": false
|
||||
},
|
||||
"name": "GitHub Actions",
|
||||
"description": "Automate your workflow from idea to production",
|
||||
"external_url": "https://help.github.com/en/actions",
|
||||
"html_url": "https://github.com/apps/github-actions",
|
||||
"created_at": "2018-07-30T09:30:17Z",
|
||||
"updated_at": "2025-03-07T16:35:00Z",
|
||||
"permissions": {
|
||||
"actions": "write",
|
||||
"administration": "read",
|
||||
"attestations": "write",
|
||||
"checks": "write",
|
||||
"contents": "write",
|
||||
"deployments": "write",
|
||||
"discussions": "write",
|
||||
"issues": "write",
|
||||
"merge_queues": "write",
|
||||
"metadata": "read",
|
||||
"models": "read",
|
||||
"packages": "write",
|
||||
"pages": "write",
|
||||
"pull_requests": "write",
|
||||
"repository_hooks": "write",
|
||||
"repository_projects": "write",
|
||||
"security_events": "write",
|
||||
"statuses": "write",
|
||||
"vulnerability_alerts": "read"
|
||||
},
|
||||
"events": [
|
||||
"branch_protection_rule",
|
||||
"check_run",
|
||||
"check_suite",
|
||||
"create",
|
||||
"delete",
|
||||
"deployment",
|
||||
"deployment_status",
|
||||
"discussion",
|
||||
"discussion_comment",
|
||||
"fork",
|
||||
"gollum",
|
||||
"issues",
|
||||
"issue_comment",
|
||||
"label",
|
||||
"merge_group",
|
||||
"milestone",
|
||||
"page_build",
|
||||
"project",
|
||||
"project_card",
|
||||
"project_column",
|
||||
"public",
|
||||
"pull_request",
|
||||
"pull_request_review",
|
||||
"pull_request_review_comment",
|
||||
"push",
|
||||
"registry_package",
|
||||
"release",
|
||||
"repository",
|
||||
"repository_dispatch",
|
||||
"status",
|
||||
"watch",
|
||||
"workflow_dispatch",
|
||||
"workflow_run"
|
||||
]
|
||||
},
|
||||
"pull_requests": [
|
||||
{
|
||||
"url": "https://api.github.com/repos/keymanapp/keyman/pulls/14728",
|
||||
"id": 2817549354,
|
||||
"number": 14728,
|
||||
"head": {
|
||||
"ref": "chore/common/unicode-17",
|
||||
"sha": "ebeacc83d0b5cfd7ab523874631e5740721f1f2f",
|
||||
"repo": {
|
||||
"id": 26063183,
|
||||
"url": "https://api.github.com/repos/keymanapp/keyman",
|
||||
"name": "keyman"
|
||||
}
|
||||
},
|
||||
"base": {
|
||||
"ref": "master",
|
||||
"sha": "898cd340a33f29b766b08da66a519be7e3d79fe6",
|
||||
"repo": {
|
||||
"id": 26063183,
|
||||
"url": "https://api.github.com/repos/keymanapp/keyman",
|
||||
"name": "keyman"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 50107238052,
|
||||
"name": "triage",
|
||||
"node_id": "CR_kwDOAY2xT88AAAALqp_GpA",
|
||||
"head_sha": "390a5bc6dba73cd32bc8c7290ac73321f6504deb",
|
||||
"external_id": "90e392c4-1805-5238-9d01-622e4d746355",
|
||||
"url": "https://api.github.com/repos/keymanapp/keyman/check-runs/50107238052",
|
||||
"html_url": "https://github.com/keymanapp/keyman/actions/runs/17634180101/job/50107238052",
|
||||
"details_url": "https://github.com/keymanapp/keyman/actions/runs/17634180101/job/50107238052",
|
||||
"status": "completed",
|
||||
"conclusion": "success",
|
||||
"started_at": "2025-09-11T04:38:47Z",
|
||||
"completed_at": "2025-09-11T04:38:52Z",
|
||||
"output": {
|
||||
"title": null,
|
||||
"summary": null,
|
||||
"text": null,
|
||||
"annotations_count": 0,
|
||||
"annotations_url": "https://api.github.com/repos/keymanapp/keyman/check-runs/50107238052/annotations"
|
||||
},
|
||||
"check_suite": {
|
||||
"id": 45240899080
|
||||
},
|
||||
"app": {
|
||||
"id": 15368,
|
||||
"client_id": "Iv1.05c79e9ad1f6bdfa",
|
||||
"slug": "github-actions",
|
||||
"node_id": "MDM6QXBwMTUzNjg=",
|
||||
"owner": {
|
||||
"login": "github",
|
||||
"id": 9919,
|
||||
"node_id": "MDEyOk9yZ2FuaXphdGlvbjk5MTk=",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/9919?v=4",
|
||||
"gravatar_id": "",
|
||||
"url": "https://api.github.com/users/github",
|
||||
"html_url": "https://github.com/github",
|
||||
"followers_url": "https://api.github.com/users/github/followers",
|
||||
"following_url": "https://api.github.com/users/github/following{/other_user}",
|
||||
"gists_url": "https://api.github.com/users/github/gists{/gist_id}",
|
||||
"starred_url": "https://api.github.com/users/github/starred{/owner}{/repo}",
|
||||
"subscriptions_url": "https://api.github.com/users/github/subscriptions",
|
||||
"organizations_url": "https://api.github.com/users/github/orgs",
|
||||
"repos_url": "https://api.github.com/users/github/repos",
|
||||
"events_url": "https://api.github.com/users/github/events{/privacy}",
|
||||
"received_events_url": "https://api.github.com/users/github/received_events",
|
||||
"type": "Organization",
|
||||
"user_view_type": "public",
|
||||
"site_admin": false
|
||||
},
|
||||
"name": "GitHub Actions",
|
||||
"description": "Automate your workflow from idea to production",
|
||||
"external_url": "https://help.github.com/en/actions",
|
||||
"html_url": "https://github.com/apps/github-actions",
|
||||
"created_at": "2018-07-30T09:30:17Z",
|
||||
"updated_at": "2025-03-07T16:35:00Z",
|
||||
"permissions": {
|
||||
"actions": "write",
|
||||
"administration": "read",
|
||||
"attestations": "write",
|
||||
"checks": "write",
|
||||
"contents": "write",
|
||||
"deployments": "write",
|
||||
"discussions": "write",
|
||||
"issues": "write",
|
||||
"merge_queues": "write",
|
||||
"metadata": "read",
|
||||
"models": "read",
|
||||
"packages": "write",
|
||||
"pages": "write",
|
||||
"pull_requests": "write",
|
||||
"repository_hooks": "write",
|
||||
"repository_projects": "write",
|
||||
"security_events": "write",
|
||||
"statuses": "write",
|
||||
"vulnerability_alerts": "read"
|
||||
},
|
||||
"events": [
|
||||
"branch_protection_rule",
|
||||
"check_run",
|
||||
"check_suite",
|
||||
"create",
|
||||
"delete",
|
||||
"deployment",
|
||||
"deployment_status",
|
||||
"discussion",
|
||||
"discussion_comment",
|
||||
"fork",
|
||||
"gollum",
|
||||
"issues",
|
||||
"issue_comment",
|
||||
"label",
|
||||
"merge_group",
|
||||
"milestone",
|
||||
"page_build",
|
||||
"project",
|
||||
"project_card",
|
||||
"project_column",
|
||||
"public",
|
||||
"pull_request",
|
||||
"pull_request_review",
|
||||
"pull_request_review_comment",
|
||||
"push",
|
||||
"registry_package",
|
||||
"release",
|
||||
"repository",
|
||||
"repository_dispatch",
|
||||
"status",
|
||||
"watch",
|
||||
"workflow_dispatch",
|
||||
"workflow_run"
|
||||
]
|
||||
},
|
||||
"pull_requests": [
|
||||
{
|
||||
"url": "https://api.github.com/repos/keymanapp/keyman/pulls/14728",
|
||||
"id": 2817549354,
|
||||
"number": 14728,
|
||||
"head": {
|
||||
"ref": "chore/common/unicode-17",
|
||||
"sha": "ebeacc83d0b5cfd7ab523874631e5740721f1f2f",
|
||||
"repo": {
|
||||
"id": 26063183,
|
||||
"url": "https://api.github.com/repos/keymanapp/keyman",
|
||||
"name": "keyman"
|
||||
}
|
||||
},
|
||||
"base": {
|
||||
"ref": "master",
|
||||
"sha": "898cd340a33f29b766b08da66a519be7e3d79fe6",
|
||||
"repo": {
|
||||
"id": 26063183,
|
||||
"url": "https://api.github.com/repos/keymanapp/keyman",
|
||||
"name": "keyman"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 50107108425,
|
||||
"name": "Summarize build status checks",
|
||||
"node_id": "CR_kwDOAY2xT88AAAALqp3MSQ",
|
||||
"head_sha": "390a5bc6dba73cd32bc8c7290ac73321f6504deb",
|
||||
"external_id": "7e5f7f3d-df60-5a09-9991-ce263cfb45c6",
|
||||
"url": "https://api.github.com/repos/keymanapp/keyman/check-runs/50107108425",
|
||||
"html_url": "https://github.com/keymanapp/keyman/actions/runs/17634132698/job/50107108425",
|
||||
"details_url": "https://github.com/keymanapp/keyman/actions/runs/17634132698/job/50107108425",
|
||||
"status": "completed",
|
||||
"conclusion": "success",
|
||||
"started_at": "2025-09-11T04:35:52Z",
|
||||
"completed_at": "2025-09-11T04:35:55Z",
|
||||
"output": {
|
||||
"title": null,
|
||||
"summary": null,
|
||||
"text": null,
|
||||
"annotations_count": 0,
|
||||
"annotations_url": "https://api.github.com/repos/keymanapp/keyman/check-runs/50107108425/annotations"
|
||||
},
|
||||
"check_suite": {
|
||||
"id": 45240794914
|
||||
},
|
||||
"app": {
|
||||
"id": 15368,
|
||||
"client_id": "Iv1.05c79e9ad1f6bdfa",
|
||||
"slug": "github-actions",
|
||||
"node_id": "MDM6QXBwMTUzNjg=",
|
||||
"owner": {
|
||||
"login": "github",
|
||||
"id": 9919,
|
||||
"node_id": "MDEyOk9yZ2FuaXphdGlvbjk5MTk=",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/9919?v=4",
|
||||
"gravatar_id": "",
|
||||
"url": "https://api.github.com/users/github",
|
||||
"html_url": "https://github.com/github",
|
||||
"followers_url": "https://api.github.com/users/github/followers",
|
||||
"following_url": "https://api.github.com/users/github/following{/other_user}",
|
||||
"gists_url": "https://api.github.com/users/github/gists{/gist_id}",
|
||||
"starred_url": "https://api.github.com/users/github/starred{/owner}{/repo}",
|
||||
"subscriptions_url": "https://api.github.com/users/github/subscriptions",
|
||||
"organizations_url": "https://api.github.com/users/github/orgs",
|
||||
"repos_url": "https://api.github.com/users/github/repos",
|
||||
"events_url": "https://api.github.com/users/github/events{/privacy}",
|
||||
"received_events_url": "https://api.github.com/users/github/received_events",
|
||||
"type": "Organization",
|
||||
"user_view_type": "public",
|
||||
"site_admin": false
|
||||
},
|
||||
"name": "GitHub Actions",
|
||||
"description": "Automate your workflow from idea to production",
|
||||
"external_url": "https://help.github.com/en/actions",
|
||||
"html_url": "https://github.com/apps/github-actions",
|
||||
"created_at": "2018-07-30T09:30:17Z",
|
||||
"updated_at": "2025-03-07T16:35:00Z",
|
||||
"permissions": {
|
||||
"actions": "write",
|
||||
"administration": "read",
|
||||
"attestations": "write",
|
||||
"checks": "write",
|
||||
"contents": "write",
|
||||
"deployments": "write",
|
||||
"discussions": "write",
|
||||
"issues": "write",
|
||||
"merge_queues": "write",
|
||||
"metadata": "read",
|
||||
"models": "read",
|
||||
"packages": "write",
|
||||
"pages": "write",
|
||||
"pull_requests": "write",
|
||||
"repository_hooks": "write",
|
||||
"repository_projects": "write",
|
||||
"security_events": "write",
|
||||
"statuses": "write",
|
||||
"vulnerability_alerts": "read"
|
||||
},
|
||||
"events": [
|
||||
"branch_protection_rule",
|
||||
"check_run",
|
||||
"check_suite",
|
||||
"create",
|
||||
"delete",
|
||||
"deployment",
|
||||
"deployment_status",
|
||||
"discussion",
|
||||
"discussion_comment",
|
||||
"fork",
|
||||
"gollum",
|
||||
"issues",
|
||||
"issue_comment",
|
||||
"label",
|
||||
"merge_group",
|
||||
"milestone",
|
||||
"page_build",
|
||||
"project",
|
||||
"project_card",
|
||||
"project_column",
|
||||
"public",
|
||||
"pull_request",
|
||||
"pull_request_review",
|
||||
"pull_request_review_comment",
|
||||
"push",
|
||||
"registry_package",
|
||||
"release",
|
||||
"repository",
|
||||
"repository_dispatch",
|
||||
"status",
|
||||
"watch",
|
||||
"workflow_dispatch",
|
||||
"workflow_run"
|
||||
]
|
||||
},
|
||||
"pull_requests": [
|
||||
{
|
||||
"url": "https://api.github.com/repos/keymanapp/keyman/pulls/14728",
|
||||
"id": 2817549354,
|
||||
"number": 14728,
|
||||
"head": {
|
||||
"ref": "chore/common/unicode-17",
|
||||
"sha": "ebeacc83d0b5cfd7ab523874631e5740721f1f2f",
|
||||
"repo": {
|
||||
"id": 26063183,
|
||||
"url": "https://api.github.com/repos/keymanapp/keyman",
|
||||
"name": "keyman"
|
||||
}
|
||||
},
|
||||
"base": {
|
||||
"ref": "master",
|
||||
"sha": "898cd340a33f29b766b08da66a519be7e3d79fe6",
|
||||
"repo": {
|
||||
"id": 26063183,
|
||||
"url": "https://api.github.com/repos/keymanapp/keyman",
|
||||
"name": "keyman"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -27,43 +27,61 @@
|
|||
// check/web/file-size
|
||||
//
|
||||
|
||||
function addLog(message) {
|
||||
console.log(message);
|
||||
return message + String.fromCharCode(13);
|
||||
}
|
||||
|
||||
function addStatus(o, type, context, state) {
|
||||
if(!o[context]) {
|
||||
o[context] = {type, state};
|
||||
return addLog(`Found ${context}: ${state}`);
|
||||
} else {
|
||||
return addLog(`Skipping repeated ${context}: ${state}`);
|
||||
}
|
||||
}
|
||||
|
||||
function reduceStatuses(statuses) {
|
||||
let summary = '';
|
||||
const filtered_statuses = statuses.reduce((o, status) => {
|
||||
if(status.creator?.login == 'keyman-server' && status.context.startsWith('Test')) {
|
||||
if(!o[status.context]) o[status.context] = {type: 'build', state: status.state};
|
||||
summary += addStatus(o, 'build', status.context, status.state);
|
||||
} else if(status.creator?.login == 'keymanapp-test-bot[bot]' && status.context == 'user_testing') {
|
||||
if(!o[status.context]) o[status.context] = {type: 'user-test', state: status.state};;
|
||||
summary += addStatus(o, 'user-test', status.context, status.state);
|
||||
} else if(status.context == 'API Verification') {
|
||||
if(!o[status.context]) o[status.context] = {type: 'check', state: status.state};
|
||||
summary += addStatus(o, 'check', status.context, status.state);
|
||||
} else if(status.context == 'Ubuntu Packaging') {
|
||||
if(!o[status.context]) o[status.context] = {type: 'build', state: status.state};
|
||||
summary += addStatus(o, 'build', status.context, status.state);
|
||||
} else if(status.context == 'check/web/file-size') {
|
||||
// Ignore check/web/file-size -- we won't block automerge for this at this point
|
||||
summary += addLog(`Skipping ${status.context}`);
|
||||
} else {
|
||||
// We fail with an 'unknown status' response if we get a new status check
|
||||
// so we can be sure we are not skipping known status checks
|
||||
summary += addLog(`Found unknown ${status.context}: ${status.state}`);
|
||||
o[status.context] = {type: 'unknown', state: status.state};
|
||||
}
|
||||
return o;
|
||||
|
||||
}, {});
|
||||
return filtered_statuses;
|
||||
return { filtered_statuses, summary };
|
||||
}
|
||||
|
||||
//
|
||||
// Given the collection of status checks we care about, return
|
||||
// an aggregate status -- error, failed, pending, or success,
|
||||
// an aggregate status -- error, failure, pending, or success,
|
||||
// and a summary description
|
||||
//
|
||||
function calculateFinalStatus(filtered_statuses) {
|
||||
function calculateFinalStatus(filtered_statuses, summary) {
|
||||
const counts = {};
|
||||
let hasBuilds = false;
|
||||
for(const context of Object.keys(filtered_statuses)) {
|
||||
const { state, type } = filtered_statuses[context];
|
||||
if(type == 'unknown') {
|
||||
// We special-case for unknown status checks, and never permit them
|
||||
console.error(`An unknown context ${context} was found, cannot calculate build status.`);
|
||||
return [
|
||||
'error', `An unknown context ${context} was found, cannot calculate build status.`
|
||||
'error', `An unknown context ${context} was found, cannot calculate build status.`, summary
|
||||
];
|
||||
}
|
||||
if(type == 'build') {
|
||||
|
|
@ -74,12 +92,13 @@
|
|||
|
||||
// If we do not have any statuses yet, we wait
|
||||
if(Object.keys(filtered_statuses).length == 0 || !hasBuilds) {
|
||||
return ['pending', 'Builds have not yet been triggered ⌛'];
|
||||
console.log(`Builds not yet triggered`);
|
||||
return ['pending', 'Builds have not yet been triggered ⌛', summary];
|
||||
}
|
||||
|
||||
const state =
|
||||
counts.error ? 'error' :
|
||||
counts.failed ? 'failed' :
|
||||
counts.failure ? 'failure' :
|
||||
counts.pending ? 'pending' :
|
||||
'success';
|
||||
|
||||
|
|
@ -90,14 +109,16 @@
|
|||
description += `${count} check${count == 1 ? '' : 's'} ${state}`;
|
||||
}
|
||||
appendDescription(counts.error, 'in an error state ❌');
|
||||
appendDescription(counts.failed, 'failed ❌');
|
||||
appendDescription(counts.failure, 'failed ❌');
|
||||
appendDescription(counts.pending, 'pending ⌛');
|
||||
appendDescription(counts.success, 'completed successfully ✅');
|
||||
|
||||
return [ state, description ];
|
||||
console.log(`Finished filtering and reviewing status checks: ${state}: ${description}`);
|
||||
return [ state, description, summary ];
|
||||
}
|
||||
|
||||
async function getCommitStatuses(github, owner, repo, sha) {
|
||||
console.log(`Getting commit statuses for ${sha}`);
|
||||
const statuses = await github.paginate('GET /repos/{owner}/{repo}/commits/{sha}/statuses', {
|
||||
owner,
|
||||
repo,
|
||||
|
|
@ -110,6 +131,7 @@
|
|||
}
|
||||
|
||||
async function getCommitCheckRuns(github, owner, repo, sha) {
|
||||
console.log(`Getting commit check runs for ${sha}`);
|
||||
const statuses = await github.paginate('GET /repos/{owner}/{repo}/commits/{sha}/check-runs', {
|
||||
owner,
|
||||
repo,
|
||||
|
|
@ -123,13 +145,11 @@
|
|||
|
||||
function calculateCheckResult(statuses) {
|
||||
if(!Array.isArray(statuses)) {
|
||||
return ['error', 'Failed to retrieve status checks from GitHub ❌'];
|
||||
return ['error', 'Failed to retrieve status checks from GitHub ❌', 'statuses is not an array'];
|
||||
}
|
||||
|
||||
const filtered_statuses = reduceStatuses(statuses);
|
||||
|
||||
const result = calculateFinalStatus(filtered_statuses);
|
||||
return result;
|
||||
const { filtered_statuses, summary } = reduceStatuses(statuses);
|
||||
return calculateFinalStatus(filtered_statuses, summary);
|
||||
}
|
||||
|
||||
async function test(github, owner, repo, sha) {
|
||||
|
|
@ -149,7 +169,7 @@
|
|||
return check.data.id;
|
||||
}
|
||||
|
||||
async function updateCheck(github, owner, repo, checkRunId, status, description) {
|
||||
async function updateCheck(github, owner, repo, checkRunId, status, description, summary) {
|
||||
const checkStatus = status == 'pending' ? 'in_progress' : 'completed';
|
||||
const conclusion = checkStatus == 'in_progress' ? undefined : (status == 'success' ? 'success' : 'failure');
|
||||
|
||||
|
|
@ -161,7 +181,7 @@
|
|||
conclusion,
|
||||
output: {
|
||||
title: description,
|
||||
summary: ''
|
||||
summary
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -179,7 +199,7 @@
|
|||
|
||||
// const checkRunId = await createCheck(github, owner, repo, sha);
|
||||
// const res = await test(github, owner, repo, sha);
|
||||
// await updateCheck(github, owner, repo, checkRunId, res[0], res[1]);
|
||||
// await updateCheck(github, owner, repo, checkRunId, res[0], res[1], res[2]);
|
||||
|
||||
// CLONE-COMMENTED:END
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import * as fs from 'node:fs';
|
||||
import 'mocha';
|
||||
import { assert } from 'chai';
|
||||
import sinon from 'sinon';
|
||||
|
||||
import { unitTestEndpoints } from './pr-build-status.mjs';
|
||||
|
||||
|
|
@ -9,9 +10,10 @@ import { getOctokit } from '@actions/github';
|
|||
import * as process from 'node:process';
|
||||
|
||||
const commits = {
|
||||
'390a5bc6dba73cd32bc8c7290ac73321f6504deb': [ 'failure', '3 checks failed ❌; 21 checks completed successfully ✅'],
|
||||
'825f7d2df0069fa56a8f2a534b42a49ee1f21ca1': [ 'success', '24 checks completed successfully ✅' ],
|
||||
'870d37f56b489ef5067b4352a06505369d9038e0': [ 'error', '6 checks in an error state ❌; 17 checks completed successfully ✅' ],
|
||||
'11a558e926370253db37026c95b7ff5a6aa1e8fc': [ 'success', '22 checks completed successfully ✅' ],
|
||||
'870d37f56b489ef5067b4352a06505369d9038e0': [ 'error', '6 checks in an error state ❌; 1 check failed ❌; 17 checks completed successfully ✅' ],
|
||||
'11a558e926370253db37026c95b7ff5a6aa1e8fc': [ 'failure', '2 checks failed ❌; 22 checks completed successfully ✅' ],
|
||||
'8fd5ccc9026b85d6a780d8bcf862380e7a89aefb': [ 'pending', 'Builds have not yet been triggered ⌛' ],
|
||||
'153683cfb007c6066c9dcf71d25afa4c66efa17f': [ 'pending', 'Builds have not yet been triggered ⌛' ],
|
||||
};
|
||||
|
|
@ -32,13 +34,23 @@ if(debug) {
|
|||
}
|
||||
|
||||
describe('pr-build-status', function () {
|
||||
beforeEach(() => {
|
||||
// just silencing the logging from pr-build-status bot
|
||||
// in order to make the test results clearer
|
||||
sinon.stub(console, 'log');
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
console.log.restore();
|
||||
});
|
||||
|
||||
for(const sha of Object.keys(commits)) {
|
||||
it(`should return '${commits[sha][1]}' for sha ${sha}`, function () {
|
||||
const json = JSON.parse(fs.readFileSync(`fixtures/${sha}-statuses.json`,'utf-8'));
|
||||
const status = unitTestEndpoints.calculateCheckResult(json);
|
||||
assert.isNotNull(status);
|
||||
assert.isArray(status);
|
||||
assert.deepStrictEqual(status, commits[sha]);
|
||||
assert.deepStrictEqual(status.splice(0, 2), commits[sha]);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ generate_table() {
|
|||
KEYMAN_VERSION | KEYMAN_VERSION_MAJOR | KEYMAN_VERSION_MINOR | \
|
||||
KEYMAN_VERSION_PATCH | KEYMAN_VERSION_RELEASE | KEYMAN_VERSION_WIN | \
|
||||
KEYMAN_VERSION_TAG | KEYMAN_VERSION_WITH_TAG | \
|
||||
KEYMAN_VERSION_ENVIRONMENT | KEYMAN_VERSION_GIT_TAG)
|
||||
KEYMAN_VERSION_ENVIRONMENT | KEYMAN_VERSION_GIT_TAG | KEYMAN_VERSION_FOR_FILENAME)
|
||||
# ignore the variables that contain the Keyman version
|
||||
;;
|
||||
*)
|
||||
|
|
|
|||
|
|
@ -216,7 +216,25 @@ _do_test_test_bot_check_pr_body() {
|
|||
|
||||
#----------------------------------------------------------------------------------------------------
|
||||
|
||||
test_is_skip_keyman_api_check() {
|
||||
builder_echo start test_is_skip_keyman_api_check 'START TEST: test_is_skip_keyman_api_check'
|
||||
result=$(is_skip_keyman_api_check 1 '{ "body": "Keyman-Api-Check: skip" }')
|
||||
assert-equal "${result}" "true" "PR #1: 'Keyman-Api-Check: skip' should return true"
|
||||
result=$(is_skip_keyman_api_check 2 '{ "body": "PR message" }')
|
||||
assert-equal "${result}" "false" "PR #2: omitted 'Keyman-Api-Check' should return false"
|
||||
result=$(is_skip_keyman_api_check 3 '{ "body": "Keyman-Api-Check: invalid" }')
|
||||
assert-equal "${result}" "false" "PR #3: invalid data for 'Keyman-Api-Check' should return false"
|
||||
result=$(is_skip_keyman_api_check 4 '{ "body": "Some message\nKeyman-Api-Check: skip" }')
|
||||
assert-equal "${result}" "true" "PR #4: 'Keyman-Api-Check: skip' at start of line should return true"
|
||||
result=$(is_skip_keyman_api_check 5 '{ "body": "Here Keyman-Api-Check: skip\nis in the middle of the line" }')
|
||||
assert-equal "${result}" "false" "PR #5: 'Keyman-Api-Check: skip' in the middle of the line should return false"
|
||||
builder_echo end test_is_skip_keyman_api_check success 'SUCCESS: test_is_skip_keyman_api_check'
|
||||
}
|
||||
|
||||
#----------------------------------------------------------------------------------------------------
|
||||
|
||||
test_build_bot_verify_platforms
|
||||
test_build_bot_update_commands
|
||||
test_build_bot_check_messages
|
||||
test_test_bot_check_pr_body
|
||||
test_is_skip_keyman_api_check
|
||||
|
|
|
|||
|
|
@ -107,3 +107,38 @@ Running tests locally with the `run.sh` looks like:
|
|||
resources/docker-images/run.sh :web --registry 'myregistry:5678' --username 'user' --password 'password' -- web/build.sh test
|
||||
```
|
||||
|
||||
## Running GitHub Actions locally
|
||||
|
||||
There exist [GitHub actions for building the Docker images](../../.github/workflows/build-test-publish-docker.yml).
|
||||
For testing and developing the workflow can be started locally.
|
||||
As a prerequisite [act](https://nektosact.com/) must be installed.
|
||||
|
||||
This is an exmaple for running the workflow with act:
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
# runs GitHub workflow locally for building, testing and publishing Docker images
|
||||
# requires act (https://nektosact.com/)
|
||||
# requires a GitHub token with repo permissions (e.g. GITHUB_TOKEN from a personal access token)
|
||||
# requires Docker with buildx support
|
||||
|
||||
tempfile=/tmp/event.json
|
||||
|
||||
cat > ${tempfile} <<EOF
|
||||
{
|
||||
"client_payload": {
|
||||
},
|
||||
"action": "build-test-publish-docker",
|
||||
"act": true
|
||||
}
|
||||
EOF
|
||||
|
||||
act repository_dispatch \
|
||||
-e /tmp/event.json \
|
||||
--actor='<username>' \
|
||||
-s GITHUB_TOKEN='<GitHub token>' \
|
||||
--container-options "--user runner:$(getent group docker | cut -d: -f3)" \
|
||||
-W '.github/workflows/build-test-publish-docker.yml'
|
||||
|
||||
rm -f ${tempfile}
|
||||
```
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ publish_action() {
|
|||
local platform=$1
|
||||
local version_list=("${build_version}")
|
||||
|
||||
builder_echo debug "publishing image for ${platform}"
|
||||
builder_echo debug "publishing image for ${platform}."
|
||||
|
||||
if is_default_values; then
|
||||
version_list+=("default")
|
||||
|
|
|
|||
|
|
@ -96,16 +96,11 @@ setup_container_registry() {
|
|||
local password=${REGISTRY_PASSWORD:-}
|
||||
registry_slash=''
|
||||
|
||||
builder_echo debug "Setting up container registry."
|
||||
builder_echo debug "Setting up container registry '${registry}'."
|
||||
|
||||
if [[ "${registry:-}" == "docker.io" ]]; then
|
||||
builder_echo debug "Container registry is 'docker.io'."
|
||||
registry=
|
||||
else
|
||||
registry_slash="${registry}/"
|
||||
registry_parameters="--registry ${registry}"
|
||||
build_args+=("--build-arg=REGISTRY=${registry_slash}")
|
||||
fi
|
||||
registry_slash="${registry}/"
|
||||
registry_parameters="--registry ${registry}"
|
||||
build_args+=("--build-arg=REGISTRY=${registry_slash}")
|
||||
|
||||
if [[ -n ${username:-} ]] ; then
|
||||
if [[ -z ${password:-} ]] ; then
|
||||
|
|
|
|||
|
|
@ -114,18 +114,25 @@ function prepend_scope() {
|
|||
fi
|
||||
fi
|
||||
|
||||
commentchar="#"
|
||||
if [[ -n "$(git config core.commentString)" ]]; then
|
||||
commentchar="$(git config core.commentString)"
|
||||
elif [[ -n "$(git config core.commentChar)" ]]; then
|
||||
commentchar="$(git config core.commentChar)"
|
||||
fi
|
||||
|
||||
postfix=$(
|
||||
cat <<EOF
|
||||
\n# Keyman Conventional Commit suggestions:
|
||||
#
|
||||
# - Link to a Sentry issue with git trailer:
|
||||
# Fixes: _MODULE_-_ID_
|
||||
# - Give credit to co-authors:
|
||||
# Co-authored-by: _Name_ <_email_>
|
||||
# - Use imperative, present tense ('attach' not 'attaches', 'attached' etc)
|
||||
# - Don't include a period at the end of the title
|
||||
# - Always include a blank line before trailers
|
||||
# - More: https://github.com/keymanapp/keyman/wiki/Pull-Request-and-Commit-workflow-notes
|
||||
\n${commentchar} Keyman Conventional Commit suggestions:
|
||||
${commentchar}
|
||||
${commentchar} - Link to a Sentry issue with git trailer:
|
||||
${commentchar} Fixes: _MODULE_-_ID_
|
||||
${commentchar} - Give credit to co-authors:
|
||||
${commentchar} Co-authored-by: _Name_ <_email_>
|
||||
${commentchar} - Use imperative, present tense ('attach' not 'attaches', 'attached' etc)
|
||||
${commentchar} - Don't include a period at the end of the title
|
||||
${commentchar} - Always include a blank line before trailers
|
||||
${commentchar} - More: https://github.com/keymanapp/keyman/wiki/Pull-Request-and-Commit-workflow-notes
|
||||
EOF
|
||||
)
|
||||
|
||||
|
|
@ -170,4 +177,4 @@ case $COMMIT_SOURCE in
|
|||
# Known possibilities: message (-m), template (-t)
|
||||
exit 0
|
||||
;;
|
||||
esac
|
||||
esac
|
||||
|
|
|
|||
|
|
@ -57,13 +57,9 @@ See also [ldml-keyboards/readme.md](ldml-keyboards/readme.md).
|
|||
|
||||
### unicode-character-database
|
||||
|
||||
Data from <https://www.unicode.org/Public/15.1.0/ucd/>:
|
||||
Data from <https://www.unicode.org/Public/17.0.0/ucd/>:
|
||||
|
||||
```bash
|
||||
UNICODE_VERSION=15.1.0
|
||||
wget https://www.unicode.org/Public/${UNICODE_VERSION}/ucd/Blocks.txt -O unicode-character-database/Blocks.txt
|
||||
wget https://www.unicode.org/Public/${UNICODE_VERSION}/ucd/UnicodeData.txt -O unicode-character-database/UnicodeData.txt
|
||||
```
|
||||
See [download.sh](./unicode-character-database/download.sh)
|
||||
|
||||
### windows-lcid-to-bcp-47
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# Blocks-16.0.0.txt
|
||||
# Date: 2024-02-02
|
||||
# © 2024 Unicode®, Inc.
|
||||
# Blocks-17.0.0.txt
|
||||
# Date: 2025-08-01
|
||||
# © 2025 Unicode®, Inc.
|
||||
# Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries.
|
||||
# For terms of use and license, see https://www.unicode.org/terms_of_use.html
|
||||
#
|
||||
|
|
@ -228,6 +228,7 @@ FFF0..FFFF; Specials
|
|||
108E0..108FF; Hatran
|
||||
10900..1091F; Phoenician
|
||||
10920..1093F; Lydian
|
||||
10940..1095F; Sidetic
|
||||
10980..1099F; Meroitic Hieroglyphs
|
||||
109A0..109FF; Meroitic Cursive
|
||||
10A00..10A5F; Kharoshthi
|
||||
|
|
@ -279,11 +280,13 @@ FFF0..FFFF; Specials
|
|||
11AB0..11ABF; Unified Canadian Aboriginal Syllabics Extended-A
|
||||
11AC0..11AFF; Pau Cin Hau
|
||||
11B00..11B5F; Devanagari Extended-A
|
||||
11B60..11B7F; Sharada Supplement
|
||||
11BC0..11BFF; Sunuwar
|
||||
11C00..11C6F; Bhaiksuki
|
||||
11C70..11CBF; Marchen
|
||||
11D00..11D5F; Masaram Gondi
|
||||
11D60..11DAF; Gunjala Gondi
|
||||
11DB0..11DEF; Tolong Siki
|
||||
11EE0..11EFF; Makasar
|
||||
11F00..11F5F; Kawi
|
||||
11FB0..11FBF; Lisu Supplement
|
||||
|
|
@ -304,12 +307,14 @@ FFF0..FFFF; Specials
|
|||
16B00..16B8F; Pahawh Hmong
|
||||
16D40..16D7F; Kirat Rai
|
||||
16E40..16E9F; Medefaidrin
|
||||
16EA0..16EDF; Beria Erfe
|
||||
16F00..16F9F; Miao
|
||||
16FE0..16FFF; Ideographic Symbols and Punctuation
|
||||
17000..187FF; Tangut
|
||||
18800..18AFF; Tangut Components
|
||||
18B00..18CFF; Khitan Small Script
|
||||
18D00..18D7F; Tangut Supplement
|
||||
18D80..18DFF; Tangut Components Supplement
|
||||
1AFF0..1AFFF; Kana Extended-B
|
||||
1B000..1B0FF; Kana Supplement
|
||||
1B100..1B12F; Kana Extended-A
|
||||
|
|
@ -318,6 +323,7 @@ FFF0..FFFF; Specials
|
|||
1BC00..1BC9F; Duployan
|
||||
1BCA0..1BCAF; Shorthand Format Controls
|
||||
1CC00..1CEBF; Symbols for Legacy Computing Supplement
|
||||
1CEC0..1CEFF; Miscellaneous Symbols Supplement
|
||||
1CF00..1CFCF; Znamenny Musical Notation
|
||||
1D000..1D0FF; Byzantine Musical Symbols
|
||||
1D100..1D1FF; Musical Symbols
|
||||
|
|
@ -336,6 +342,7 @@ FFF0..FFFF; Specials
|
|||
1E2C0..1E2FF; Wancho
|
||||
1E4D0..1E4FF; Nag Mundari
|
||||
1E5D0..1E5FF; Ol Onal
|
||||
1E6C0..1E6FF; Tai Yo
|
||||
1E7E0..1E7FF; Ethiopic Extended-B
|
||||
1E800..1E8DF; Mende Kikakui
|
||||
1E900..1E95F; Adlam
|
||||
|
|
@ -367,6 +374,7 @@ FFF0..FFFF; Specials
|
|||
2F800..2FA1F; CJK Compatibility Ideographs Supplement
|
||||
30000..3134F; CJK Unified Ideographs Extension G
|
||||
31350..323AF; CJK Unified Ideographs Extension H
|
||||
323B0..3347F; CJK Unified Ideographs Extension J
|
||||
E0000..E007F; Tags
|
||||
E0100..E01EF; Variation Selectors Supplement
|
||||
F0000..FFFFF; Supplementary Private Use Area-A
|
||||
|
|
|
|||
|
|
@ -659,7 +659,7 @@
|
|||
0292;LATIN SMALL LETTER EZH;Ll;0;L;;;;;N;LATIN SMALL LETTER YOGH;;01B7;;01B7
|
||||
0293;LATIN SMALL LETTER EZH WITH CURL;Ll;0;L;;;;;N;LATIN SMALL LETTER YOGH CURL;;;;
|
||||
0294;LATIN LETTER GLOTTAL STOP;Lo;0;L;;;;;N;;;;;
|
||||
0295;LATIN LETTER PHARYNGEAL VOICED FRICATIVE;Ll;0;L;;;;;N;LATIN LETTER REVERSED GLOTTAL STOP;;;;
|
||||
0295;LATIN LETTER PHARYNGEAL VOICED FRICATIVE;Lo;0;L;;;;;N;LATIN LETTER REVERSED GLOTTAL STOP;;;;
|
||||
0296;LATIN LETTER INVERTED GLOTTAL STOP;Ll;0;L;;;;;N;;;;;
|
||||
0297;LATIN LETTER STRETCHED C;Ll;0;L;;;;;N;;;;;
|
||||
0298;LATIN LETTER BILABIAL CLICK;Ll;0;L;;;;;N;LATIN LETTER BULLSEYE;;;;
|
||||
|
|
@ -2121,6 +2121,7 @@
|
|||
088C;ARABIC LETTER TAH WITH THREE DOTS BELOW;Lo;0;AL;;;;;N;;;;;
|
||||
088D;ARABIC LETTER KEHEH WITH TWO DOTS VERTICALLY BELOW;Lo;0;AL;;;;;N;;;;;
|
||||
088E;ARABIC VERTICAL TAIL;Lo;0;AL;;;;;N;;;;;
|
||||
088F;ARABIC LETTER NOON WITH RING ABOVE;Lo;0;AL;;;;;N;;;;;
|
||||
0890;ARABIC POUND MARK ABOVE;Cf;0;AN;;;;;N;;;;;
|
||||
0891;ARABIC PIASTRE MARK ABOVE;Cf;0;AN;;;;;N;;;;;
|
||||
0897;ARABIC PEPET;Mn;230;NSM;;;;;N;;;;;
|
||||
|
|
@ -2862,6 +2863,7 @@
|
|||
0C58;TELUGU LETTER TSA;Lo;0;L;;;;;N;;;;;
|
||||
0C59;TELUGU LETTER DZA;Lo;0;L;;;;;N;;;;;
|
||||
0C5A;TELUGU LETTER RRRA;Lo;0;L;;;;;N;;;;;
|
||||
0C5C;TELUGU ARCHAIC SHRII;Lo;0;L;;;;;N;;;;;
|
||||
0C5D;TELUGU LETTER NAKAARA POLLU;Lo;0;L;;;;;N;;;;;
|
||||
0C60;TELUGU LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;;
|
||||
0C61;TELUGU LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;;
|
||||
|
|
@ -2958,6 +2960,7 @@
|
|||
0CCD;KANNADA SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;;
|
||||
0CD5;KANNADA LENGTH MARK;Mc;0;L;;;;;N;;;;;
|
||||
0CD6;KANNADA AI LENGTH MARK;Mc;0;L;;;;;N;;;;;
|
||||
0CDC;KANNADA ARCHAIC SHRII;Lo;0;L;;;;;N;;;;;
|
||||
0CDD;KANNADA LETTER NAKAARA POLLU;Lo;0;L;;;;;N;;;;;
|
||||
0CDE;KANNADA LETTER FA;Lo;0;L;;;;;N;;;;;
|
||||
0CE0;KANNADA LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;;
|
||||
|
|
@ -6137,6 +6140,33 @@
|
|||
1ACC;COMBINING LATIN SMALL LETTER INSULAR G;Mn;230;NSM;;;;;N;;;;;
|
||||
1ACD;COMBINING LATIN SMALL LETTER INSULAR R;Mn;230;NSM;;;;;N;;;;;
|
||||
1ACE;COMBINING LATIN SMALL LETTER INSULAR T;Mn;230;NSM;;;;;N;;;;;
|
||||
1ACF;COMBINING DOUBLE CARON;Mn;230;NSM;;;;;N;;;;;
|
||||
1AD0;COMBINING VERTICAL-LINE-ACUTE;Mn;230;NSM;;;;;N;;;;;
|
||||
1AD1;COMBINING GRAVE-VERTICAL-LINE;Mn;230;NSM;;;;;N;;;;;
|
||||
1AD2;COMBINING VERTICAL-LINE-GRAVE;Mn;230;NSM;;;;;N;;;;;
|
||||
1AD3;COMBINING ACUTE-VERTICAL-LINE;Mn;230;NSM;;;;;N;;;;;
|
||||
1AD4;COMBINING VERTICAL-LINE-MACRON;Mn;230;NSM;;;;;N;;;;;
|
||||
1AD5;COMBINING MACRON-VERTICAL-LINE;Mn;230;NSM;;;;;N;;;;;
|
||||
1AD6;COMBINING VERTICAL-LINE-ACUTE-GRAVE;Mn;230;NSM;;;;;N;;;;;
|
||||
1AD7;COMBINING VERTICAL-LINE-GRAVE-ACUTE;Mn;230;NSM;;;;;N;;;;;
|
||||
1AD8;COMBINING MACRON-ACUTE-GRAVE;Mn;230;NSM;;;;;N;;;;;
|
||||
1AD9;COMBINING SHARP SIGN;Mn;230;NSM;;;;;N;;;;;
|
||||
1ADA;COMBINING FLAT SIGN;Mn;230;NSM;;;;;N;;;;;
|
||||
1ADB;COMBINING DOWN TACK ABOVE;Mn;230;NSM;;;;;N;;;;;
|
||||
1ADC;COMBINING DIAERESIS WITH RAISED LEFT DOT;Mn;230;NSM;;;;;N;;;;;
|
||||
1ADD;COMBINING DOT-AND-RING BELOW;Mn;220;NSM;;;;;N;;;;;
|
||||
1AE0;COMBINING LEFT TACK ABOVE;Mn;230;NSM;;;;;N;;;;;
|
||||
1AE1;COMBINING RIGHT TACK ABOVE;Mn;230;NSM;;;;;N;;;;;
|
||||
1AE2;COMBINING MINUS SIGN ABOVE;Mn;230;NSM;;;;;N;;;;;
|
||||
1AE3;COMBINING INVERTED BRIDGE ABOVE;Mn;230;NSM;;;;;N;;;;;
|
||||
1AE4;COMBINING SQUARE ABOVE;Mn;230;NSM;;;;;N;;;;;
|
||||
1AE5;COMBINING SEAGULL ABOVE;Mn;230;NSM;;;;;N;;;;;
|
||||
1AE6;COMBINING DOUBLE ARCH BELOW;Mn;220;NSM;;;;;N;;;;;
|
||||
1AE7;COMBINING DOUBLE ARCH ABOVE;Mn;230;NSM;;;;;N;;;;;
|
||||
1AE8;COMBINING EQUALS SIGN ABOVE;Mn;230;NSM;;;;;N;;;;;
|
||||
1AE9;COMBINING LEFT ANGLE CENTRED ABOVE;Mn;230;NSM;;;;;N;;;;;
|
||||
1AEA;COMBINING UPWARDS ARROW ABOVE;Mn;230;NSM;;;;;N;;;;;
|
||||
1AEB;COMBINING DOUBLE RIGHTWARDS ARROW ABOVE;Mn;234;NSM;;;;;N;;;;;
|
||||
1B00;BALINESE SIGN ULU RICEM;Mn;0;NSM;;;;;N;;;;;
|
||||
1B01;BALINESE SIGN ULU CANDRA;Mn;0;NSM;;;;;N;;;;;
|
||||
1B02;BALINESE SIGN CECEK;Mn;0;NSM;;;;;N;;;;;
|
||||
|
|
@ -7545,6 +7575,7 @@
|
|||
20BE;LARI SIGN;Sc;0;ET;;;;;N;;;;;
|
||||
20BF;BITCOIN SIGN;Sc;0;ET;;;;;N;;;;;
|
||||
20C0;SOM SIGN;Sc;0;ET;;;;;N;;;;;
|
||||
20C1;SAUDI RIYAL SIGN;Sc;0;ET;;;;;N;;;;;
|
||||
20D0;COMBINING LEFT HARPOON ABOVE;Mn;230;NSM;;;;;N;NON-SPACING LEFT HARPOON ABOVE;;;;
|
||||
20D1;COMBINING RIGHT HARPOON ABOVE;Mn;230;NSM;;;;;N;NON-SPACING RIGHT HARPOON ABOVE;;;;
|
||||
20D2;COMBINING LONG VERTICAL LINE OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING LONG VERTICAL BAR OVERLAY;;;;
|
||||
|
|
@ -10239,6 +10270,7 @@
|
|||
2B93;NEWLINE RIGHT;So;0;ON;;;;;N;;;;;
|
||||
2B94;FOUR CORNER ARROWS CIRCLING ANTICLOCKWISE;So;0;ON;;;;;N;;;;;
|
||||
2B95;RIGHTWARDS BLACK ARROW;So;0;ON;;;;;N;;;;;
|
||||
2B96;EQUALS SIGN WITH INFINITY ABOVE;So;0;ON;;;;;N;;;;;
|
||||
2B97;SYMBOL FOR TYPE A ELECTRONICS;So;0;ON;;;;;N;;;;;
|
||||
2B98;THREE-D TOP-LIGHTED LEFTWARDS EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;;
|
||||
2B99;THREE-D RIGHT-LIGHTED UPWARDS EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;;
|
||||
|
|
@ -14274,10 +14306,14 @@ A7CA;LATIN SMALL LETTER S WITH SHORT STROKE OVERLAY;Ll;0;L;;;;;N;;;A7C9;;A7C9
|
|||
A7CB;LATIN CAPITAL LETTER RAMS HORN;Lu;0;L;;;;;N;;;;0264;
|
||||
A7CC;LATIN CAPITAL LETTER S WITH DIAGONAL STROKE;Lu;0;L;;;;;N;;;;A7CD;
|
||||
A7CD;LATIN SMALL LETTER S WITH DIAGONAL STROKE;Ll;0;L;;;;;N;;;A7CC;;A7CC
|
||||
A7CE;LATIN CAPITAL LETTER PHARYNGEAL VOICED FRICATIVE;Lu;0;L;;;;;N;;;;A7CF;
|
||||
A7CF;LATIN SMALL LETTER PHARYNGEAL VOICED FRICATIVE;Ll;0;L;;;;;N;;;A7CE;;A7CE
|
||||
A7D0;LATIN CAPITAL LETTER CLOSED INSULAR G;Lu;0;L;;;;;N;;;;A7D1;
|
||||
A7D1;LATIN SMALL LETTER CLOSED INSULAR G;Ll;0;L;;;;;N;;;A7D0;;A7D0
|
||||
A7D3;LATIN SMALL LETTER DOUBLE THORN;Ll;0;L;;;;;N;;;;;
|
||||
A7D5;LATIN SMALL LETTER DOUBLE WYNN;Ll;0;L;;;;;N;;;;;
|
||||
A7D2;LATIN CAPITAL LETTER DOUBLE THORN;Lu;0;L;;;;;N;;;;A7D3;
|
||||
A7D3;LATIN SMALL LETTER DOUBLE THORN;Ll;0;L;;;;;N;;;A7D2;;A7D2
|
||||
A7D4;LATIN CAPITAL LETTER DOUBLE WYNN;Lu;0;L;;;;;N;;;;A7D5;
|
||||
A7D5;LATIN SMALL LETTER DOUBLE WYNN;Ll;0;L;;;;;N;;;A7D4;;A7D4
|
||||
A7D6;LATIN CAPITAL LETTER MIDDLE SCOTS S;Lu;0;L;;;;;N;;;;A7D7;
|
||||
A7D7;LATIN SMALL LETTER MIDDLE SCOTS S;Ll;0;L;;;;;N;;;A7D6;;A7D6
|
||||
A7D8;LATIN CAPITAL LETTER SIGMOID S;Lu;0;L;;;;;N;;;;A7D9;
|
||||
|
|
@ -14285,6 +14321,7 @@ A7D9;LATIN SMALL LETTER SIGMOID S;Ll;0;L;;;;;N;;;A7D8;;A7D8
|
|||
A7DA;LATIN CAPITAL LETTER LAMBDA;Lu;0;L;;;;;N;;;;A7DB;
|
||||
A7DB;LATIN SMALL LETTER LAMBDA;Ll;0;L;;;;;N;;;A7DA;;A7DA
|
||||
A7DC;LATIN CAPITAL LETTER LAMBDA WITH STROKE;Lu;0;L;;;;;N;;;;019B;
|
||||
A7F1;MODIFIER LETTER CAPITAL S;Lm;0;L;<super> 0053;;;;N;;;;;
|
||||
A7F2;MODIFIER LETTER CAPITAL C;Lm;0;L;<super> 0043;;;;N;;;;;
|
||||
A7F3;MODIFIER LETTER CAPITAL F;Lm;0;L;<super> 0046;;;;N;;;;;
|
||||
A7F4;MODIFIER LETTER CAPITAL Q;Lm;0;L;<super> 0051;;;;N;;;;;
|
||||
|
|
@ -15925,6 +15962,22 @@ FBBF;ARABIC SYMBOL RING;Sk;0;AL;;;;;N;;;;;
|
|||
FBC0;ARABIC SYMBOL SMALL TAH ABOVE;Sk;0;AL;;;;;N;;;;;
|
||||
FBC1;ARABIC SYMBOL SMALL TAH BELOW;Sk;0;AL;;;;;N;;;;;
|
||||
FBC2;ARABIC SYMBOL WASLA ABOVE;Sk;0;AL;;;;;N;;;;;
|
||||
FBC3;ARABIC LIGATURE JALLA WA-ALAA;So;0;ON;;;;;N;;;;;
|
||||
FBC4;ARABIC LIGATURE DAAMAT BARAKAATUHUM;So;0;ON;;;;;N;;;;;
|
||||
FBC5;ARABIC LIGATURE RAHMATU ALLAAHI TAAALAA ALAYH;So;0;ON;;;;;N;;;;;
|
||||
FBC6;ARABIC LIGATURE RAHMATU ALLAAHI ALAYHIM;So;0;ON;;;;;N;;;;;
|
||||
FBC7;ARABIC LIGATURE RAHMATU ALLAAHI ALAYHIMAA;So;0;ON;;;;;N;;;;;
|
||||
FBC8;ARABIC LIGATURE RAHIMAHUM ALLAAHU TAAALAA;So;0;ON;;;;;N;;;;;
|
||||
FBC9;ARABIC LIGATURE RAHIMAHUMAA ALLAAH;So;0;ON;;;;;N;;;;;
|
||||
FBCA;ARABIC LIGATURE RAHIMAHUMAA ALLAAHU TAAALAA;So;0;ON;;;;;N;;;;;
|
||||
FBCB;ARABIC LIGATURE RADI ALLAAHU TAAALAA ANHUM;So;0;ON;;;;;N;;;;;
|
||||
FBCC;ARABIC LIGATURE HAFIZAHU ALLAAH;So;0;ON;;;;;N;;;;;
|
||||
FBCD;ARABIC LIGATURE HAFIZAHU ALLAAHU TAAALAA;So;0;ON;;;;;N;;;;;
|
||||
FBCE;ARABIC LIGATURE HAFIZAHUM ALLAAHU TAAALAA;So;0;ON;;;;;N;;;;;
|
||||
FBCF;ARABIC LIGATURE HAFIZAHUMAA ALLAAHU TAAALAA;So;0;ON;;;;;N;;;;;
|
||||
FBD0;ARABIC LIGATURE SALLALLAAHU TAAALAA ALAYHI WA-SALLAM;So;0;ON;;;;;N;;;;;
|
||||
FBD1;ARABIC LIGATURE AJJAL ALLAAHU FARAJAHU ASH-SHAREEF;So;0;ON;;;;;N;;;;;
|
||||
FBD2;ARABIC LIGATURE ALAYHI AR-RAHMAH;So;0;ON;;;;;N;;;;;
|
||||
FBD3;ARABIC LETTER NG ISOLATED FORM;Lo;0;AL;<isolated> 06AD;;;;N;;;;;
|
||||
FBD4;ARABIC LETTER NG FINAL FORM;Lo;0;AL;<final> 06AD;;;;N;;;;;
|
||||
FBD5;ARABIC LETTER NG INITIAL FORM;Lo;0;AL;<initial> 06AD;;;;N;;;;;
|
||||
|
|
@ -16370,6 +16423,8 @@ FD8C;ARABIC LIGATURE MEEM WITH JEEM WITH HAH INITIAL FORM;Lo;0;AL;<initial> 0645
|
|||
FD8D;ARABIC LIGATURE MEEM WITH JEEM WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0645 062C 0645;;;;N;;;;;
|
||||
FD8E;ARABIC LIGATURE MEEM WITH KHAH WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 0645 062E 062C;;;;N;;;;;
|
||||
FD8F;ARABIC LIGATURE MEEM WITH KHAH WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0645 062E 0645;;;;N;;;;;
|
||||
FD90;ARABIC LIGATURE RAHMATU ALLAAHI ALAYH;So;0;ON;;;;;N;;;;;
|
||||
FD91;ARABIC LIGATURE RAHMATU ALLAAHI ALAYHAA;So;0;ON;;;;;N;;;;;
|
||||
FD92;ARABIC LIGATURE MEEM WITH JEEM WITH KHAH INITIAL FORM;Lo;0;AL;<initial> 0645 062C 062E;;;;N;;;;;
|
||||
FD93;ARABIC LIGATURE HEH WITH MEEM WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 0647 0645 062C;;;;N;;;;;
|
||||
FD94;ARABIC LIGATURE HEH WITH MEEM WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0647 0645 0645;;;;N;;;;;
|
||||
|
|
@ -16424,6 +16479,13 @@ FDC4;ARABIC LIGATURE AIN WITH JEEM WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0639
|
|||
FDC5;ARABIC LIGATURE SAD WITH MEEM WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0635 0645 0645;;;;N;;;;;
|
||||
FDC6;ARABIC LIGATURE SEEN WITH KHAH WITH YEH FINAL FORM;Lo;0;AL;<final> 0633 062E 064A;;;;N;;;;;
|
||||
FDC7;ARABIC LIGATURE NOON WITH JEEM WITH YEH FINAL FORM;Lo;0;AL;<final> 0646 062C 064A;;;;N;;;;;
|
||||
FDC8;ARABIC LIGATURE RAHIMAHU ALLAAH TAAALAA;So;0;ON;;;;;N;;;;;
|
||||
FDC9;ARABIC LIGATURE RADI ALLAAHU TAAALAA ANH;So;0;ON;;;;;N;;;;;
|
||||
FDCA;ARABIC LIGATURE RADI ALLAAHU TAAALAA ANHAA;So;0;ON;;;;;N;;;;;
|
||||
FDCB;ARABIC LIGATURE RADI ALLAAHU TAAALAA ANHUMAA;So;0;ON;;;;;N;;;;;
|
||||
FDCC;ARABIC LIGATURE SALLALLAHU ALAYHI WA-ALAA AALIHEE WA-SALLAM;So;0;ON;;;;;N;;;;;
|
||||
FDCD;ARABIC LIGATURE AJJAL ALLAAHU TAAALAA FARAJAHU ASH-SHAREEF;So;0;ON;;;;;N;;;;;
|
||||
FDCE;ARABIC LIGATURE KARRAMA ALLAAHU WAJHAH;So;0;ON;;;;;N;;;;;
|
||||
FDCF;ARABIC LIGATURE SALAAMUHU ALAYNAA;So;0;ON;;;;;N;;;;;
|
||||
FDF0;ARABIC LIGATURE SALLA USED AS KORANIC STOP SIGN ISOLATED FORM;Lo;0;AL;<isolated> 0635 0644 06D2;;;;N;;;;;
|
||||
FDF1;ARABIC LIGATURE QALA USED AS KORANIC STOP SIGN ISOLATED FORM;Lo;0;AL;<isolated> 0642 0644 06D2;;;;N;;;;;
|
||||
|
|
@ -18708,6 +18770,32 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;;
|
|||
10938;LYDIAN LETTER NN;Lo;0;R;;;;;N;;;;;
|
||||
10939;LYDIAN LETTER C;Lo;0;R;;;;;N;;;;;
|
||||
1093F;LYDIAN TRIANGULAR MARK;Po;0;R;;;;;N;;;;;
|
||||
10940;SIDETIC LETTER N01;Lo;0;R;;;;;N;;;;;
|
||||
10941;SIDETIC LETTER N02;Lo;0;R;;;;;N;;;;;
|
||||
10942;SIDETIC LETTER N03;Lo;0;R;;;;;N;;;;;
|
||||
10943;SIDETIC LETTER N04;Lo;0;R;;;;;N;;;;;
|
||||
10944;SIDETIC LETTER N05;Lo;0;R;;;;;N;;;;;
|
||||
10945;SIDETIC LETTER N06;Lo;0;R;;;;;N;;;;;
|
||||
10946;SIDETIC LETTER N07;Lo;0;R;;;;;N;;;;;
|
||||
10947;SIDETIC LETTER N08;Lo;0;R;;;;;N;;;;;
|
||||
10948;SIDETIC LETTER N09;Lo;0;R;;;;;N;;;;;
|
||||
10949;SIDETIC LETTER N10;Lo;0;R;;;;;N;;;;;
|
||||
1094A;SIDETIC LETTER N11;Lo;0;R;;;;;N;;;;;
|
||||
1094B;SIDETIC LETTER N12;Lo;0;R;;;;;N;;;;;
|
||||
1094C;SIDETIC LETTER N13;Lo;0;R;;;;;N;;;;;
|
||||
1094D;SIDETIC LETTER N14;Lo;0;R;;;;;N;;;;;
|
||||
1094E;SIDETIC LETTER N15;Lo;0;R;;;;;N;;;;;
|
||||
1094F;SIDETIC LETTER N16;Lo;0;R;;;;;N;;;;;
|
||||
10950;SIDETIC LETTER N17;Lo;0;R;;;;;N;;;;;
|
||||
10951;SIDETIC LETTER N18;Lo;0;R;;;;;N;;;;;
|
||||
10952;SIDETIC LETTER N19;Lo;0;R;;;;;N;;;;;
|
||||
10953;SIDETIC LETTER N20;Lo;0;R;;;;;N;;;;;
|
||||
10954;SIDETIC LETTER N21;Lo;0;R;;;;;N;;;;;
|
||||
10955;SIDETIC LETTER N22;Lo;0;R;;;;;N;;;;;
|
||||
10956;SIDETIC LETTER N23;Lo;0;R;;;;;N;;;;;
|
||||
10957;SIDETIC LETTER N24;Lo;0;R;;;;;N;;;;;
|
||||
10958;SIDETIC LETTER N25;Lo;0;R;;;;;N;;;;;
|
||||
10959;SIDETIC LETTER N26;Lo;0;R;;;;;N;;;;;
|
||||
10980;MEROITIC HIEROGLYPHIC LETTER A;Lo;0;R;;;;;N;;;;;
|
||||
10981;MEROITIC HIEROGLYPHIC LETTER E;Lo;0;R;;;;;N;;;;;
|
||||
10982;MEROITIC HIEROGLYPHIC LETTER I;Lo;0;R;;;;;N;;;;;
|
||||
|
|
@ -19541,6 +19629,20 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;;
|
|||
10EC2;ARABIC LETTER DAL WITH TWO DOTS VERTICALLY BELOW;Lo;0;AL;;;;;N;;;;;
|
||||
10EC3;ARABIC LETTER TAH WITH TWO DOTS VERTICALLY BELOW;Lo;0;AL;;;;;N;;;;;
|
||||
10EC4;ARABIC LETTER KAF WITH TWO DOTS VERTICALLY BELOW;Lo;0;AL;;;;;N;;;;;
|
||||
10EC5;ARABIC SMALL YEH BARREE WITH TWO DOTS BELOW;Lm;0;AL;;;;;N;;;;;
|
||||
10EC6;ARABIC LETTER THIN NOON;Lo;0;AL;;;;;N;;;;;
|
||||
10EC7;ARABIC LETTER YEH WITH FOUR DOTS BELOW;Lo;0;AL;;;;;N;;;;;
|
||||
10ED0;ARABIC BIBLICAL END OF VERSE;Po;0;ON;;;;;N;;;;;
|
||||
10ED1;ARABIC LIGATURE ALAYHAA AS-SALAATU WAS-SALAAM;So;0;ON;;;;;N;;;;;
|
||||
10ED2;ARABIC LIGATURE ALAYHIM AS-SALAATU WAS-SALAAM;So;0;ON;;;;;N;;;;;
|
||||
10ED3;ARABIC LIGATURE ALAYHIMAA AS-SALAATU WAS-SALAAM;So;0;ON;;;;;N;;;;;
|
||||
10ED4;ARABIC LIGATURE QADDASA ALLAAHU SIRRAH;So;0;ON;;;;;N;;;;;
|
||||
10ED5;ARABIC LIGATURE QUDDISA SIRRUHUM;So;0;ON;;;;;N;;;;;
|
||||
10ED6;ARABIC LIGATURE QUDDISA SIRRUHUMAA;So;0;ON;;;;;N;;;;;
|
||||
10ED7;ARABIC LIGATURE QUDDISAT ASRAARUHUM;So;0;ON;;;;;N;;;;;
|
||||
10ED8;ARABIC LIGATURE NAWWARA ALLAAHU MARQADAH;So;0;ON;;;;;N;;;;;
|
||||
10EFA;ARABIC DOUBLE VERTICAL BAR BELOW;Mn;220;NSM;;;;;N;;;;;
|
||||
10EFB;ARABIC SMALL LOW NOON;Mn;220;NSM;;;;;N;;;;;
|
||||
10EFC;ARABIC COMBINING ALEF OVERLAY;Mn;0;NSM;;;;;N;;;;;
|
||||
10EFD;ARABIC SMALL LOW WORD SAKTA;Mn;220;NSM;;;;;N;;;;;
|
||||
10EFE;ARABIC SMALL LOW WORD QASR;Mn;220;NSM;;;;;N;;;;;
|
||||
|
|
@ -21521,6 +21623,14 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;;
|
|||
11B07;DEVANAGARI SIGN WESTERN NINE-LIKE BHALE;Po;0;L;;;;;N;;;;;
|
||||
11B08;DEVANAGARI SIGN REVERSED NINE-LIKE BHALE;Po;0;L;;;;;N;;;;;
|
||||
11B09;DEVANAGARI SIGN MINDU;Po;0;L;;;;;N;;;;;
|
||||
11B60;SHARADA VOWEL SIGN OE;Mn;0;NSM;;;;;N;;;;;
|
||||
11B61;SHARADA VOWEL SIGN OOE;Mc;0;L;;;;;N;;;;;
|
||||
11B62;SHARADA VOWEL SIGN UE;Mn;0;NSM;;;;;N;;;;;
|
||||
11B63;SHARADA VOWEL SIGN UUE;Mn;0;NSM;;;;;N;;;;;
|
||||
11B64;SHARADA VOWEL SIGN SHORT E;Mn;0;NSM;;;;;N;;;;;
|
||||
11B65;SHARADA VOWEL SIGN SHORT O;Mc;0;L;;;;;N;;;;;
|
||||
11B66;SHARADA VOWEL SIGN CANDRA E;Mn;0;NSM;;;;;N;;;;;
|
||||
11B67;SHARADA VOWEL SIGN CANDRA O;Mc;0;L;;;;;N;;;;;
|
||||
11BC0;SUNUWAR LETTER DEVI;Lo;0;L;;;;;N;;;;;
|
||||
11BC1;SUNUWAR LETTER TASLA;Lo;0;L;;;;;N;;;;;
|
||||
11BC2;SUNUWAR LETTER EKO;Lo;0;L;;;;;N;;;;;
|
||||
|
|
@ -21868,6 +21978,60 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;;
|
|||
11DA7;GUNJALA GONDI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;;
|
||||
11DA8;GUNJALA GONDI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;;
|
||||
11DA9;GUNJALA GONDI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;;
|
||||
11DB0;TOLONG SIKI LETTER I;Lo;0;L;;;;;N;;;;;
|
||||
11DB1;TOLONG SIKI LETTER E;Lo;0;L;;;;;N;;;;;
|
||||
11DB2;TOLONG SIKI LETTER U;Lo;0;L;;;;;N;;;;;
|
||||
11DB3;TOLONG SIKI LETTER O;Lo;0;L;;;;;N;;;;;
|
||||
11DB4;TOLONG SIKI LETTER A;Lo;0;L;;;;;N;;;;;
|
||||
11DB5;TOLONG SIKI LETTER AA;Lo;0;L;;;;;N;;;;;
|
||||
11DB6;TOLONG SIKI LETTER P;Lo;0;L;;;;;N;;;;;
|
||||
11DB7;TOLONG SIKI LETTER PH;Lo;0;L;;;;;N;;;;;
|
||||
11DB8;TOLONG SIKI LETTER B;Lo;0;L;;;;;N;;;;;
|
||||
11DB9;TOLONG SIKI LETTER BH;Lo;0;L;;;;;N;;;;;
|
||||
11DBA;TOLONG SIKI LETTER M;Lo;0;L;;;;;N;;;;;
|
||||
11DBB;TOLONG SIKI LETTER T;Lo;0;L;;;;;N;;;;;
|
||||
11DBC;TOLONG SIKI LETTER TH;Lo;0;L;;;;;N;;;;;
|
||||
11DBD;TOLONG SIKI LETTER D;Lo;0;L;;;;;N;;;;;
|
||||
11DBE;TOLONG SIKI LETTER DH;Lo;0;L;;;;;N;;;;;
|
||||
11DBF;TOLONG SIKI LETTER N;Lo;0;L;;;;;N;;;;;
|
||||
11DC0;TOLONG SIKI LETTER TT;Lo;0;L;;;;;N;;;;;
|
||||
11DC1;TOLONG SIKI LETTER TTH;Lo;0;L;;;;;N;;;;;
|
||||
11DC2;TOLONG SIKI LETTER DD;Lo;0;L;;;;;N;;;;;
|
||||
11DC3;TOLONG SIKI LETTER DDH;Lo;0;L;;;;;N;;;;;
|
||||
11DC4;TOLONG SIKI LETTER NN;Lo;0;L;;;;;N;;;;;
|
||||
11DC5;TOLONG SIKI LETTER C;Lo;0;L;;;;;N;;;;;
|
||||
11DC6;TOLONG SIKI LETTER CH;Lo;0;L;;;;;N;;;;;
|
||||
11DC7;TOLONG SIKI LETTER J;Lo;0;L;;;;;N;;;;;
|
||||
11DC8;TOLONG SIKI LETTER JH;Lo;0;L;;;;;N;;;;;
|
||||
11DC9;TOLONG SIKI LETTER NY;Lo;0;L;;;;;N;;;;;
|
||||
11DCA;TOLONG SIKI LETTER K;Lo;0;L;;;;;N;;;;;
|
||||
11DCB;TOLONG SIKI LETTER KH;Lo;0;L;;;;;N;;;;;
|
||||
11DCC;TOLONG SIKI LETTER G;Lo;0;L;;;;;N;;;;;
|
||||
11DCD;TOLONG SIKI LETTER GH;Lo;0;L;;;;;N;;;;;
|
||||
11DCE;TOLONG SIKI LETTER NG;Lo;0;L;;;;;N;;;;;
|
||||
11DCF;TOLONG SIKI LETTER Y;Lo;0;L;;;;;N;;;;;
|
||||
11DD0;TOLONG SIKI LETTER R;Lo;0;L;;;;;N;;;;;
|
||||
11DD1;TOLONG SIKI LETTER L;Lo;0;L;;;;;N;;;;;
|
||||
11DD2;TOLONG SIKI LETTER V;Lo;0;L;;;;;N;;;;;
|
||||
11DD3;TOLONG SIKI LETTER NNY;Lo;0;L;;;;;N;;;;;
|
||||
11DD4;TOLONG SIKI LETTER S;Lo;0;L;;;;;N;;;;;
|
||||
11DD5;TOLONG SIKI LETTER H;Lo;0;L;;;;;N;;;;;
|
||||
11DD6;TOLONG SIKI LETTER X;Lo;0;L;;;;;N;;;;;
|
||||
11DD7;TOLONG SIKI LETTER RR;Lo;0;L;;;;;N;;;;;
|
||||
11DD8;TOLONG SIKI LETTER RRH;Lo;0;L;;;;;N;;;;;
|
||||
11DD9;TOLONG SIKI SIGN SELA;Lm;0;L;;;;;N;;;;;
|
||||
11DDA;TOLONG SIKI SIGN HECAKA;Lo;0;L;;;;;N;;;;;
|
||||
11DDB;TOLONG SIKI UNGGA;Lo;0;L;;;;;N;;;;;
|
||||
11DE0;TOLONG SIKI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;;
|
||||
11DE1;TOLONG SIKI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;;
|
||||
11DE2;TOLONG SIKI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;;
|
||||
11DE3;TOLONG SIKI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;;
|
||||
11DE4;TOLONG SIKI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;;
|
||||
11DE5;TOLONG SIKI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;;
|
||||
11DE6;TOLONG SIKI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;;
|
||||
11DE7;TOLONG SIKI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;;
|
||||
11DE8;TOLONG SIKI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;;
|
||||
11DE9;TOLONG SIKI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;;
|
||||
11EE0;MAKASAR LETTER KA;Lo;0;L;;;;;N;;;;;
|
||||
11EE1;MAKASAR LETTER GA;Lo;0;L;;;;;N;;;;;
|
||||
11EE2;MAKASAR LETTER NGA;Lo;0;L;;;;;N;;;;;
|
||||
|
|
@ -22088,8 +22252,8 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;;
|
|||
12035;CUNEIFORM SIGN ARAD TIMES KUR;Lo;0;L;;;;;N;;;;;
|
||||
12036;CUNEIFORM SIGN ARKAB;Lo;0;L;;;;;N;;;;;
|
||||
12037;CUNEIFORM SIGN ASAL2;Lo;0;L;;;;;N;;;;;
|
||||
12038;CUNEIFORM SIGN ASH;Lo;0;L;;;;;N;;;;;
|
||||
12039;CUNEIFORM SIGN ASH ZIDA TENU;Lo;0;L;;;;;N;;;;;
|
||||
12038;CUNEIFORM SIGN ASH;Lo;0;L;;;;1;N;;;;;
|
||||
12039;CUNEIFORM SIGN ASH ZIDA TENU;Lo;0;L;;;;1;N;;;;;
|
||||
1203A;CUNEIFORM SIGN ASH KABA TENU;Lo;0;L;;;;;N;;;;;
|
||||
1203B;CUNEIFORM SIGN ASH OVER ASH TUG2 OVER TUG2 TUG2 OVER TUG2 PAP;Lo;0;L;;;;;N;;;;;
|
||||
1203C;CUNEIFORM SIGN ASH OVER ASH OVER ASH;Lo;0;L;;;;;N;;;;;
|
||||
|
|
@ -22153,7 +22317,7 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;;
|
|||
12076;CUNEIFORM SIGN DIM2;Lo;0;L;;;;;N;;;;;
|
||||
12077;CUNEIFORM SIGN DIN;Lo;0;L;;;;;N;;;;;
|
||||
12078;CUNEIFORM SIGN DIN KASKAL U GUNU DISH;Lo;0;L;;;;;N;;;;;
|
||||
12079;CUNEIFORM SIGN DISH;Lo;0;L;;;;;N;;;;;
|
||||
12079;CUNEIFORM SIGN DISH;Lo;0;L;;;;1;N;;;;;
|
||||
1207A;CUNEIFORM SIGN DU;Lo;0;L;;;;;N;;;;;
|
||||
1207B;CUNEIFORM SIGN DU OVER DU;Lo;0;L;;;;;N;;;;;
|
||||
1207C;CUNEIFORM SIGN DU GUNU;Lo;0;L;;;;;N;;;;;
|
||||
|
|
@ -22582,12 +22746,12 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;;
|
|||
12223;CUNEIFORM SIGN MA2;Lo;0;L;;;;;N;;;;;
|
||||
12224;CUNEIFORM SIGN MAH;Lo;0;L;;;;;N;;;;;
|
||||
12225;CUNEIFORM SIGN MAR;Lo;0;L;;;;;N;;;;;
|
||||
12226;CUNEIFORM SIGN MASH;Lo;0;L;;;;;N;;;;;
|
||||
12226;CUNEIFORM SIGN MASH;Lo;0;L;;;;1/2;N;;;;;
|
||||
12227;CUNEIFORM SIGN MASH2;Lo;0;L;;;;;N;;;;;
|
||||
12228;CUNEIFORM SIGN ME;Lo;0;L;;;;;N;;;;;
|
||||
12229;CUNEIFORM SIGN MES;Lo;0;L;;;;;N;;;;;
|
||||
1222A;CUNEIFORM SIGN MI;Lo;0;L;;;;;N;;;;;
|
||||
1222B;CUNEIFORM SIGN MIN;Lo;0;L;;;;;N;;;;;
|
||||
1222B;CUNEIFORM SIGN MIN;Lo;0;L;;;;2;N;;;;;
|
||||
1222C;CUNEIFORM SIGN MU;Lo;0;L;;;;;N;;;;;
|
||||
1222D;CUNEIFORM SIGN MU OVER MU;Lo;0;L;;;;;N;;;;;
|
||||
1222E;CUNEIFORM SIGN MUG;Lo;0;L;;;;;N;;;;;
|
||||
|
|
@ -22811,9 +22975,9 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;;
|
|||
12308;CUNEIFORM SIGN TUM;Lo;0;L;;;;;N;;;;;
|
||||
12309;CUNEIFORM SIGN TUR;Lo;0;L;;;;;N;;;;;
|
||||
1230A;CUNEIFORM SIGN TUR OVER TUR ZA OVER ZA;Lo;0;L;;;;;N;;;;;
|
||||
1230B;CUNEIFORM SIGN U;Lo;0;L;;;;;N;;;;;
|
||||
1230B;CUNEIFORM SIGN U;Lo;0;L;;;;1;N;;;;;
|
||||
1230C;CUNEIFORM SIGN U GUD;Lo;0;L;;;;;N;;;;;
|
||||
1230D;CUNEIFORM SIGN U U U;Lo;0;L;;;;;N;;;;;
|
||||
1230D;CUNEIFORM SIGN U U U;Lo;0;L;;;;3;N;;;;;
|
||||
1230E;CUNEIFORM SIGN U OVER U PA OVER PA GAR OVER GAR;Lo;0;L;;;;;N;;;;;
|
||||
1230F;CUNEIFORM SIGN U OVER U SUR OVER SUR;Lo;0;L;;;;;N;;;;;
|
||||
12310;CUNEIFORM SIGN U OVER U U REVERSED OVER U REVERSED;Lo;0;L;;;;;N;;;;;
|
||||
|
|
@ -22953,7 +23117,7 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;;
|
|||
12396;CUNEIFORM SIGN SAG TIMES IGI GUNU;Lo;0;L;;;;;N;;;;;
|
||||
12397;CUNEIFORM SIGN TI2;Lo;0;L;;;;;N;;;;;
|
||||
12398;CUNEIFORM SIGN UM TIMES ME;Lo;0;L;;;;;N;;;;;
|
||||
12399;CUNEIFORM SIGN U U;Lo;0;L;;;;;N;;;;;
|
||||
12399;CUNEIFORM SIGN U U;Lo;0;L;;;;2;N;;;;;
|
||||
12400;CUNEIFORM NUMERIC SIGN TWO ASH;Nl;0;L;;;;2;N;;;;;
|
||||
12401;CUNEIFORM NUMERIC SIGN THREE ASH;Nl;0;L;;;;3;N;;;;;
|
||||
12402;CUNEIFORM NUMERIC SIGN FOUR ASH;Nl;0;L;;;;4;N;;;;;
|
||||
|
|
@ -30124,6 +30288,56 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;;
|
|||
16E98;MEDEFAIDRIN FULL STOP;Po;0;L;;;;;N;;;;;
|
||||
16E99;MEDEFAIDRIN SYMBOL AIVA;Po;0;L;;;;;N;;;;;
|
||||
16E9A;MEDEFAIDRIN EXCLAMATION OH;Po;0;L;;;;;N;;;;;
|
||||
16EA0;BERIA ERFE CAPITAL LETTER ARKAB;Lu;0;L;;;;;N;;;;16EBB;
|
||||
16EA1;BERIA ERFE CAPITAL LETTER BASIGNA;Lu;0;L;;;;;N;;;;16EBC;
|
||||
16EA2;BERIA ERFE CAPITAL LETTER DARBAI;Lu;0;L;;;;;N;;;;16EBD;
|
||||
16EA3;BERIA ERFE CAPITAL LETTER EH;Lu;0;L;;;;;N;;;;16EBE;
|
||||
16EA4;BERIA ERFE CAPITAL LETTER FITKO;Lu;0;L;;;;;N;;;;16EBF;
|
||||
16EA5;BERIA ERFE CAPITAL LETTER GOWAY;Lu;0;L;;;;;N;;;;16EC0;
|
||||
16EA6;BERIA ERFE CAPITAL LETTER HIRDEABO;Lu;0;L;;;;;N;;;;16EC1;
|
||||
16EA7;BERIA ERFE CAPITAL LETTER I;Lu;0;L;;;;;N;;;;16EC2;
|
||||
16EA8;BERIA ERFE CAPITAL LETTER DJAI;Lu;0;L;;;;;N;;;;16EC3;
|
||||
16EA9;BERIA ERFE CAPITAL LETTER KOBO;Lu;0;L;;;;;N;;;;16EC4;
|
||||
16EAA;BERIA ERFE CAPITAL LETTER LAKKO;Lu;0;L;;;;;N;;;;16EC5;
|
||||
16EAB;BERIA ERFE CAPITAL LETTER MERI;Lu;0;L;;;;;N;;;;16EC6;
|
||||
16EAC;BERIA ERFE CAPITAL LETTER NINI;Lu;0;L;;;;;N;;;;16EC7;
|
||||
16EAD;BERIA ERFE CAPITAL LETTER GNA;Lu;0;L;;;;;N;;;;16EC8;
|
||||
16EAE;BERIA ERFE CAPITAL LETTER NGAY;Lu;0;L;;;;;N;;;;16EC9;
|
||||
16EAF;BERIA ERFE CAPITAL LETTER OI;Lu;0;L;;;;;N;;;;16ECA;
|
||||
16EB0;BERIA ERFE CAPITAL LETTER PI;Lu;0;L;;;;;N;;;;16ECB;
|
||||
16EB1;BERIA ERFE CAPITAL LETTER ERIGO;Lu;0;L;;;;;N;;;;16ECC;
|
||||
16EB2;BERIA ERFE CAPITAL LETTER ERIGO TAMURA;Lu;0;L;;;;;N;;;;16ECD;
|
||||
16EB3;BERIA ERFE CAPITAL LETTER SERI;Lu;0;L;;;;;N;;;;16ECE;
|
||||
16EB4;BERIA ERFE CAPITAL LETTER SHEP;Lu;0;L;;;;;N;;;;16ECF;
|
||||
16EB5;BERIA ERFE CAPITAL LETTER TATASOUE;Lu;0;L;;;;;N;;;;16ED0;
|
||||
16EB6;BERIA ERFE CAPITAL LETTER UI;Lu;0;L;;;;;N;;;;16ED1;
|
||||
16EB7;BERIA ERFE CAPITAL LETTER WASSE;Lu;0;L;;;;;N;;;;16ED2;
|
||||
16EB8;BERIA ERFE CAPITAL LETTER AY;Lu;0;L;;;;;N;;;;16ED3;
|
||||
16EBB;BERIA ERFE SMALL LETTER ARKAB;Ll;0;L;;;;;N;;;16EA0;;16EA0
|
||||
16EBC;BERIA ERFE SMALL LETTER BASIGNA;Ll;0;L;;;;;N;;;16EA1;;16EA1
|
||||
16EBD;BERIA ERFE SMALL LETTER DARBAI;Ll;0;L;;;;;N;;;16EA2;;16EA2
|
||||
16EBE;BERIA ERFE SMALL LETTER EH;Ll;0;L;;;;;N;;;16EA3;;16EA3
|
||||
16EBF;BERIA ERFE SMALL LETTER FITKO;Ll;0;L;;;;;N;;;16EA4;;16EA4
|
||||
16EC0;BERIA ERFE SMALL LETTER GOWAY;Ll;0;L;;;;;N;;;16EA5;;16EA5
|
||||
16EC1;BERIA ERFE SMALL LETTER HIRDEABO;Ll;0;L;;;;;N;;;16EA6;;16EA6
|
||||
16EC2;BERIA ERFE SMALL LETTER I;Ll;0;L;;;;;N;;;16EA7;;16EA7
|
||||
16EC3;BERIA ERFE SMALL LETTER DJAI;Ll;0;L;;;;;N;;;16EA8;;16EA8
|
||||
16EC4;BERIA ERFE SMALL LETTER KOBO;Ll;0;L;;;;;N;;;16EA9;;16EA9
|
||||
16EC5;BERIA ERFE SMALL LETTER LAKKO;Ll;0;L;;;;;N;;;16EAA;;16EAA
|
||||
16EC6;BERIA ERFE SMALL LETTER MERI;Ll;0;L;;;;;N;;;16EAB;;16EAB
|
||||
16EC7;BERIA ERFE SMALL LETTER NINI;Ll;0;L;;;;;N;;;16EAC;;16EAC
|
||||
16EC8;BERIA ERFE SMALL LETTER GNA;Ll;0;L;;;;;N;;;16EAD;;16EAD
|
||||
16EC9;BERIA ERFE SMALL LETTER NGAY;Ll;0;L;;;;;N;;;16EAE;;16EAE
|
||||
16ECA;BERIA ERFE SMALL LETTER OI;Ll;0;L;;;;;N;;;16EAF;;16EAF
|
||||
16ECB;BERIA ERFE SMALL LETTER PI;Ll;0;L;;;;;N;;;16EB0;;16EB0
|
||||
16ECC;BERIA ERFE SMALL LETTER ERIGO;Ll;0;L;;;;;N;;;16EB1;;16EB1
|
||||
16ECD;BERIA ERFE SMALL LETTER ERIGO TAMURA;Ll;0;L;;;;;N;;;16EB2;;16EB2
|
||||
16ECE;BERIA ERFE SMALL LETTER SERI;Ll;0;L;;;;;N;;;16EB3;;16EB3
|
||||
16ECF;BERIA ERFE SMALL LETTER SHEP;Ll;0;L;;;;;N;;;16EB4;;16EB4
|
||||
16ED0;BERIA ERFE SMALL LETTER TATASOUE;Ll;0;L;;;;;N;;;16EB5;;16EB5
|
||||
16ED1;BERIA ERFE SMALL LETTER UI;Ll;0;L;;;;;N;;;16EB6;;16EB6
|
||||
16ED2;BERIA ERFE SMALL LETTER WASSE;Ll;0;L;;;;;N;;;16EB7;;16EB7
|
||||
16ED3;BERIA ERFE SMALL LETTER AY;Ll;0;L;;;;;N;;;16EB8;;16EB8
|
||||
16F00;MIAO LETTER PA;Lo;0;L;;;;;N;;;;;
|
||||
16F01;MIAO LETTER BA;Lo;0;L;;;;;N;;;;;
|
||||
16F02;MIAO LETTER YI PA;Lo;0;L;;;;;N;;;;;
|
||||
|
|
@ -30280,8 +30494,13 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;;
|
|||
16FE4;KHITAN SMALL SCRIPT FILLER;Mn;0;NSM;;;;;N;;;;;
|
||||
16FF0;VIETNAMESE ALTERNATE READING MARK CA;Mc;6;L;;;;;N;;;;;
|
||||
16FF1;VIETNAMESE ALTERNATE READING MARK NHAY;Mc;6;L;;;;;N;;;;;
|
||||
16FF2;CHINESE SMALL SIMPLIFIED ER;Lm;0;L;;;;;N;;;;;
|
||||
16FF3;CHINESE SMALL TRADITIONAL ER;Lm;0;L;;;;;N;;;;;
|
||||
16FF4;YANGQIN SIGN SLOW ONE BEAT;Nl;0;L;;;;1;N;;;;;
|
||||
16FF5;YANGQIN SIGN SLOW THREE HALF BEATS;Nl;0;L;;;;3/2;N;;;;;
|
||||
16FF6;YANGQIN SIGN SLOW TWO BEATS;Nl;0;L;;;;2;N;;;;;
|
||||
17000;<Tangut Ideograph, First>;Lo;0;L;;;;;N;;;;;
|
||||
187F7;<Tangut Ideograph, Last>;Lo;0;L;;;;;N;;;;;
|
||||
187FF;<Tangut Ideograph, Last>;Lo;0;L;;;;;N;;;;;
|
||||
18800;TANGUT COMPONENT-001;Lo;0;L;;;;;N;;;;;
|
||||
18801;TANGUT COMPONENT-002;Lo;0;L;;;;;N;;;;;
|
||||
18802;TANGUT COMPONENT-003;Lo;0;L;;;;;N;;;;;
|
||||
|
|
@ -31522,7 +31741,122 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;;
|
|||
18CD5;KHITAN SMALL SCRIPT CHARACTER-18CD5;Lo;0;L;;;;;N;;;;;
|
||||
18CFF;KHITAN SMALL SCRIPT CHARACTER-18CFF;Lo;0;L;;;;;N;;;;;
|
||||
18D00;<Tangut Ideograph Supplement, First>;Lo;0;L;;;;;N;;;;;
|
||||
18D08;<Tangut Ideograph Supplement, Last>;Lo;0;L;;;;;N;;;;;
|
||||
18D1E;<Tangut Ideograph Supplement, Last>;Lo;0;L;;;;;N;;;;;
|
||||
18D80;TANGUT COMPONENT-769;Lo;0;L;;;;;N;;;;;
|
||||
18D81;TANGUT COMPONENT-770;Lo;0;L;;;;;N;;;;;
|
||||
18D82;TANGUT COMPONENT-771;Lo;0;L;;;;;N;;;;;
|
||||
18D83;TANGUT COMPONENT-772;Lo;0;L;;;;;N;;;;;
|
||||
18D84;TANGUT COMPONENT-773;Lo;0;L;;;;;N;;;;;
|
||||
18D85;TANGUT COMPONENT-774;Lo;0;L;;;;;N;;;;;
|
||||
18D86;TANGUT COMPONENT-775;Lo;0;L;;;;;N;;;;;
|
||||
18D87;TANGUT COMPONENT-776;Lo;0;L;;;;;N;;;;;
|
||||
18D88;TANGUT COMPONENT-777;Lo;0;L;;;;;N;;;;;
|
||||
18D89;TANGUT COMPONENT-778;Lo;0;L;;;;;N;;;;;
|
||||
18D8A;TANGUT COMPONENT-779;Lo;0;L;;;;;N;;;;;
|
||||
18D8B;TANGUT COMPONENT-780;Lo;0;L;;;;;N;;;;;
|
||||
18D8C;TANGUT COMPONENT-781;Lo;0;L;;;;;N;;;;;
|
||||
18D8D;TANGUT COMPONENT-782;Lo;0;L;;;;;N;;;;;
|
||||
18D8E;TANGUT COMPONENT-783;Lo;0;L;;;;;N;;;;;
|
||||
18D8F;TANGUT COMPONENT-784;Lo;0;L;;;;;N;;;;;
|
||||
18D90;TANGUT COMPONENT-785;Lo;0;L;;;;;N;;;;;
|
||||
18D91;TANGUT COMPONENT-786;Lo;0;L;;;;;N;;;;;
|
||||
18D92;TANGUT COMPONENT-787;Lo;0;L;;;;;N;;;;;
|
||||
18D93;TANGUT COMPONENT-788;Lo;0;L;;;;;N;;;;;
|
||||
18D94;TANGUT COMPONENT-789;Lo;0;L;;;;;N;;;;;
|
||||
18D95;TANGUT COMPONENT-790;Lo;0;L;;;;;N;;;;;
|
||||
18D96;TANGUT COMPONENT-791;Lo;0;L;;;;;N;;;;;
|
||||
18D97;TANGUT COMPONENT-792;Lo;0;L;;;;;N;;;;;
|
||||
18D98;TANGUT COMPONENT-793;Lo;0;L;;;;;N;;;;;
|
||||
18D99;TANGUT COMPONENT-794;Lo;0;L;;;;;N;;;;;
|
||||
18D9A;TANGUT COMPONENT-795;Lo;0;L;;;;;N;;;;;
|
||||
18D9B;TANGUT COMPONENT-796;Lo;0;L;;;;;N;;;;;
|
||||
18D9C;TANGUT COMPONENT-797;Lo;0;L;;;;;N;;;;;
|
||||
18D9D;TANGUT COMPONENT-798;Lo;0;L;;;;;N;;;;;
|
||||
18D9E;TANGUT COMPONENT-799;Lo;0;L;;;;;N;;;;;
|
||||
18D9F;TANGUT COMPONENT-800;Lo;0;L;;;;;N;;;;;
|
||||
18DA0;TANGUT COMPONENT-801;Lo;0;L;;;;;N;;;;;
|
||||
18DA1;TANGUT COMPONENT-802;Lo;0;L;;;;;N;;;;;
|
||||
18DA2;TANGUT COMPONENT-803;Lo;0;L;;;;;N;;;;;
|
||||
18DA3;TANGUT COMPONENT-804;Lo;0;L;;;;;N;;;;;
|
||||
18DA4;TANGUT COMPONENT-805;Lo;0;L;;;;;N;;;;;
|
||||
18DA5;TANGUT COMPONENT-806;Lo;0;L;;;;;N;;;;;
|
||||
18DA6;TANGUT COMPONENT-807;Lo;0;L;;;;;N;;;;;
|
||||
18DA7;TANGUT COMPONENT-808;Lo;0;L;;;;;N;;;;;
|
||||
18DA8;TANGUT COMPONENT-809;Lo;0;L;;;;;N;;;;;
|
||||
18DA9;TANGUT COMPONENT-810;Lo;0;L;;;;;N;;;;;
|
||||
18DAA;TANGUT COMPONENT-811;Lo;0;L;;;;;N;;;;;
|
||||
18DAB;TANGUT COMPONENT-812;Lo;0;L;;;;;N;;;;;
|
||||
18DAC;TANGUT COMPONENT-813;Lo;0;L;;;;;N;;;;;
|
||||
18DAD;TANGUT COMPONENT-814;Lo;0;L;;;;;N;;;;;
|
||||
18DAE;TANGUT COMPONENT-815;Lo;0;L;;;;;N;;;;;
|
||||
18DAF;TANGUT COMPONENT-816;Lo;0;L;;;;;N;;;;;
|
||||
18DB0;TANGUT COMPONENT-817;Lo;0;L;;;;;N;;;;;
|
||||
18DB1;TANGUT COMPONENT-818;Lo;0;L;;;;;N;;;;;
|
||||
18DB2;TANGUT COMPONENT-819;Lo;0;L;;;;;N;;;;;
|
||||
18DB3;TANGUT COMPONENT-820;Lo;0;L;;;;;N;;;;;
|
||||
18DB4;TANGUT COMPONENT-821;Lo;0;L;;;;;N;;;;;
|
||||
18DB5;TANGUT COMPONENT-822;Lo;0;L;;;;;N;;;;;
|
||||
18DB6;TANGUT COMPONENT-823;Lo;0;L;;;;;N;;;;;
|
||||
18DB7;TANGUT COMPONENT-824;Lo;0;L;;;;;N;;;;;
|
||||
18DB8;TANGUT COMPONENT-825;Lo;0;L;;;;;N;;;;;
|
||||
18DB9;TANGUT COMPONENT-826;Lo;0;L;;;;;N;;;;;
|
||||
18DBA;TANGUT COMPONENT-827;Lo;0;L;;;;;N;;;;;
|
||||
18DBB;TANGUT COMPONENT-828;Lo;0;L;;;;;N;;;;;
|
||||
18DBC;TANGUT COMPONENT-829;Lo;0;L;;;;;N;;;;;
|
||||
18DBD;TANGUT COMPONENT-830;Lo;0;L;;;;;N;;;;;
|
||||
18DBE;TANGUT COMPONENT-831;Lo;0;L;;;;;N;;;;;
|
||||
18DBF;TANGUT COMPONENT-832;Lo;0;L;;;;;N;;;;;
|
||||
18DC0;TANGUT COMPONENT-833;Lo;0;L;;;;;N;;;;;
|
||||
18DC1;TANGUT COMPONENT-834;Lo;0;L;;;;;N;;;;;
|
||||
18DC2;TANGUT COMPONENT-835;Lo;0;L;;;;;N;;;;;
|
||||
18DC3;TANGUT COMPONENT-836;Lo;0;L;;;;;N;;;;;
|
||||
18DC4;TANGUT COMPONENT-837;Lo;0;L;;;;;N;;;;;
|
||||
18DC5;TANGUT COMPONENT-838;Lo;0;L;;;;;N;;;;;
|
||||
18DC6;TANGUT COMPONENT-839;Lo;0;L;;;;;N;;;;;
|
||||
18DC7;TANGUT COMPONENT-840;Lo;0;L;;;;;N;;;;;
|
||||
18DC8;TANGUT COMPONENT-841;Lo;0;L;;;;;N;;;;;
|
||||
18DC9;TANGUT COMPONENT-842;Lo;0;L;;;;;N;;;;;
|
||||
18DCA;TANGUT COMPONENT-843;Lo;0;L;;;;;N;;;;;
|
||||
18DCB;TANGUT COMPONENT-844;Lo;0;L;;;;;N;;;;;
|
||||
18DCC;TANGUT COMPONENT-845;Lo;0;L;;;;;N;;;;;
|
||||
18DCD;TANGUT COMPONENT-846;Lo;0;L;;;;;N;;;;;
|
||||
18DCE;TANGUT COMPONENT-847;Lo;0;L;;;;;N;;;;;
|
||||
18DCF;TANGUT COMPONENT-848;Lo;0;L;;;;;N;;;;;
|
||||
18DD0;TANGUT COMPONENT-849;Lo;0;L;;;;;N;;;;;
|
||||
18DD1;TANGUT COMPONENT-850;Lo;0;L;;;;;N;;;;;
|
||||
18DD2;TANGUT COMPONENT-851;Lo;0;L;;;;;N;;;;;
|
||||
18DD3;TANGUT COMPONENT-852;Lo;0;L;;;;;N;;;;;
|
||||
18DD4;TANGUT COMPONENT-853;Lo;0;L;;;;;N;;;;;
|
||||
18DD5;TANGUT COMPONENT-854;Lo;0;L;;;;;N;;;;;
|
||||
18DD6;TANGUT COMPONENT-855;Lo;0;L;;;;;N;;;;;
|
||||
18DD7;TANGUT COMPONENT-856;Lo;0;L;;;;;N;;;;;
|
||||
18DD8;TANGUT COMPONENT-857;Lo;0;L;;;;;N;;;;;
|
||||
18DD9;TANGUT COMPONENT-858;Lo;0;L;;;;;N;;;;;
|
||||
18DDA;TANGUT COMPONENT-859;Lo;0;L;;;;;N;;;;;
|
||||
18DDB;TANGUT COMPONENT-860;Lo;0;L;;;;;N;;;;;
|
||||
18DDC;TANGUT COMPONENT-861;Lo;0;L;;;;;N;;;;;
|
||||
18DDD;TANGUT COMPONENT-862;Lo;0;L;;;;;N;;;;;
|
||||
18DDE;TANGUT COMPONENT-863;Lo;0;L;;;;;N;;;;;
|
||||
18DDF;TANGUT COMPONENT-864;Lo;0;L;;;;;N;;;;;
|
||||
18DE0;TANGUT COMPONENT-865;Lo;0;L;;;;;N;;;;;
|
||||
18DE1;TANGUT COMPONENT-866;Lo;0;L;;;;;N;;;;;
|
||||
18DE2;TANGUT COMPONENT-867;Lo;0;L;;;;;N;;;;;
|
||||
18DE3;TANGUT COMPONENT-868;Lo;0;L;;;;;N;;;;;
|
||||
18DE4;TANGUT COMPONENT-869;Lo;0;L;;;;;N;;;;;
|
||||
18DE5;TANGUT COMPONENT-870;Lo;0;L;;;;;N;;;;;
|
||||
18DE6;TANGUT COMPONENT-871;Lo;0;L;;;;;N;;;;;
|
||||
18DE7;TANGUT COMPONENT-872;Lo;0;L;;;;;N;;;;;
|
||||
18DE8;TANGUT COMPONENT-873;Lo;0;L;;;;;N;;;;;
|
||||
18DE9;TANGUT COMPONENT-874;Lo;0;L;;;;;N;;;;;
|
||||
18DEA;TANGUT COMPONENT-875;Lo;0;L;;;;;N;;;;;
|
||||
18DEB;TANGUT COMPONENT-876;Lo;0;L;;;;;N;;;;;
|
||||
18DEC;TANGUT COMPONENT-877;Lo;0;L;;;;;N;;;;;
|
||||
18DED;TANGUT COMPONENT-878;Lo;0;L;;;;;N;;;;;
|
||||
18DEE;TANGUT COMPONENT-879;Lo;0;L;;;;;N;;;;;
|
||||
18DEF;TANGUT COMPONENT-880;Lo;0;L;;;;;N;;;;;
|
||||
18DF0;TANGUT COMPONENT-881;Lo;0;L;;;;;N;;;;;
|
||||
18DF1;TANGUT COMPONENT-882;Lo;0;L;;;;;N;;;;;
|
||||
18DF2;TANGUT COMPONENT-883;Lo;0;L;;;;;N;;;;;
|
||||
1AFF0;KATAKANA LETTER MINNAN TONE-2;Lm;0;L;;;;;N;;;;;
|
||||
1AFF1;KATAKANA LETTER MINNAN TONE-3;Lm;0;L;;;;;N;;;;;
|
||||
1AFF2;KATAKANA LETTER MINNAN TONE-4;Lm;0;L;;;;;N;;;;;
|
||||
|
|
@ -32629,6 +32963,9 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;;
|
|||
1CCF7;OUTLINED DIGIT SEVEN;Nd;0;EN;<font> 0037;7;7;7;N;;;;;
|
||||
1CCF8;OUTLINED DIGIT EIGHT;Nd;0;EN;<font> 0038;8;8;8;N;;;;;
|
||||
1CCF9;OUTLINED DIGIT NINE;Nd;0;EN;<font> 0039;9;9;9;N;;;;;
|
||||
1CCFA;SNAKE SYMBOL;So;0;ON;;;;;N;;;;;
|
||||
1CCFB;FLYING SAUCER SYMBOL;So;0;ON;;;;;N;;;;;
|
||||
1CCFC;NOSE SYMBOL;So;0;ON;;;;;N;;;;;
|
||||
1CD00;BLOCK OCTANT-3;So;0;ON;;;;;N;;;;;
|
||||
1CD01;BLOCK OCTANT-23;So;0;ON;;;;;N;;;;;
|
||||
1CD02;BLOCK OCTANT-123;So;0;ON;;;;;N;;;;;
|
||||
|
|
@ -33065,6 +33402,46 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;;
|
|||
1CEB1;KEYHOLE;So;0;ON;;;;;N;;;;;
|
||||
1CEB2;OLD PERSONAL COMPUTER WITH MONITOR IN PORTRAIT ORIENTATION;So;0;ON;;;;;N;;;;;
|
||||
1CEB3;BLACK RIGHT TRIANGLE CARET;So;0;ON;;;;;N;;;;;
|
||||
1CEBA;FRAGILE SYMBOL;So;0;ON;;;;;N;;;;;
|
||||
1CEBB;OFFICE BUILDING SYMBOL;So;0;ON;;;;;N;;;;;
|
||||
1CEBC;TREE SYMBOL;So;0;ON;;;;;N;;;;;
|
||||
1CEBD;APPLE SYMBOL;So;0;ON;;;;;N;;;;;
|
||||
1CEBE;CHERRY SYMBOL;So;0;ON;;;;;N;;;;;
|
||||
1CEBF;STRAWBERRY SYMBOL;So;0;ON;;;;;N;;;;;
|
||||
1CEC0;HEBE;So;0;ON;;;;;N;;;;;
|
||||
1CEC1;IRIS;So;0;ON;;;;;N;;;;;
|
||||
1CEC2;FLORA;So;0;ON;;;;;N;;;;;
|
||||
1CEC3;METIS;So;0;ON;;;;;N;;;;;
|
||||
1CEC4;PARTHENOPE;So;0;ON;;;;;N;;;;;
|
||||
1CEC5;VICTORIA;So;0;ON;;;;;N;;;;;
|
||||
1CEC6;EGERIA;So;0;ON;;;;;N;;;;;
|
||||
1CEC7;IRENE;So;0;ON;;;;;N;;;;;
|
||||
1CEC8;EUNOMIA;So;0;ON;;;;;N;;;;;
|
||||
1CEC9;PSYCHE;So;0;ON;;;;;N;;;;;
|
||||
1CECA;THETIS;So;0;ON;;;;;N;;;;;
|
||||
1CECB;MELPOMENE;So;0;ON;;;;;N;;;;;
|
||||
1CECC;FORTUNA;So;0;ON;;;;;N;;;;;
|
||||
1CECD;ASTRONOMICAL SYMBOL FOR ASTEROID PROSERPINA;So;0;ON;;;;;N;;;;;
|
||||
1CECE;BELLONA;So;0;ON;;;;;N;;;;;
|
||||
1CECF;AMPHITRITE;So;0;ON;;;;;N;;;;;
|
||||
1CED0;LEUKOTHEA;So;0;ON;;;;;N;;;;;
|
||||
1CEE0;GEOMANTIC FIGURE POPULUS;So;0;ON;;;;;N;;;;;
|
||||
1CEE1;GEOMANTIC FIGURE TRISTITIA;So;0;ON;;;;;N;;;;;
|
||||
1CEE2;GEOMANTIC FIGURE ALBUS;So;0;ON;;;;;N;;;;;
|
||||
1CEE3;GEOMANTIC FIGURE FORTUNA MAJOR;So;0;ON;;;;;N;;;;;
|
||||
1CEE4;GEOMANTIC FIGURE RUBEUS;So;0;ON;;;;;N;;;;;
|
||||
1CEE5;GEOMANTIC FIGURE ACQUISITIO;So;0;ON;;;;;N;;;;;
|
||||
1CEE6;GEOMANTIC FIGURE CONJUNCTIO;So;0;ON;;;;;N;;;;;
|
||||
1CEE7;GEOMANTIC FIGURE CAPUT DRACONIS;So;0;ON;;;;;N;;;;;
|
||||
1CEE8;GEOMANTIC FIGURE LAETITIA;So;0;ON;;;;;N;;;;;
|
||||
1CEE9;GEOMANTIC FIGURE CARCER;So;0;ON;;;;;N;;;;;
|
||||
1CEEA;GEOMANTIC FIGURE AMISSIO;So;0;ON;;;;;N;;;;;
|
||||
1CEEB;GEOMANTIC FIGURE PUELLA;So;0;ON;;;;;N;;;;;
|
||||
1CEEC;GEOMANTIC FIGURE FORTUNA MINOR;So;0;ON;;;;;N;;;;;
|
||||
1CEED;GEOMANTIC FIGURE PUER;So;0;ON;;;;;N;;;;;
|
||||
1CEEE;GEOMANTIC FIGURE CAUDA DRACONIS;So;0;ON;;;;;N;;;;;
|
||||
1CEEF;GEOMANTIC FIGURE VIA;So;0;ON;;;;;N;;;;;
|
||||
1CEF0;MEDIUM SMALL WHITE CIRCLE WITH HORIZONTAL BAR;Sm;0;ON;;;;;N;;;;;
|
||||
1CF00;ZNAMENNY COMBINING MARK GORAZDO NIZKO S KRYZHEM ON LEFT;Mn;0;NSM;;;;;N;;;;;
|
||||
1CF01;ZNAMENNY COMBINING MARK NIZKO S KRYZHEM ON LEFT;Mn;0;NSM;;;;;N;;;;;
|
||||
1CF02;ZNAMENNY COMBINING MARK TSATA ON LEFT;Mn;0;NSM;;;;;N;;;;;
|
||||
|
|
@ -36004,6 +36381,61 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;;
|
|||
1E5F9;OL ONAL DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;;
|
||||
1E5FA;OL ONAL DIGIT NINE;Nd;0;L;;9;9;9;N;;;;;
|
||||
1E5FF;OL ONAL ABBREVIATION SIGN;Po;0;L;;;;;N;;;;;
|
||||
1E6C0;TAI YO LETTER LOW KO;Lo;0;L;;;;;N;;;;;
|
||||
1E6C1;TAI YO LETTER HIGH KO;Lo;0;L;;;;;N;;;;;
|
||||
1E6C2;TAI YO LETTER LOW KHO;Lo;0;L;;;;;N;;;;;
|
||||
1E6C3;TAI YO LETTER HIGH KHO;Lo;0;L;;;;;N;;;;;
|
||||
1E6C4;TAI YO LETTER GO;Lo;0;L;;;;;N;;;;;
|
||||
1E6C5;TAI YO LETTER NGO;Lo;0;L;;;;;N;;;;;
|
||||
1E6C6;TAI YO LETTER CO;Lo;0;L;;;;;N;;;;;
|
||||
1E6C7;TAI YO LETTER LOW XO;Lo;0;L;;;;;N;;;;;
|
||||
1E6C8;TAI YO LETTER HIGH XO;Lo;0;L;;;;;N;;;;;
|
||||
1E6C9;TAI YO LETTER LOW NYO;Lo;0;L;;;;;N;;;;;
|
||||
1E6CA;TAI YO LETTER HIGH NYO;Lo;0;L;;;;;N;;;;;
|
||||
1E6CB;TAI YO LETTER DO;Lo;0;L;;;;;N;;;;;
|
||||
1E6CC;TAI YO LETTER LOW TO;Lo;0;L;;;;;N;;;;;
|
||||
1E6CD;TAI YO LETTER HIGH TO;Lo;0;L;;;;;N;;;;;
|
||||
1E6CE;TAI YO LETTER THO;Lo;0;L;;;;;N;;;;;
|
||||
1E6CF;TAI YO LETTER NO;Lo;0;L;;;;;N;;;;;
|
||||
1E6D0;TAI YO LETTER BO;Lo;0;L;;;;;N;;;;;
|
||||
1E6D1;TAI YO LETTER LOW PO;Lo;0;L;;;;;N;;;;;
|
||||
1E6D2;TAI YO LETTER HIGH PO;Lo;0;L;;;;;N;;;;;
|
||||
1E6D3;TAI YO LETTER PHO;Lo;0;L;;;;;N;;;;;
|
||||
1E6D4;TAI YO LETTER LOW FO;Lo;0;L;;;;;N;;;;;
|
||||
1E6D5;TAI YO LETTER HIGH FO;Lo;0;L;;;;;N;;;;;
|
||||
1E6D6;TAI YO LETTER MO;Lo;0;L;;;;;N;;;;;
|
||||
1E6D7;TAI YO LETTER YO;Lo;0;L;;;;;N;;;;;
|
||||
1E6D8;TAI YO LETTER LO;Lo;0;L;;;;;N;;;;;
|
||||
1E6D9;TAI YO LETTER VO;Lo;0;L;;;;;N;;;;;
|
||||
1E6DA;TAI YO LETTER LOW HO;Lo;0;L;;;;;N;;;;;
|
||||
1E6DB;TAI YO LETTER HIGH HO;Lo;0;L;;;;;N;;;;;
|
||||
1E6DC;TAI YO LETTER QO;Lo;0;L;;;;;N;;;;;
|
||||
1E6DD;TAI YO LETTER LOW KVO;Lo;0;L;;;;;N;;;;;
|
||||
1E6DE;TAI YO LETTER HIGH KVO;Lo;0;L;;;;;N;;;;;
|
||||
1E6E0;TAI YO LETTER AA;Lo;0;L;;;;;N;;;;;
|
||||
1E6E1;TAI YO LETTER I;Lo;0;L;;;;;N;;;;;
|
||||
1E6E2;TAI YO LETTER UE;Lo;0;L;;;;;N;;;;;
|
||||
1E6E3;TAI YO SIGN UE;Mn;230;NSM;;;;;N;;;;;
|
||||
1E6E4;TAI YO LETTER U;Lo;0;L;;;;;N;;;;;
|
||||
1E6E5;TAI YO LETTER AE;Lo;0;L;;;;;N;;;;;
|
||||
1E6E6;TAI YO SIGN AU;Mn;230;NSM;;;;;N;;;;;
|
||||
1E6E7;TAI YO LETTER O;Lo;0;L;;;;;N;;;;;
|
||||
1E6E8;TAI YO LETTER E;Lo;0;L;;;;;N;;;;;
|
||||
1E6E9;TAI YO LETTER IA;Lo;0;L;;;;;N;;;;;
|
||||
1E6EA;TAI YO LETTER UEA;Lo;0;L;;;;;N;;;;;
|
||||
1E6EB;TAI YO LETTER UA;Lo;0;L;;;;;N;;;;;
|
||||
1E6EC;TAI YO LETTER OO;Lo;0;L;;;;;N;;;;;
|
||||
1E6ED;TAI YO LETTER AUE;Lo;0;L;;;;;N;;;;;
|
||||
1E6EE;TAI YO SIGN AY;Mn;230;NSM;;;;;N;;;;;
|
||||
1E6EF;TAI YO SIGN ANG;Mn;230;NSM;;;;;N;;;;;
|
||||
1E6F0;TAI YO LETTER AN;Lo;0;L;;;;;N;;;;;
|
||||
1E6F1;TAI YO LETTER AM;Lo;0;L;;;;;N;;;;;
|
||||
1E6F2;TAI YO LETTER AK;Lo;0;L;;;;;N;;;;;
|
||||
1E6F3;TAI YO LETTER AT;Lo;0;L;;;;;N;;;;;
|
||||
1E6F4;TAI YO LETTER AP;Lo;0;L;;;;;N;;;;;
|
||||
1E6F5;TAI YO SIGN OM;Mn;230;NSM;;;;;N;;;;;
|
||||
1E6FE;TAI YO SYMBOL MUEANG;Lo;0;L;;;;;N;;;;;
|
||||
1E6FF;TAI YO XAM LAI;Lm;0;L;;;;;N;;;;;
|
||||
1E7E0;ETHIOPIC SYLLABLE HHYA;Lo;0;L;;;;;N;;;;;
|
||||
1E7E1;ETHIOPIC SYLLABLE HHYU;Lo;0;L;;;;;N;;;;;
|
||||
1E7E2;ETHIOPIC SYLLABLE HHYI;Lo;0;L;;;;;N;;;;;
|
||||
|
|
@ -38079,6 +38511,7 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;;
|
|||
1F6D5;HINDU TEMPLE;So;0;ON;;;;;N;;;;;
|
||||
1F6D6;HUT;So;0;ON;;;;;N;;;;;
|
||||
1F6D7;ELEVATOR;So;0;ON;;;;;N;;;;;
|
||||
1F6D8;LANDSLIDE;So;0;ON;;;;;N;;;;;
|
||||
1F6DC;WIRELESS;So;0;ON;;;;;N;;;;;
|
||||
1F6DD;PLAYGROUND SLIDE;So;0;ON;;;;;N;;;;;
|
||||
1F6DE;WHEEL;So;0;ON;;;;;N;;;;;
|
||||
|
|
@ -38228,6 +38661,10 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;;
|
|||
1F774;LOT OF FORTUNE;So;0;ON;;;;;N;;;;;
|
||||
1F775;OCCULTATION;So;0;ON;;;;;N;;;;;
|
||||
1F776;LUNAR ECLIPSE;So;0;ON;;;;;N;;;;;
|
||||
1F777;VESTA FORM TWO;So;0;ON;;;;;N;;;;;
|
||||
1F778;ASTRAEA FORM TWO;So;0;ON;;;;;N;;;;;
|
||||
1F779;HYGIEA FORM TWO;So;0;ON;;;;;N;;;;;
|
||||
1F77A;PARTHENOPE FORM TWO;So;0;ON;;;;;N;;;;;
|
||||
1F77B;HAUMEA;So;0;ON;;;;;N;;;;;
|
||||
1F77C;MAKEMAKE;So;0;ON;;;;;N;;;;;
|
||||
1F77D;GONGGONG;So;0;ON;;;;;N;;;;;
|
||||
|
|
@ -38498,6 +38935,15 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;;
|
|||
1F8BB;SOUTH WEST ARROW FROM BAR;So;0;ON;;;;;N;;;;;
|
||||
1F8C0;LEFTWARDS ARROW FROM DOWNWARDS ARROW;So;0;ON;;;;;N;;;;;
|
||||
1F8C1;RIGHTWARDS ARROW FROM DOWNWARDS ARROW;So;0;ON;;;;;N;;;;;
|
||||
1F8D0;LONG RIGHTWARDS ARROW OVER LONG LEFTWARDS ARROW;Sm;0;ON;;;;;N;;;;;
|
||||
1F8D1;LONG RIGHTWARDS HARPOON OVER LONG LEFTWARDS HARPOON;Sm;0;ON;;;;;N;;;;;
|
||||
1F8D2;LONG RIGHTWARDS HARPOON ABOVE SHORT LEFTWARDS HARPOON;Sm;0;ON;;;;;N;;;;;
|
||||
1F8D3;SHORT RIGHTWARDS HARPOON ABOVE LONG LEFTWARDS HARPOON;Sm;0;ON;;;;;N;;;;;
|
||||
1F8D4;LONG LEFTWARDS HARPOON ABOVE SHORT RIGHTWARDS HARPOON;Sm;0;ON;;;;;N;;;;;
|
||||
1F8D5;SHORT LEFTWARDS HARPOON ABOVE LONG RIGHTWARDS HARPOON;Sm;0;ON;;;;;N;;;;;
|
||||
1F8D6;LONG RIGHTWARDS ARROW THROUGH X;Sm;0;ON;;;;;N;;;;;
|
||||
1F8D7;LONG RIGHTWARDS ARROW WITH DOUBLE SLASH;Sm;0;ON;;;;;N;;;;;
|
||||
1F8D8;LONG LEFT RIGHT ARROW WITH DEPENDENT LOBE;Sm;0;ON;;;;;N;;;;;
|
||||
1F900;CIRCLED CROSS FORMEE WITH FOUR DOTS;So;0;ON;;;;;N;;;;;
|
||||
1F901;CIRCLED CROSS FORMEE WITH TWO DOTS;So;0;ON;;;;;N;;;;;
|
||||
1F902;CIRCLED CROSS FORMEE;So;0;ON;;;;;N;;;;;
|
||||
|
|
@ -38838,6 +39284,10 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;;
|
|||
1FA51;BLACK CHESS KNIGHT-QUEEN;So;0;ON;;;;;N;;;;;
|
||||
1FA52;BLACK CHESS KNIGHT-ROOK;So;0;ON;;;;;N;;;;;
|
||||
1FA53;BLACK CHESS KNIGHT-BISHOP;So;0;ON;;;;;N;;;;;
|
||||
1FA54;WHITE CHESS FERZ;So;0;ON;;;;;N;;;;;
|
||||
1FA55;WHITE CHESS ALFIL;So;0;ON;;;;;N;;;;;
|
||||
1FA56;BLACK CHESS FERZ;So;0;ON;;;;;N;;;;;
|
||||
1FA57;BLACK CHESS ALFIL;So;0;ON;;;;;N;;;;;
|
||||
1FA60;XIANGQI RED GENERAL;So;0;ON;;;;;N;;;;;
|
||||
1FA61;XIANGQI RED MANDARIN;So;0;ON;;;;;N;;;;;
|
||||
1FA62;XIANGQI RED ELEPHANT;So;0;ON;;;;;N;;;;;
|
||||
|
|
@ -38875,6 +39325,8 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;;
|
|||
1FA87;MARACAS;So;0;ON;;;;;N;;;;;
|
||||
1FA88;FLUTE;So;0;ON;;;;;N;;;;;
|
||||
1FA89;HARP;So;0;ON;;;;;N;;;;;
|
||||
1FA8A;TROMBONE;So;0;ON;;;;;N;;;;;
|
||||
1FA8E;TREASURE CHEST;So;0;ON;;;;;N;;;;;
|
||||
1FA8F;SHOVEL;So;0;ON;;;;;N;;;;;
|
||||
1FA90;RINGED PLANET;So;0;ON;;;;;N;;;;;
|
||||
1FA91;CHAIR;So;0;ON;;;;;N;;;;;
|
||||
|
|
@ -38931,6 +39383,8 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;;
|
|||
1FAC4;PREGNANT PERSON;So;0;ON;;;;;N;;;;;
|
||||
1FAC5;PERSON WITH CROWN;So;0;ON;;;;;N;;;;;
|
||||
1FAC6;FINGERPRINT;So;0;ON;;;;;N;;;;;
|
||||
1FAC8;HAIRY CREATURE;So;0;ON;;;;;N;;;;;
|
||||
1FACD;ORCA;So;0;ON;;;;;N;;;;;
|
||||
1FACE;MOOSE;So;0;ON;;;;;N;;;;;
|
||||
1FACF;DONKEY;So;0;ON;;;;;N;;;;;
|
||||
1FAD0;BLUEBERRIES;So;0;ON;;;;;N;;;;;
|
||||
|
|
@ -38957,6 +39411,8 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;;
|
|||
1FAE7;BUBBLES;So;0;ON;;;;;N;;;;;
|
||||
1FAE8;SHAKING FACE;So;0;ON;;;;;N;;;;;
|
||||
1FAE9;FACE WITH BAGS UNDER EYES;So;0;ON;;;;;N;;;;;
|
||||
1FAEA;DISTORTED FACE;So;0;ON;;;;;N;;;;;
|
||||
1FAEF;FIGHT CLOUD;So;0;ON;;;;;N;;;;;
|
||||
1FAF0;HAND WITH INDEX FINGER AND THUMB CROSSED;So;0;ON;;;;;N;;;;;
|
||||
1FAF1;RIGHTWARDS HAND;So;0;ON;;;;;N;;;;;
|
||||
1FAF2;LEFTWARDS HAND;So;0;ON;;;;;N;;;;;
|
||||
|
|
@ -39215,14 +39671,15 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;;
|
|||
1FBF7;SEGMENTED DIGIT SEVEN;Nd;0;EN;<font> 0037;7;7;7;N;;;;;
|
||||
1FBF8;SEGMENTED DIGIT EIGHT;Nd;0;EN;<font> 0038;8;8;8;N;;;;;
|
||||
1FBF9;SEGMENTED DIGIT NINE;Nd;0;EN;<font> 0039;9;9;9;N;;;;;
|
||||
1FBFA;ALARM BELL SYMBOL;So;0;ON;;;;;N;;;;;
|
||||
20000;<CJK Ideograph Extension B, First>;Lo;0;L;;;;;N;;;;;
|
||||
2A6DF;<CJK Ideograph Extension B, Last>;Lo;0;L;;;;;N;;;;;
|
||||
2A700;<CJK Ideograph Extension C, First>;Lo;0;L;;;;;N;;;;;
|
||||
2B739;<CJK Ideograph Extension C, Last>;Lo;0;L;;;;;N;;;;;
|
||||
2B73F;<CJK Ideograph Extension C, Last>;Lo;0;L;;;;;N;;;;;
|
||||
2B740;<CJK Ideograph Extension D, First>;Lo;0;L;;;;;N;;;;;
|
||||
2B81D;<CJK Ideograph Extension D, Last>;Lo;0;L;;;;;N;;;;;
|
||||
2B820;<CJK Ideograph Extension E, First>;Lo;0;L;;;;;N;;;;;
|
||||
2CEA1;<CJK Ideograph Extension E, Last>;Lo;0;L;;;;;N;;;;;
|
||||
2CEAD;<CJK Ideograph Extension E, Last>;Lo;0;L;;;;;N;;;;;
|
||||
2CEB0;<CJK Ideograph Extension F, First>;Lo;0;L;;;;;N;;;;;
|
||||
2EBE0;<CJK Ideograph Extension F, Last>;Lo;0;L;;;;;N;;;;;
|
||||
2EBF0;<CJK Ideograph Extension I, First>;Lo;0;L;;;;;N;;;;;
|
||||
|
|
@ -39773,6 +40230,8 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;;
|
|||
3134A;<CJK Ideograph Extension G, Last>;Lo;0;L;;;;;N;;;;;
|
||||
31350;<CJK Ideograph Extension H, First>;Lo;0;L;;;;;N;;;;;
|
||||
323AF;<CJK Ideograph Extension H, Last>;Lo;0;L;;;;;N;;;;;
|
||||
323B0;<CJK Ideograph Extension J, First>;Lo;0;L;;;;;N;;;;;
|
||||
33479;<CJK Ideograph Extension J, Last>;Lo;0;L;;;;;N;;;;;
|
||||
E0001;LANGUAGE TAG;Cf;0;BN;;;;;N;;;;;
|
||||
E0020;TAG SPACE;Cf;0;BN;;;;;N;;;;;
|
||||
E0021;TAG EXCLAMATION MARK;Cf;0;BN;;;;;N;;;;;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# WordBreakProperty-16.0.0.txt
|
||||
# Date: 2024-07-29, 16:27:36 GMT
|
||||
# © 2024 Unicode®, Inc.
|
||||
# WordBreakProperty-17.0.0.txt
|
||||
# Date: 2025-06-30, 06:20:49 GMT
|
||||
# © 2025 Unicode®, Inc.
|
||||
# Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries.
|
||||
# For terms of use and license, see https://www.unicode.org/terms_of_use.html
|
||||
#
|
||||
|
|
@ -283,7 +283,8 @@ FB46..FB4F ; Hebrew_Letter # Lo [10] HEBREW LETTER TSADI WITH DAGESH..HEBREW
|
|||
1A7F ; Extend # Mn TAI THAM COMBINING CRYPTOGRAMMIC DOT
|
||||
1AB0..1ABD ; Extend # Mn [14] COMBINING DOUBLED CIRCUMFLEX ACCENT..COMBINING PARENTHESES BELOW
|
||||
1ABE ; Extend # Me COMBINING PARENTHESES OVERLAY
|
||||
1ABF..1ACE ; Extend # Mn [16] COMBINING LATIN SMALL LETTER W BELOW..COMBINING LATIN SMALL LETTER INSULAR T
|
||||
1ABF..1ADD ; Extend # Mn [31] COMBINING LATIN SMALL LETTER W BELOW..COMBINING DOT-AND-RING BELOW
|
||||
1AE0..1AEB ; Extend # Mn [12] COMBINING LEFT TACK ABOVE..COMBINING DOUBLE RIGHTWARDS ARROW ABOVE
|
||||
1B00..1B03 ; Extend # Mn [4] BALINESE SIGN ULU RICEM..BALINESE SIGN SURANG
|
||||
1B04 ; Extend # Mc BALINESE SIGN BISAH
|
||||
1B34 ; Extend # Mn BALINESE SIGN REREKAN
|
||||
|
|
@ -409,7 +410,7 @@ FF9E..FF9F ; Extend # Lm [2] HALFWIDTH KATAKANA VOICED SOUND MARK..HALFWIDT
|
|||
10D24..10D27 ; Extend # Mn [4] HANIFI ROHINGYA SIGN HARBAHAY..HANIFI ROHINGYA SIGN TASSI
|
||||
10D69..10D6D ; Extend # Mn [5] GARAY VOWEL SIGN E..GARAY CONSONANT NASALIZATION MARK
|
||||
10EAB..10EAC ; Extend # Mn [2] YEZIDI COMBINING HAMZA MARK..YEZIDI COMBINING MADDA MARK
|
||||
10EFC..10EFF ; Extend # Mn [4] ARABIC COMBINING ALEF OVERLAY..ARABIC SMALL LOW WORD MADDA
|
||||
10EFA..10EFF ; Extend # Mn [6] ARABIC DOUBLE VERTICAL BAR BELOW..ARABIC SMALL LOW WORD MADDA
|
||||
10F46..10F50 ; Extend # Mn [11] SOGDIAN COMBINING DOT BELOW..SOGDIAN COMBINING STROKE BELOW
|
||||
10F82..10F85 ; Extend # Mn [4] OLD UYGHUR COMBINING DOT ABOVE..OLD UYGHUR COMBINING TWO DOTS BELOW
|
||||
11000 ; Extend # Mc BRAHMI SIGN CANDRABINDU
|
||||
|
|
@ -544,6 +545,12 @@ FF9E..FF9F ; Extend # Lm [2] HALFWIDTH KATAKANA VOICED SOUND MARK..HALFWIDT
|
|||
11A8A..11A96 ; Extend # Mn [13] SOYOMBO FINAL CONSONANT SIGN G..SOYOMBO SIGN ANUSVARA
|
||||
11A97 ; Extend # Mc SOYOMBO SIGN VISARGA
|
||||
11A98..11A99 ; Extend # Mn [2] SOYOMBO GEMINATION MARK..SOYOMBO SUBJOINER
|
||||
11B60 ; Extend # Mn SHARADA VOWEL SIGN OE
|
||||
11B61 ; Extend # Mc SHARADA VOWEL SIGN OOE
|
||||
11B62..11B64 ; Extend # Mn [3] SHARADA VOWEL SIGN UE..SHARADA VOWEL SIGN SHORT E
|
||||
11B65 ; Extend # Mc SHARADA VOWEL SIGN SHORT O
|
||||
11B66 ; Extend # Mn SHARADA VOWEL SIGN CANDRA E
|
||||
11B67 ; Extend # Mc SHARADA VOWEL SIGN CANDRA O
|
||||
11C2F ; Extend # Mc BHAIKSUKI VOWEL SIGN AA
|
||||
11C30..11C36 ; Extend # Mn [7] BHAIKSUKI VOWEL SIGN I..BHAIKSUKI VOWEL SIGN VOCALIC L
|
||||
11C38..11C3D ; Extend # Mn [6] BHAIKSUKI VOWEL SIGN E..BHAIKSUKI SIGN ANUSVARA
|
||||
|
|
@ -617,13 +624,17 @@ FF9E..FF9F ; Extend # Lm [2] HALFWIDTH KATAKANA VOICED SOUND MARK..HALFWIDT
|
|||
1E2EC..1E2EF ; Extend # Mn [4] WANCHO TONE TUP..WANCHO TONE KOINI
|
||||
1E4EC..1E4EF ; Extend # Mn [4] NAG MUNDARI SIGN MUHOR..NAG MUNDARI SIGN SUTUH
|
||||
1E5EE..1E5EF ; Extend # Mn [2] OL ONAL SIGN MU..OL ONAL SIGN IKIR
|
||||
1E6E3 ; Extend # Mn TAI YO SIGN UE
|
||||
1E6E6 ; Extend # Mn TAI YO SIGN AU
|
||||
1E6EE..1E6EF ; Extend # Mn [2] TAI YO SIGN AY..TAI YO SIGN ANG
|
||||
1E6F5 ; Extend # Mn TAI YO SIGN OM
|
||||
1E8D0..1E8D6 ; Extend # Mn [7] MENDE KIKAKUI COMBINING NUMBER TEENS..MENDE KIKAKUI COMBINING NUMBER MILLIONS
|
||||
1E944..1E94A ; Extend # Mn [7] ADLAM ALIF LENGTHENER..ADLAM NUKTA
|
||||
1F3FB..1F3FF ; Extend # Sk [5] EMOJI MODIFIER FITZPATRICK TYPE-1-2..EMOJI MODIFIER FITZPATRICK TYPE-6
|
||||
E0020..E007F ; Extend # Cf [96] TAG SPACE..CANCEL TAG
|
||||
E0100..E01EF ; Extend # Mn [240] VARIATION SELECTOR-17..VARIATION SELECTOR-256
|
||||
|
||||
# Total code points: 2605
|
||||
# Total code points: 2647
|
||||
|
||||
# ================================================
|
||||
|
||||
|
|
@ -679,6 +690,7 @@ FF71..FF9D ; Katakana # Lo [45] HALFWIDTH KATAKANA LETTER A..HALFWIDTH KATAK
|
|||
0061..007A ; ALetter # L& [26] LATIN SMALL LETTER A..LATIN SMALL LETTER Z
|
||||
00AA ; ALetter # Lo FEMININE ORDINAL INDICATOR
|
||||
00B5 ; ALetter # L& MICRO SIGN
|
||||
00B8 ; ALetter # Sk CEDILLA
|
||||
00BA ; ALetter # Lo MASCULINE ORDINAL INDICATOR
|
||||
00C0..00D6 ; ALetter # L& [23] LATIN CAPITAL LETTER A WITH GRAVE..LATIN CAPITAL LETTER O WITH DIAERESIS
|
||||
00D8..00F6 ; ALetter # L& [31] LATIN CAPITAL LETTER O WITH STROKE..LATIN SMALL LETTER O WITH DIAERESIS
|
||||
|
|
@ -687,8 +699,8 @@ FF71..FF9D ; Katakana # Lo [45] HALFWIDTH KATAKANA LETTER A..HALFWIDTH KATAK
|
|||
01BC..01BF ; ALetter # L& [4] LATIN CAPITAL LETTER TONE FIVE..LATIN LETTER WYNN
|
||||
01C0..01C3 ; ALetter # Lo [4] LATIN LETTER DENTAL CLICK..LATIN LETTER RETROFLEX CLICK
|
||||
01C4..0293 ; ALetter # L& [208] LATIN CAPITAL LETTER DZ WITH CARON..LATIN SMALL LETTER EZH WITH CURL
|
||||
0294 ; ALetter # Lo LATIN LETTER GLOTTAL STOP
|
||||
0295..02AF ; ALetter # L& [27] LATIN LETTER PHARYNGEAL VOICED FRICATIVE..LATIN SMALL LETTER TURNED H WITH FISHHOOK AND TAIL
|
||||
0294..0295 ; ALetter # Lo [2] LATIN LETTER GLOTTAL STOP..LATIN LETTER PHARYNGEAL VOICED FRICATIVE
|
||||
0296..02AF ; ALetter # L& [26] LATIN LETTER INVERTED GLOTTAL STOP..LATIN SMALL LETTER TURNED H WITH FISHHOOK AND TAIL
|
||||
02B0..02C1 ; ALetter # Lm [18] MODIFIER LETTER SMALL H..MODIFIER LETTER REVERSED GLOTTAL STOP
|
||||
02C2..02C5 ; ALetter # Sk [4] MODIFIER LETTER LEFT ARROWHEAD..MODIFIER LETTER DOWN ARROWHEAD
|
||||
02C6..02D1 ; ALetter # Lm [12] MODIFIER LETTER CIRCUMFLEX ACCENT..MODIFIER LETTER HALF TRIANGULAR COLON
|
||||
|
|
@ -745,7 +757,7 @@ FF71..FF9D ; Katakana # Lo [45] HALFWIDTH KATAKANA LETTER A..HALFWIDTH KATAK
|
|||
0840..0858 ; ALetter # Lo [25] MANDAIC LETTER HALQA..MANDAIC LETTER AIN
|
||||
0860..086A ; ALetter # Lo [11] SYRIAC LETTER MALAYALAM NGA..SYRIAC LETTER MALAYALAM SSA
|
||||
0870..0887 ; ALetter # Lo [24] ARABIC LETTER ALEF WITH ATTACHED FATHA..ARABIC BASELINE ROUND DOT
|
||||
0889..088E ; ALetter # Lo [6] ARABIC LETTER NOON WITH INVERTED SMALL V..ARABIC VERTICAL TAIL
|
||||
0889..088F ; ALetter # Lo [7] ARABIC LETTER NOON WITH INVERTED SMALL V..ARABIC LETTER NOON WITH RING ABOVE
|
||||
08A0..08C8 ; ALetter # Lo [41] ARABIC LETTER BEH WITH SMALL V BELOW..ARABIC LETTER GRAF
|
||||
08C9 ; ALetter # Lm ARABIC SMALL FARSI YEH
|
||||
0904..0939 ; ALetter # Lo [54] DEVANAGARI LETTER SHORT A..DEVANAGARI LETTER HA
|
||||
|
|
@ -813,7 +825,7 @@ FF71..FF9D ; Katakana # Lo [45] HALFWIDTH KATAKANA LETTER A..HALFWIDTH KATAK
|
|||
0C2A..0C39 ; ALetter # Lo [16] TELUGU LETTER PA..TELUGU LETTER HA
|
||||
0C3D ; ALetter # Lo TELUGU SIGN AVAGRAHA
|
||||
0C58..0C5A ; ALetter # Lo [3] TELUGU LETTER TSA..TELUGU LETTER RRRA
|
||||
0C5D ; ALetter # Lo TELUGU LETTER NAKAARA POLLU
|
||||
0C5C..0C5D ; ALetter # Lo [2] TELUGU ARCHAIC SHRII..TELUGU LETTER NAKAARA POLLU
|
||||
0C60..0C61 ; ALetter # Lo [2] TELUGU LETTER VOCALIC RR..TELUGU LETTER VOCALIC LL
|
||||
0C80 ; ALetter # Lo KANNADA SIGN SPACING CANDRABINDU
|
||||
0C85..0C8C ; ALetter # Lo [8] KANNADA LETTER A..KANNADA LETTER VOCALIC L
|
||||
|
|
@ -822,7 +834,7 @@ FF71..FF9D ; Katakana # Lo [45] HALFWIDTH KATAKANA LETTER A..HALFWIDTH KATAK
|
|||
0CAA..0CB3 ; ALetter # Lo [10] KANNADA LETTER PA..KANNADA LETTER LLA
|
||||
0CB5..0CB9 ; ALetter # Lo [5] KANNADA LETTER VA..KANNADA LETTER HA
|
||||
0CBD ; ALetter # Lo KANNADA SIGN AVAGRAHA
|
||||
0CDD..0CDE ; ALetter # Lo [2] KANNADA LETTER NAKAARA POLLU..KANNADA LETTER FA
|
||||
0CDC..0CDE ; ALetter # Lo [3] KANNADA ARCHAIC SHRII..KANNADA LETTER FA
|
||||
0CE0..0CE1 ; ALetter # Lo [2] KANNADA LETTER VOCALIC RR..KANNADA LETTER VOCALIC LL
|
||||
0CF1..0CF2 ; ALetter # Lo [2] KANNADA SIGN JIHVAMULIYA..KANNADA SIGN UPADHMANIYA
|
||||
0D04..0D0C ; ALetter # Lo [9] MALAYALAM LETTER VEDIC ANUSVARA..MALAYALAM LETTER VOCALIC L
|
||||
|
|
@ -1002,11 +1014,8 @@ A788 ; ALetter # Lm MODIFIER LETTER LOW CIRCUMFLEX ACCENT
|
|||
A789..A78A ; ALetter # Sk [2] MODIFIER LETTER COLON..MODIFIER LETTER SHORT EQUALS SIGN
|
||||
A78B..A78E ; ALetter # L& [4] LATIN CAPITAL LETTER SALTILLO..LATIN SMALL LETTER L WITH RETROFLEX HOOK AND BELT
|
||||
A78F ; ALetter # Lo LATIN LETTER SINOLOGICAL DOT
|
||||
A790..A7CD ; ALetter # L& [62] LATIN CAPITAL LETTER N WITH DESCENDER..LATIN SMALL LETTER S WITH DIAGONAL STROKE
|
||||
A7D0..A7D1 ; ALetter # L& [2] LATIN CAPITAL LETTER CLOSED INSULAR G..LATIN SMALL LETTER CLOSED INSULAR G
|
||||
A7D3 ; ALetter # L& LATIN SMALL LETTER DOUBLE THORN
|
||||
A7D5..A7DC ; ALetter # L& [8] LATIN SMALL LETTER DOUBLE WYNN..LATIN CAPITAL LETTER LAMBDA WITH STROKE
|
||||
A7F2..A7F4 ; ALetter # Lm [3] MODIFIER LETTER CAPITAL C..MODIFIER LETTER CAPITAL Q
|
||||
A790..A7DC ; ALetter # L& [77] LATIN CAPITAL LETTER N WITH DESCENDER..LATIN CAPITAL LETTER LAMBDA WITH STROKE
|
||||
A7F1..A7F4 ; ALetter # Lm [4] MODIFIER LETTER CAPITAL S..MODIFIER LETTER CAPITAL Q
|
||||
A7F5..A7F6 ; ALetter # L& [2] LATIN CAPITAL LETTER REVERSED HALF H..LATIN SMALL LETTER REVERSED HALF H
|
||||
A7F7 ; ALetter # Lo LATIN EPIGRAPHIC LETTER SIDEWAYS I
|
||||
A7F8..A7F9 ; ALetter # Lm [2] MODIFIER LETTER CAPITAL H WITH STROKE..MODIFIER LETTER SMALL LIGATURE OE
|
||||
|
|
@ -1115,6 +1124,7 @@ FFDA..FFDC ; ALetter # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HANGUL
|
|||
108F4..108F5 ; ALetter # Lo [2] HATRAN LETTER SHIN..HATRAN LETTER TAW
|
||||
10900..10915 ; ALetter # Lo [22] PHOENICIAN LETTER ALF..PHOENICIAN LETTER TAU
|
||||
10920..10939 ; ALetter # Lo [26] LYDIAN LETTER A..LYDIAN LETTER C
|
||||
10940..10959 ; ALetter # Lo [26] SIDETIC LETTER N01..SIDETIC LETTER N26
|
||||
10980..109B7 ; ALetter # Lo [56] MEROITIC HIEROGLYPHIC LETTER A..MEROITIC CURSIVE LETTER DA
|
||||
109BE..109BF ; ALetter # Lo [2] MEROITIC CURSIVE LOGOGRAM RMT..MEROITIC CURSIVE LOGOGRAM IMN
|
||||
10A00 ; ALetter # Lo KHAROSHTHI LETTER A
|
||||
|
|
@ -1142,6 +1152,8 @@ FFDA..FFDC ; ALetter # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HANGUL
|
|||
10E80..10EA9 ; ALetter # Lo [42] YEZIDI LETTER ELIF..YEZIDI LETTER ET
|
||||
10EB0..10EB1 ; ALetter # Lo [2] YEZIDI LETTER LAM WITH DOT ABOVE..YEZIDI LETTER YOT WITH CIRCUMFLEX ABOVE
|
||||
10EC2..10EC4 ; ALetter # Lo [3] ARABIC LETTER DAL WITH TWO DOTS VERTICALLY BELOW..ARABIC LETTER KAF WITH TWO DOTS VERTICALLY BELOW
|
||||
10EC5 ; ALetter # Lm ARABIC SMALL YEH BARREE WITH TWO DOTS BELOW
|
||||
10EC6..10EC7 ; ALetter # Lo [2] ARABIC LETTER THIN NOON..ARABIC LETTER YEH WITH FOUR DOTS BELOW
|
||||
10F00..10F1C ; ALetter # Lo [29] OLD SOGDIAN LETTER ALEPH..OLD SOGDIAN LETTER FINAL TAW WITH VERTICAL TAIL
|
||||
10F27 ; ALetter # Lo OLD SOGDIAN LIGATURE AYIN-DALETH
|
||||
10F30..10F45 ; ALetter # Lo [22] SOGDIAN LETTER ALEPH..SOGDIAN INDEPENDENT SHIN
|
||||
|
|
@ -1232,6 +1244,9 @@ FFDA..FFDC ; ALetter # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HANGUL
|
|||
11D67..11D68 ; ALetter # Lo [2] GUNJALA GONDI LETTER EE..GUNJALA GONDI LETTER AI
|
||||
11D6A..11D89 ; ALetter # Lo [32] GUNJALA GONDI LETTER OO..GUNJALA GONDI LETTER SA
|
||||
11D98 ; ALetter # Lo GUNJALA GONDI OM
|
||||
11DB0..11DD8 ; ALetter # Lo [41] TOLONG SIKI LETTER I..TOLONG SIKI LETTER RRH
|
||||
11DD9 ; ALetter # Lm TOLONG SIKI SIGN SELA
|
||||
11DDA..11DDB ; ALetter # Lo [2] TOLONG SIKI SIGN HECAKA..TOLONG SIKI UNGGA
|
||||
11EE0..11EF2 ; ALetter # Lo [19] MAKASAR LETTER KA..MAKASAR ANGKA
|
||||
11F02 ; ALetter # Lo KAWI SIGN REPHA
|
||||
11F04..11F10 ; ALetter # Lo [13] KAWI LETTER A..KAWI LETTER O
|
||||
|
|
@ -1258,6 +1273,8 @@ FFDA..FFDC ; ALetter # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HANGUL
|
|||
16D43..16D6A ; ALetter # Lo [40] KIRAT RAI LETTER A..KIRAT RAI VOWEL SIGN AU
|
||||
16D6B..16D6C ; ALetter # Lm [2] KIRAT RAI SIGN VIRAMA..KIRAT RAI SIGN SAAT
|
||||
16E40..16E7F ; ALetter # L& [64] MEDEFAIDRIN CAPITAL LETTER M..MEDEFAIDRIN SMALL LETTER Y
|
||||
16EA0..16EB8 ; ALetter # L& [25] BERIA ERFE CAPITAL LETTER ARKAB..BERIA ERFE CAPITAL LETTER AY
|
||||
16EBB..16ED3 ; ALetter # L& [25] BERIA ERFE SMALL LETTER ARKAB..BERIA ERFE SMALL LETTER AY
|
||||
16F00..16F4A ; ALetter # Lo [75] MIAO LETTER PA..MIAO LETTER RTE
|
||||
16F50 ; ALetter # Lo MIAO LETTER NASALIZATION
|
||||
16F93..16F9F ; ALetter # Lm [13] MIAO LETTER TONE-2..MIAO LETTER REFORMED TONE-8
|
||||
|
|
@ -1311,6 +1328,13 @@ FFDA..FFDC ; ALetter # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HANGUL
|
|||
1E4EB ; ALetter # Lm NAG MUNDARI SIGN OJOD
|
||||
1E5D0..1E5ED ; ALetter # Lo [30] OL ONAL LETTER O..OL ONAL LETTER EG
|
||||
1E5F0 ; ALetter # Lo OL ONAL SIGN HODDOND
|
||||
1E6C0..1E6DE ; ALetter # Lo [31] TAI YO LETTER LOW KO..TAI YO LETTER HIGH KVO
|
||||
1E6E0..1E6E2 ; ALetter # Lo [3] TAI YO LETTER AA..TAI YO LETTER UE
|
||||
1E6E4..1E6E5 ; ALetter # Lo [2] TAI YO LETTER U..TAI YO LETTER AE
|
||||
1E6E7..1E6ED ; ALetter # Lo [7] TAI YO LETTER O..TAI YO LETTER AUE
|
||||
1E6F0..1E6F4 ; ALetter # Lo [5] TAI YO LETTER AN..TAI YO LETTER AP
|
||||
1E6FE ; ALetter # Lo TAI YO SYMBOL MUEANG
|
||||
1E6FF ; ALetter # Lm TAI YO XAM LAI
|
||||
1E7E0..1E7E6 ; ALetter # Lo [7] ETHIOPIC SYLLABLE HHYA..ETHIOPIC SYLLABLE HHYO
|
||||
1E7E8..1E7EB ; ALetter # Lo [4] ETHIOPIC SYLLABLE GURAGE HHWA..ETHIOPIC SYLLABLE HHWE
|
||||
1E7ED..1E7EE ; ALetter # Lo [2] ETHIOPIC SYLLABLE GURAGE MWI..ETHIOPIC SYLLABLE GURAGE MWEE
|
||||
|
|
@ -1355,7 +1379,7 @@ FFDA..FFDC ; ALetter # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HANGUL
|
|||
1F150..1F169 ; ALetter # So [26] NEGATIVE CIRCLED LATIN CAPITAL LETTER A..NEGATIVE CIRCLED LATIN CAPITAL LETTER Z
|
||||
1F170..1F189 ; ALetter # So [26] NEGATIVE SQUARED LATIN CAPITAL LETTER A..NEGATIVE SQUARED LATIN CAPITAL LETTER Z
|
||||
|
||||
# Total code points: 33791
|
||||
# Total code points: 33973
|
||||
|
||||
# ================================================
|
||||
|
||||
|
|
@ -1467,6 +1491,7 @@ FF10..FF19 ; Numeric # Nd [10] FULLWIDTH DIGIT ZERO..FULLWIDTH DIGIT NINE
|
|||
11C50..11C59 ; Numeric # Nd [10] BHAIKSUKI DIGIT ZERO..BHAIKSUKI DIGIT NINE
|
||||
11D50..11D59 ; Numeric # Nd [10] MASARAM GONDI DIGIT ZERO..MASARAM GONDI DIGIT NINE
|
||||
11DA0..11DA9 ; Numeric # Nd [10] GUNJALA GONDI DIGIT ZERO..GUNJALA GONDI DIGIT NINE
|
||||
11DE0..11DE9 ; Numeric # Nd [10] TOLONG SIKI DIGIT ZERO..TOLONG SIKI DIGIT NINE
|
||||
11F50..11F59 ; Numeric # Nd [10] KAWI DIGIT ZERO..KAWI DIGIT NINE
|
||||
16130..16139 ; Numeric # Nd [10] GURUNG KHEMA DIGIT ZERO..GURUNG KHEMA DIGIT NINE
|
||||
16A60..16A69 ; Numeric # Nd [10] MRO DIGIT ZERO..MRO DIGIT NINE
|
||||
|
|
@ -1482,7 +1507,7 @@ FF10..FF19 ; Numeric # Nd [10] FULLWIDTH DIGIT ZERO..FULLWIDTH DIGIT NINE
|
|||
1E950..1E959 ; Numeric # Nd [10] ADLAM DIGIT ZERO..ADLAM DIGIT NINE
|
||||
1FBF0..1FBF9 ; Numeric # Nd [10] SEGMENTED DIGIT ZERO..SEGMENTED DIGIT NINE
|
||||
|
||||
# Total code points: 774
|
||||
# Total code points: 784
|
||||
|
||||
# ================================================
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
# emoji-data.txt
|
||||
# Date: 2024-05-01, 21:25:24 GMT
|
||||
# © 2024 Unicode®, Inc.
|
||||
# Date: 2025-07-25, 17:54:31 GMT
|
||||
# © 2025 Unicode®, Inc.
|
||||
# Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries.
|
||||
# For terms of use and license, see https://www.unicode.org/terms_of_use.html
|
||||
#
|
||||
# Emoji Data for UTS #51
|
||||
# Used with Emoji Version 16.0 and subsequent minor revisions (if any)
|
||||
# Version: 17.0
|
||||
#
|
||||
# For documentation and usage, see https://www.unicode.org/reports/tr51
|
||||
#
|
||||
|
|
@ -340,6 +340,7 @@
|
|||
1F6D1..1F6D2 ; Emoji # E3.0 [2] (🛑..🛒) stop sign..shopping cart
|
||||
1F6D5 ; Emoji # E12.0 [1] (🛕) hindu temple
|
||||
1F6D6..1F6D7 ; Emoji # E13.0 [2] (🛖..🛗) hut..elevator
|
||||
1F6D8 ; Emoji # E17.0 [1] () landslide
|
||||
1F6DC ; Emoji # E15.0 [1] (🛜) wireless
|
||||
1F6DD..1F6DF ; Emoji # E14.0 [3] (🛝..🛟) playground slide..ring buoy
|
||||
1F6E0..1F6E5 ; Emoji # E0.7 [6] (🛠️..🛥️) hammer and wrench..motor boat
|
||||
|
|
@ -408,6 +409,8 @@
|
|||
1FA83..1FA86 ; Emoji # E13.0 [4] (🪃..🪆) boomerang..nesting dolls
|
||||
1FA87..1FA88 ; Emoji # E15.0 [2] (🪇..🪈) maracas..flute
|
||||
1FA89 ; Emoji # E16.0 [1] () harp
|
||||
1FA8A ; Emoji # E17.0 [1] () trombone
|
||||
1FA8E ; Emoji # E17.0 [1] () treasure chest
|
||||
1FA8F ; Emoji # E16.0 [1] () shovel
|
||||
1FA90..1FA95 ; Emoji # E12.0 [6] (🪐..🪕) ringed planet..banjo
|
||||
1FA96..1FAA8 ; Emoji # E13.0 [19] (🪖..🪨) military helmet..rock
|
||||
|
|
@ -421,6 +424,8 @@
|
|||
1FAC0..1FAC2 ; Emoji # E13.0 [3] (🫀..🫂) anatomical heart..people hugging
|
||||
1FAC3..1FAC5 ; Emoji # E14.0 [3] (🫃..🫅) pregnant man..person with crown
|
||||
1FAC6 ; Emoji # E16.0 [1] () fingerprint
|
||||
1FAC8 ; Emoji # E17.0 [1] () hairy creature
|
||||
1FACD ; Emoji # E17.0 [1] () orca
|
||||
1FACE..1FACF ; Emoji # E15.0 [2] (🫎..🫏) moose..donkey
|
||||
1FAD0..1FAD6 ; Emoji # E13.0 [7] (🫐..🫖) blueberries..teapot
|
||||
1FAD7..1FAD9 ; Emoji # E14.0 [3] (🫗..🫙) pouring liquid..jar
|
||||
|
|
@ -430,10 +435,12 @@
|
|||
1FAE0..1FAE7 ; Emoji # E14.0 [8] (🫠..🫧) melting face..bubbles
|
||||
1FAE8 ; Emoji # E15.0 [1] (🫨) shaking face
|
||||
1FAE9 ; Emoji # E16.0 [1] () face with bags under eyes
|
||||
1FAEA ; Emoji # E17.0 [1] () distorted face
|
||||
1FAEF ; Emoji # E17.0 [1] () fight cloud
|
||||
1FAF0..1FAF6 ; Emoji # E14.0 [7] (🫰..🫶) hand with index finger and thumb crossed..heart hands
|
||||
1FAF7..1FAF8 ; Emoji # E15.0 [2] (🫷..🫸) leftwards pushing hand..rightwards pushing hand
|
||||
|
||||
# Total elements: 1431
|
||||
# Total elements: 1438
|
||||
|
||||
# ================================================
|
||||
|
||||
|
|
@ -640,6 +647,7 @@
|
|||
1F6D1..1F6D2 ; Emoji_Presentation # E3.0 [2] (🛑..🛒) stop sign..shopping cart
|
||||
1F6D5 ; Emoji_Presentation # E12.0 [1] (🛕) hindu temple
|
||||
1F6D6..1F6D7 ; Emoji_Presentation # E13.0 [2] (🛖..🛗) hut..elevator
|
||||
1F6D8 ; Emoji_Presentation # E17.0 [1] () landslide
|
||||
1F6DC ; Emoji_Presentation # E15.0 [1] (🛜) wireless
|
||||
1F6DD..1F6DF ; Emoji_Presentation # E14.0 [3] (🛝..🛟) playground slide..ring buoy
|
||||
1F6EB..1F6EC ; Emoji_Presentation # E1.0 [2] (🛫..🛬) airplane departure..airplane arrival
|
||||
|
|
@ -704,6 +712,8 @@
|
|||
1FA83..1FA86 ; Emoji_Presentation # E13.0 [4] (🪃..🪆) boomerang..nesting dolls
|
||||
1FA87..1FA88 ; Emoji_Presentation # E15.0 [2] (🪇..🪈) maracas..flute
|
||||
1FA89 ; Emoji_Presentation # E16.0 [1] () harp
|
||||
1FA8A ; Emoji_Presentation # E17.0 [1] () trombone
|
||||
1FA8E ; Emoji_Presentation # E17.0 [1] () treasure chest
|
||||
1FA8F ; Emoji_Presentation # E16.0 [1] () shovel
|
||||
1FA90..1FA95 ; Emoji_Presentation # E12.0 [6] (🪐..🪕) ringed planet..banjo
|
||||
1FA96..1FAA8 ; Emoji_Presentation # E13.0 [19] (🪖..🪨) military helmet..rock
|
||||
|
|
@ -717,6 +727,8 @@
|
|||
1FAC0..1FAC2 ; Emoji_Presentation # E13.0 [3] (🫀..🫂) anatomical heart..people hugging
|
||||
1FAC3..1FAC5 ; Emoji_Presentation # E14.0 [3] (🫃..🫅) pregnant man..person with crown
|
||||
1FAC6 ; Emoji_Presentation # E16.0 [1] () fingerprint
|
||||
1FAC8 ; Emoji_Presentation # E17.0 [1] () hairy creature
|
||||
1FACD ; Emoji_Presentation # E17.0 [1] () orca
|
||||
1FACE..1FACF ; Emoji_Presentation # E15.0 [2] (🫎..🫏) moose..donkey
|
||||
1FAD0..1FAD6 ; Emoji_Presentation # E13.0 [7] (🫐..🫖) blueberries..teapot
|
||||
1FAD7..1FAD9 ; Emoji_Presentation # E14.0 [3] (🫗..🫙) pouring liquid..jar
|
||||
|
|
@ -726,10 +738,12 @@
|
|||
1FAE0..1FAE7 ; Emoji_Presentation # E14.0 [8] (🫠..🫧) melting face..bubbles
|
||||
1FAE8 ; Emoji_Presentation # E15.0 [1] (🫨) shaking face
|
||||
1FAE9 ; Emoji_Presentation # E16.0 [1] () face with bags under eyes
|
||||
1FAEA ; Emoji_Presentation # E17.0 [1] () distorted face
|
||||
1FAEF ; Emoji_Presentation # E17.0 [1] () fight cloud
|
||||
1FAF0..1FAF6 ; Emoji_Presentation # E14.0 [7] (🫰..🫶) hand with index finger and thumb crossed..heart hands
|
||||
1FAF7..1FAF8 ; Emoji_Presentation # E15.0 [2] (🫷..🫸) leftwards pushing hand..rightwards pushing hand
|
||||
|
||||
# Total elements: 1212
|
||||
# Total elements: 1219
|
||||
|
||||
# ================================================
|
||||
|
||||
|
|
@ -827,7 +841,6 @@ E0020..E007F ; Emoji_Component # E0.0 [96] (..) tag space..c
|
|||
21A9..21AA ; Extended_Pictographic# E0.6 [2] (↩️..↪️) right arrow curving left..left arrow curving right
|
||||
231A..231B ; Extended_Pictographic# E0.6 [2] (⌚..⌛) watch..hourglass done
|
||||
2328 ; Extended_Pictographic# E1.0 [1] (⌨️) keyboard
|
||||
2388 ; Extended_Pictographic# E0.0 [1] (⎈) HELM SYMBOL
|
||||
23CF ; Extended_Pictographic# E1.0 [1] (⏏️) eject button
|
||||
23E9..23EC ; Extended_Pictographic# E0.6 [4] (⏩..⏬) fast-forward button..fast down button
|
||||
23ED..23EE ; Extended_Pictographic# E0.7 [2] (⏭️..⏮️) next track button..last track button
|
||||
|
|
@ -844,106 +857,63 @@ E0020..E007F ; Emoji_Component # E0.0 [96] (..) tag space..c
|
|||
2600..2601 ; Extended_Pictographic# E0.6 [2] (☀️..☁️) sun..cloud
|
||||
2602..2603 ; Extended_Pictographic# E0.7 [2] (☂️..☃️) umbrella..snowman
|
||||
2604 ; Extended_Pictographic# E1.0 [1] (☄️) comet
|
||||
2605 ; Extended_Pictographic# E0.0 [1] (★) BLACK STAR
|
||||
2607..260D ; Extended_Pictographic# E0.0 [7] (☇..☍) LIGHTNING..OPPOSITION
|
||||
260E ; Extended_Pictographic# E0.6 [1] (☎️) telephone
|
||||
260F..2610 ; Extended_Pictographic# E0.0 [2] (☏..☐) WHITE TELEPHONE..BALLOT BOX
|
||||
2611 ; Extended_Pictographic# E0.6 [1] (☑️) check box with check
|
||||
2612 ; Extended_Pictographic# E0.0 [1] (☒) BALLOT BOX WITH X
|
||||
2614..2615 ; Extended_Pictographic# E0.6 [2] (☔..☕) umbrella with rain drops..hot beverage
|
||||
2616..2617 ; Extended_Pictographic# E0.0 [2] (☖..☗) WHITE SHOGI PIECE..BLACK SHOGI PIECE
|
||||
2618 ; Extended_Pictographic# E1.0 [1] (☘️) shamrock
|
||||
2619..261C ; Extended_Pictographic# E0.0 [4] (☙..☜) REVERSED ROTATED FLORAL HEART BULLET..WHITE LEFT POINTING INDEX
|
||||
261D ; Extended_Pictographic# E0.6 [1] (☝️) index pointing up
|
||||
261E..261F ; Extended_Pictographic# E0.0 [2] (☞..☟) WHITE RIGHT POINTING INDEX..WHITE DOWN POINTING INDEX
|
||||
2620 ; Extended_Pictographic# E1.0 [1] (☠️) skull and crossbones
|
||||
2621 ; Extended_Pictographic# E0.0 [1] (☡) CAUTION SIGN
|
||||
2622..2623 ; Extended_Pictographic# E1.0 [2] (☢️..☣️) radioactive..biohazard
|
||||
2624..2625 ; Extended_Pictographic# E0.0 [2] (☤..☥) CADUCEUS..ANKH
|
||||
2626 ; Extended_Pictographic# E1.0 [1] (☦️) orthodox cross
|
||||
2627..2629 ; Extended_Pictographic# E0.0 [3] (☧..☩) CHI RHO..CROSS OF JERUSALEM
|
||||
262A ; Extended_Pictographic# E0.7 [1] (☪️) star and crescent
|
||||
262B..262D ; Extended_Pictographic# E0.0 [3] (☫..☭) FARSI SYMBOL..HAMMER AND SICKLE
|
||||
262E ; Extended_Pictographic# E1.0 [1] (☮️) peace symbol
|
||||
262F ; Extended_Pictographic# E0.7 [1] (☯️) yin yang
|
||||
2630..2637 ; Extended_Pictographic# E0.0 [8] (☰..☷) TRIGRAM FOR HEAVEN..TRIGRAM FOR EARTH
|
||||
2638..2639 ; Extended_Pictographic# E0.7 [2] (☸️..☹️) wheel of dharma..frowning face
|
||||
263A ; Extended_Pictographic# E0.6 [1] (☺️) smiling face
|
||||
263B..263F ; Extended_Pictographic# E0.0 [5] (☻..☿) BLACK SMILING FACE..MERCURY
|
||||
2640 ; Extended_Pictographic# E4.0 [1] (♀️) female sign
|
||||
2641 ; Extended_Pictographic# E0.0 [1] (♁) EARTH
|
||||
2642 ; Extended_Pictographic# E4.0 [1] (♂️) male sign
|
||||
2643..2647 ; Extended_Pictographic# E0.0 [5] (♃..♇) JUPITER..PLUTO
|
||||
2648..2653 ; Extended_Pictographic# E0.6 [12] (♈..♓) Aries..Pisces
|
||||
2654..265E ; Extended_Pictographic# E0.0 [11] (♔..♞) WHITE CHESS KING..BLACK CHESS KNIGHT
|
||||
265F ; Extended_Pictographic# E11.0 [1] (♟️) chess pawn
|
||||
2660 ; Extended_Pictographic# E0.6 [1] (♠️) spade suit
|
||||
2661..2662 ; Extended_Pictographic# E0.0 [2] (♡..♢) WHITE HEART SUIT..WHITE DIAMOND SUIT
|
||||
2663 ; Extended_Pictographic# E0.6 [1] (♣️) club suit
|
||||
2664 ; Extended_Pictographic# E0.0 [1] (♤) WHITE SPADE SUIT
|
||||
2665..2666 ; Extended_Pictographic# E0.6 [2] (♥️..♦️) heart suit..diamond suit
|
||||
2667 ; Extended_Pictographic# E0.0 [1] (♧) WHITE CLUB SUIT
|
||||
2668 ; Extended_Pictographic# E0.6 [1] (♨️) hot springs
|
||||
2669..267A ; Extended_Pictographic# E0.0 [18] (♩..♺) QUARTER NOTE..RECYCLING SYMBOL FOR GENERIC MATERIALS
|
||||
267B ; Extended_Pictographic# E0.6 [1] (♻️) recycling symbol
|
||||
267C..267D ; Extended_Pictographic# E0.0 [2] (♼..♽) RECYCLED PAPER SYMBOL..PARTIALLY-RECYCLED PAPER SYMBOL
|
||||
267E ; Extended_Pictographic# E11.0 [1] (♾️) infinity
|
||||
267F ; Extended_Pictographic# E0.6 [1] (♿) wheelchair symbol
|
||||
2680..2685 ; Extended_Pictographic# E0.0 [6] (⚀..⚅) DIE FACE-1..DIE FACE-6
|
||||
2690..2691 ; Extended_Pictographic# E0.0 [2] (⚐..⚑) WHITE FLAG..BLACK FLAG
|
||||
2692 ; Extended_Pictographic# E1.0 [1] (⚒️) hammer and pick
|
||||
2693 ; Extended_Pictographic# E0.6 [1] (⚓) anchor
|
||||
2694 ; Extended_Pictographic# E1.0 [1] (⚔️) crossed swords
|
||||
2695 ; Extended_Pictographic# E4.0 [1] (⚕️) medical symbol
|
||||
2696..2697 ; Extended_Pictographic# E1.0 [2] (⚖️..⚗️) balance scale..alembic
|
||||
2698 ; Extended_Pictographic# E0.0 [1] (⚘) FLOWER
|
||||
2699 ; Extended_Pictographic# E1.0 [1] (⚙️) gear
|
||||
269A ; Extended_Pictographic# E0.0 [1] (⚚) STAFF OF HERMES
|
||||
269B..269C ; Extended_Pictographic# E1.0 [2] (⚛️..⚜️) atom symbol..fleur-de-lis
|
||||
269D..269F ; Extended_Pictographic# E0.0 [3] (⚝..⚟) OUTLINED WHITE STAR..THREE LINES CONVERGING LEFT
|
||||
26A0..26A1 ; Extended_Pictographic# E0.6 [2] (⚠️..⚡) warning..high voltage
|
||||
26A2..26A6 ; Extended_Pictographic# E0.0 [5] (⚢..⚦) DOUBLED FEMALE SIGN..MALE WITH STROKE SIGN
|
||||
26A7 ; Extended_Pictographic# E13.0 [1] (⚧️) transgender symbol
|
||||
26A8..26A9 ; Extended_Pictographic# E0.0 [2] (⚨..⚩) VERTICAL MALE WITH STROKE SIGN..HORIZONTAL MALE WITH STROKE SIGN
|
||||
26AA..26AB ; Extended_Pictographic# E0.6 [2] (⚪..⚫) white circle..black circle
|
||||
26AC..26AF ; Extended_Pictographic# E0.0 [4] (⚬..⚯) MEDIUM SMALL WHITE CIRCLE..UNMARRIED PARTNERSHIP SYMBOL
|
||||
26B0..26B1 ; Extended_Pictographic# E1.0 [2] (⚰️..⚱️) coffin..funeral urn
|
||||
26B2..26BC ; Extended_Pictographic# E0.0 [11] (⚲..⚼) NEUTER..SESQUIQUADRATE
|
||||
26BD..26BE ; Extended_Pictographic# E0.6 [2] (⚽..⚾) soccer ball..baseball
|
||||
26BF..26C3 ; Extended_Pictographic# E0.0 [5] (⚿..⛃) SQUARED KEY..BLACK DRAUGHTS KING
|
||||
26C4..26C5 ; Extended_Pictographic# E0.6 [2] (⛄..⛅) snowman without snow..sun behind cloud
|
||||
26C6..26C7 ; Extended_Pictographic# E0.0 [2] (⛆..⛇) RAIN..BLACK SNOWMAN
|
||||
26C8 ; Extended_Pictographic# E0.7 [1] (⛈️) cloud with lightning and rain
|
||||
26C9..26CD ; Extended_Pictographic# E0.0 [5] (⛉..⛍) TURNED WHITE SHOGI PIECE..DISABLED CAR
|
||||
26CE ; Extended_Pictographic# E0.6 [1] (⛎) Ophiuchus
|
||||
26CF ; Extended_Pictographic# E0.7 [1] (⛏️) pick
|
||||
26D0 ; Extended_Pictographic# E0.0 [1] (⛐) CAR SLIDING
|
||||
26D1 ; Extended_Pictographic# E0.7 [1] (⛑️) rescue worker’s helmet
|
||||
26D2 ; Extended_Pictographic# E0.0 [1] (⛒) CIRCLED CROSSING LANES
|
||||
26D3 ; Extended_Pictographic# E0.7 [1] (⛓️) chains
|
||||
26D4 ; Extended_Pictographic# E0.6 [1] (⛔) no entry
|
||||
26D5..26E8 ; Extended_Pictographic# E0.0 [20] (⛕..⛨) ALTERNATE ONE-WAY LEFT WAY TRAFFIC..BLACK CROSS ON SHIELD
|
||||
26E9 ; Extended_Pictographic# E0.7 [1] (⛩️) shinto shrine
|
||||
26EA ; Extended_Pictographic# E0.6 [1] (⛪) church
|
||||
26EB..26EF ; Extended_Pictographic# E0.0 [5] (⛫..⛯) CASTLE..MAP SYMBOL FOR LIGHTHOUSE
|
||||
26F0..26F1 ; Extended_Pictographic# E0.7 [2] (⛰️..⛱️) mountain..umbrella on ground
|
||||
26F2..26F3 ; Extended_Pictographic# E0.6 [2] (⛲..⛳) fountain..flag in hole
|
||||
26F4 ; Extended_Pictographic# E0.7 [1] (⛴️) ferry
|
||||
26F5 ; Extended_Pictographic# E0.6 [1] (⛵) sailboat
|
||||
26F6 ; Extended_Pictographic# E0.0 [1] (⛶) SQUARE FOUR CORNERS
|
||||
26F7..26F9 ; Extended_Pictographic# E0.7 [3] (⛷️..⛹️) skier..person bouncing ball
|
||||
26FA ; Extended_Pictographic# E0.6 [1] (⛺) tent
|
||||
26FB..26FC ; Extended_Pictographic# E0.0 [2] (⛻..⛼) JAPANESE BANK SYMBOL..HEADSTONE GRAVEYARD SYMBOL
|
||||
26FD ; Extended_Pictographic# E0.6 [1] (⛽) fuel pump
|
||||
26FE..2701 ; Extended_Pictographic# E0.0 [4] (⛾..✁) CUP ON BLACK SQUARE..UPPER BLADE SCISSORS
|
||||
2702 ; Extended_Pictographic# E0.6 [1] (✂️) scissors
|
||||
2703..2704 ; Extended_Pictographic# E0.0 [2] (✃..✄) LOWER BLADE SCISSORS..WHITE SCISSORS
|
||||
2705 ; Extended_Pictographic# E0.6 [1] (✅) check mark button
|
||||
2708..270C ; Extended_Pictographic# E0.6 [5] (✈️..✌️) airplane..victory hand
|
||||
270D ; Extended_Pictographic# E0.7 [1] (✍️) writing hand
|
||||
270E ; Extended_Pictographic# E0.0 [1] (✎) LOWER RIGHT PENCIL
|
||||
270F ; Extended_Pictographic# E0.6 [1] (✏️) pencil
|
||||
2710..2711 ; Extended_Pictographic# E0.0 [2] (✐..✑) UPPER RIGHT PENCIL..WHITE NIB
|
||||
2712 ; Extended_Pictographic# E0.6 [1] (✒️) black nib
|
||||
2714 ; Extended_Pictographic# E0.6 [1] (✔️) check mark
|
||||
2716 ; Extended_Pictographic# E0.6 [1] (✖️) multiply
|
||||
|
|
@ -959,7 +929,6 @@ E0020..E007F ; Emoji_Component # E0.0 [96] (..) tag space..c
|
|||
2757 ; Extended_Pictographic# E0.6 [1] (❗) red exclamation mark
|
||||
2763 ; Extended_Pictographic# E1.0 [1] (❣️) heart exclamation
|
||||
2764 ; Extended_Pictographic# E0.6 [1] (❤️) red heart
|
||||
2765..2767 ; Extended_Pictographic# E0.0 [3] (❥..❧) ROTATED HEAVY BLACK HEART BULLET..ROTATED FLORAL HEART BULLET
|
||||
2795..2797 ; Extended_Pictographic# E0.6 [3] (➕..➗) plus..divide
|
||||
27A1 ; Extended_Pictographic# E0.6 [1] (➡️) right arrow
|
||||
27B0 ; Extended_Pictographic# E0.6 [1] (➰) curly loop
|
||||
|
|
@ -973,19 +942,19 @@ E0020..E007F ; Emoji_Component # E0.0 [96] (..) tag space..c
|
|||
303D ; Extended_Pictographic# E0.6 [1] (〽️) part alternation mark
|
||||
3297 ; Extended_Pictographic# E0.6 [1] (㊗️) Japanese “congratulations” button
|
||||
3299 ; Extended_Pictographic# E0.6 [1] (㊙️) Japanese “secret” button
|
||||
1F000..1F003 ; Extended_Pictographic# E0.0 [4] (🀀..🀃) MAHJONG TILE EAST WIND..MAHJONG TILE NORTH WIND
|
||||
1F004 ; Extended_Pictographic# E0.6 [1] (🀄) mahjong red dragon
|
||||
1F005..1F0CE ; Extended_Pictographic# E0.0 [202] (🀅..🃎) MAHJONG TILE GREEN DRAGON..PLAYING CARD KING OF DIAMONDS
|
||||
1F02C..1F02F ; Extended_Pictographic# E0.0 [4] (..) <reserved-1F02C>..<reserved-1F02F>
|
||||
1F094..1F09F ; Extended_Pictographic# E0.0 [12] (..) <reserved-1F094>..<reserved-1F09F>
|
||||
1F0AF..1F0B0 ; Extended_Pictographic# E0.0 [2] (..) <reserved-1F0AF>..<reserved-1F0B0>
|
||||
1F0C0 ; Extended_Pictographic# E0.0 [1] () <reserved-1F0C0>
|
||||
1F0CF ; Extended_Pictographic# E0.6 [1] (🃏) joker
|
||||
1F0D0..1F0FF ; Extended_Pictographic# E0.0 [48] (..) <reserved-1F0D0>..<reserved-1F0FF>
|
||||
1F10D..1F10F ; Extended_Pictographic# E0.0 [3] (🄍..🄏) CIRCLED ZERO WITH SLASH..CIRCLED DOLLAR SIGN WITH OVERLAID BACKSLASH
|
||||
1F12F ; Extended_Pictographic# E0.0 [1] (🄯) COPYLEFT SYMBOL
|
||||
1F16C..1F16F ; Extended_Pictographic# E0.0 [4] (🅬..🅯) RAISED MR SIGN..CIRCLED HUMAN FIGURE
|
||||
1F0D0 ; Extended_Pictographic# E0.0 [1] () <reserved-1F0D0>
|
||||
1F0F6..1F0FF ; Extended_Pictographic# E0.0 [10] (..) <reserved-1F0F6>..<reserved-1F0FF>
|
||||
1F170..1F171 ; Extended_Pictographic# E0.6 [2] (🅰️..🅱️) A button (blood type)..B button (blood type)
|
||||
1F17E..1F17F ; Extended_Pictographic# E0.6 [2] (🅾️..🅿️) O button (blood type)..P button
|
||||
1F18E ; Extended_Pictographic# E0.6 [1] (🆎) AB button (blood type)
|
||||
1F191..1F19A ; Extended_Pictographic# E0.6 [10] (🆑..🆚) CL button..VS button
|
||||
1F1AD..1F1E5 ; Extended_Pictographic# E0.0 [57] (🆭..) MASK WORK SYMBOL..<reserved-1F1E5>
|
||||
1F1AE..1F1E5 ; Extended_Pictographic# E0.0 [56] (..) <reserved-1F1AE>..<reserved-1F1E5>
|
||||
1F201..1F202 ; Extended_Pictographic# E0.6 [2] (🈁..🈂️) Japanese “here” button..Japanese “service charge” button
|
||||
1F203..1F20F ; Extended_Pictographic# E0.0 [13] (..) <reserved-1F203>..<reserved-1F20F>
|
||||
1F21A ; Extended_Pictographic# E0.6 [1] (🈚) Japanese “free of charge” button
|
||||
|
|
@ -994,7 +963,8 @@ E0020..E007F ; Emoji_Component # E0.0 [96] (..) tag space..c
|
|||
1F23C..1F23F ; Extended_Pictographic# E0.0 [4] (..) <reserved-1F23C>..<reserved-1F23F>
|
||||
1F249..1F24F ; Extended_Pictographic# E0.0 [7] (..) <reserved-1F249>..<reserved-1F24F>
|
||||
1F250..1F251 ; Extended_Pictographic# E0.6 [2] (🉐..🉑) Japanese “bargain” button..Japanese “acceptable” button
|
||||
1F252..1F2FF ; Extended_Pictographic# E0.0 [174] (..) <reserved-1F252>..<reserved-1F2FF>
|
||||
1F252..1F25F ; Extended_Pictographic# E0.0 [14] (..) <reserved-1F252>..<reserved-1F25F>
|
||||
1F266..1F2FF ; Extended_Pictographic# E0.0 [154] (..) <reserved-1F266>..<reserved-1F2FF>
|
||||
1F300..1F30C ; Extended_Pictographic# E0.6 [13] (🌀..🌌) cyclone..milky way
|
||||
1F30D..1F30E ; Extended_Pictographic# E0.7 [2] (🌍..🌎) globe showing Europe-Africa..globe showing Americas
|
||||
1F30F ; Extended_Pictographic# E0.6 [1] (🌏) globe showing Asia-Australia
|
||||
|
|
@ -1010,7 +980,6 @@ E0020..E007F ; Emoji_Component # E0.0 [96] (..) tag space..c
|
|||
1F31D..1F31E ; Extended_Pictographic# E1.0 [2] (🌝..🌞) full moon face..sun with face
|
||||
1F31F..1F320 ; Extended_Pictographic# E0.6 [2] (🌟..🌠) glowing star..shooting star
|
||||
1F321 ; Extended_Pictographic# E0.7 [1] (🌡️) thermometer
|
||||
1F322..1F323 ; Extended_Pictographic# E0.0 [2] (🌢..🌣) BLACK DROPLET..WHITE SUN
|
||||
1F324..1F32C ; Extended_Pictographic# E0.7 [9] (🌤️..🌬️) sun behind small cloud..wind face
|
||||
1F32D..1F32F ; Extended_Pictographic# E1.0 [3] (🌭..🌯) hot dog..burrito
|
||||
1F330..1F331 ; Extended_Pictographic# E0.6 [2] (🌰..🌱) chestnut..seedling
|
||||
|
|
@ -1026,11 +995,8 @@ E0020..E007F ; Emoji_Component # E0.0 [96] (..) tag space..c
|
|||
1F37D ; Extended_Pictographic# E0.7 [1] (🍽️) fork and knife with plate
|
||||
1F37E..1F37F ; Extended_Pictographic# E1.0 [2] (🍾..🍿) bottle with popping cork..popcorn
|
||||
1F380..1F393 ; Extended_Pictographic# E0.6 [20] (🎀..🎓) ribbon..graduation cap
|
||||
1F394..1F395 ; Extended_Pictographic# E0.0 [2] (🎔..🎕) HEART WITH TIP ON THE LEFT..BOUQUET OF FLOWERS
|
||||
1F396..1F397 ; Extended_Pictographic# E0.7 [2] (🎖️..🎗️) military medal..reminder ribbon
|
||||
1F398 ; Extended_Pictographic# E0.0 [1] (🎘) MUSICAL KEYBOARD WITH JACKS
|
||||
1F399..1F39B ; Extended_Pictographic# E0.7 [3] (🎙️..🎛️) studio microphone..control knobs
|
||||
1F39C..1F39D ; Extended_Pictographic# E0.0 [2] (🎜..🎝) BEAMED ASCENDING MUSICAL NOTES..BEAMED DESCENDING MUSICAL NOTES
|
||||
1F39E..1F39F ; Extended_Pictographic# E0.7 [2] (🎞️..🎟️) film frames..admission tickets
|
||||
1F3A0..1F3C4 ; Extended_Pictographic# E0.6 [37] (🎠..🏄) carousel horse..person surfing
|
||||
1F3C5 ; Extended_Pictographic# E1.0 [1] (🏅) sports medal
|
||||
|
|
@ -1045,11 +1011,9 @@ E0020..E007F ; Emoji_Component # E0.0 [96] (..) tag space..c
|
|||
1F3E0..1F3E3 ; Extended_Pictographic# E0.6 [4] (🏠..🏣) house..Japanese post office
|
||||
1F3E4 ; Extended_Pictographic# E1.0 [1] (🏤) post office
|
||||
1F3E5..1F3F0 ; Extended_Pictographic# E0.6 [12] (🏥..🏰) hospital..castle
|
||||
1F3F1..1F3F2 ; Extended_Pictographic# E0.0 [2] (🏱..🏲) WHITE PENNANT..BLACK PENNANT
|
||||
1F3F3 ; Extended_Pictographic# E0.7 [1] (🏳️) white flag
|
||||
1F3F4 ; Extended_Pictographic# E1.0 [1] (🏴) black flag
|
||||
1F3F5 ; Extended_Pictographic# E0.7 [1] (🏵️) rosette
|
||||
1F3F6 ; Extended_Pictographic# E0.0 [1] (🏶) BLACK ROSETTE
|
||||
1F3F7 ; Extended_Pictographic# E0.7 [1] (🏷️) label
|
||||
1F3F8..1F3FA ; Extended_Pictographic# E1.0 [3] (🏸..🏺) badminton..amphora
|
||||
1F400..1F407 ; Extended_Pictographic# E1.0 [8] (🐀..🐇) rat..rabbit
|
||||
|
|
@ -1086,7 +1050,6 @@ E0020..E007F ; Emoji_Component # E0.0 [96] (..) tag space..c
|
|||
1F4F8 ; Extended_Pictographic# E1.0 [1] (📸) camera with flash
|
||||
1F4F9..1F4FC ; Extended_Pictographic# E0.6 [4] (📹..📼) video camera..videocassette
|
||||
1F4FD ; Extended_Pictographic# E0.7 [1] (📽️) film projector
|
||||
1F4FE ; Extended_Pictographic# E0.0 [1] (📾) PORTABLE STEREO
|
||||
1F4FF..1F502 ; Extended_Pictographic# E1.0 [4] (📿..🔂) prayer beads..repeat single button
|
||||
1F503 ; Extended_Pictographic# E0.6 [1] (🔃) clockwise vertical arrows
|
||||
1F504..1F507 ; Extended_Pictographic# E1.0 [4] (🔄..🔇) counterclockwise arrows button..muted speaker
|
||||
|
|
@ -1097,51 +1060,30 @@ E0020..E007F ; Emoji_Component # E0.0 [96] (..) tag space..c
|
|||
1F516..1F52B ; Extended_Pictographic# E0.6 [22] (🔖..🔫) bookmark..water pistol
|
||||
1F52C..1F52D ; Extended_Pictographic# E1.0 [2] (🔬..🔭) microscope..telescope
|
||||
1F52E..1F53D ; Extended_Pictographic# E0.6 [16] (🔮..🔽) crystal ball..downwards button
|
||||
1F546..1F548 ; Extended_Pictographic# E0.0 [3] (🕆..🕈) WHITE LATIN CROSS..CELTIC CROSS
|
||||
1F549..1F54A ; Extended_Pictographic# E0.7 [2] (🕉️..🕊️) om..dove
|
||||
1F54B..1F54E ; Extended_Pictographic# E1.0 [4] (🕋..🕎) kaaba..menorah
|
||||
1F54F ; Extended_Pictographic# E0.0 [1] (🕏) BOWL OF HYGIEIA
|
||||
1F550..1F55B ; Extended_Pictographic# E0.6 [12] (🕐..🕛) one o’clock..twelve o’clock
|
||||
1F55C..1F567 ; Extended_Pictographic# E0.7 [12] (🕜..🕧) one-thirty..twelve-thirty
|
||||
1F568..1F56E ; Extended_Pictographic# E0.0 [7] (🕨..🕮) RIGHT SPEAKER..BOOK
|
||||
1F56F..1F570 ; Extended_Pictographic# E0.7 [2] (🕯️..🕰️) candle..mantelpiece clock
|
||||
1F571..1F572 ; Extended_Pictographic# E0.0 [2] (🕱..🕲) BLACK SKULL AND CROSSBONES..NO PIRACY
|
||||
1F573..1F579 ; Extended_Pictographic# E0.7 [7] (🕳️..🕹️) hole..joystick
|
||||
1F57A ; Extended_Pictographic# E3.0 [1] (🕺) man dancing
|
||||
1F57B..1F586 ; Extended_Pictographic# E0.0 [12] (🕻..🖆) LEFT HAND TELEPHONE RECEIVER..PEN OVER STAMPED ENVELOPE
|
||||
1F587 ; Extended_Pictographic# E0.7 [1] (🖇️) linked paperclips
|
||||
1F588..1F589 ; Extended_Pictographic# E0.0 [2] (🖈..🖉) BLACK PUSHPIN..LOWER LEFT PENCIL
|
||||
1F58A..1F58D ; Extended_Pictographic# E0.7 [4] (🖊️..🖍️) pen..crayon
|
||||
1F58E..1F58F ; Extended_Pictographic# E0.0 [2] (🖎..🖏) LEFT WRITING HAND..TURNED OK HAND SIGN
|
||||
1F590 ; Extended_Pictographic# E0.7 [1] (🖐️) hand with fingers splayed
|
||||
1F591..1F594 ; Extended_Pictographic# E0.0 [4] (🖑..🖔) REVERSED RAISED HAND WITH FINGERS SPLAYED..REVERSED VICTORY HAND
|
||||
1F595..1F596 ; Extended_Pictographic# E1.0 [2] (🖕..🖖) middle finger..vulcan salute
|
||||
1F597..1F5A3 ; Extended_Pictographic# E0.0 [13] (🖗..🖣) WHITE DOWN POINTING LEFT HAND INDEX..BLACK DOWN POINTING BACKHAND INDEX
|
||||
1F5A4 ; Extended_Pictographic# E3.0 [1] (🖤) black heart
|
||||
1F5A5 ; Extended_Pictographic# E0.7 [1] (🖥️) desktop computer
|
||||
1F5A6..1F5A7 ; Extended_Pictographic# E0.0 [2] (🖦..🖧) KEYBOARD AND MOUSE..THREE NETWORKED COMPUTERS
|
||||
1F5A8 ; Extended_Pictographic# E0.7 [1] (🖨️) printer
|
||||
1F5A9..1F5B0 ; Extended_Pictographic# E0.0 [8] (🖩..🖰) POCKET CALCULATOR..TWO BUTTON MOUSE
|
||||
1F5B1..1F5B2 ; Extended_Pictographic# E0.7 [2] (🖱️..🖲️) computer mouse..trackball
|
||||
1F5B3..1F5BB ; Extended_Pictographic# E0.0 [9] (🖳..🖻) OLD PERSONAL COMPUTER..DOCUMENT WITH PICTURE
|
||||
1F5BC ; Extended_Pictographic# E0.7 [1] (🖼️) framed picture
|
||||
1F5BD..1F5C1 ; Extended_Pictographic# E0.0 [5] (🖽..🗁) FRAME WITH TILES..OPEN FOLDER
|
||||
1F5C2..1F5C4 ; Extended_Pictographic# E0.7 [3] (🗂️..🗄️) card index dividers..file cabinet
|
||||
1F5C5..1F5D0 ; Extended_Pictographic# E0.0 [12] (🗅..🗐) EMPTY NOTE..PAGES
|
||||
1F5D1..1F5D3 ; Extended_Pictographic# E0.7 [3] (🗑️..🗓️) wastebasket..spiral calendar
|
||||
1F5D4..1F5DB ; Extended_Pictographic# E0.0 [8] (🗔..🗛) DESKTOP WINDOW..DECREASE FONT SIZE SYMBOL
|
||||
1F5DC..1F5DE ; Extended_Pictographic# E0.7 [3] (🗜️..🗞️) clamp..rolled-up newspaper
|
||||
1F5DF..1F5E0 ; Extended_Pictographic# E0.0 [2] (🗟..🗠) PAGE WITH CIRCLED TEXT..STOCK CHART
|
||||
1F5E1 ; Extended_Pictographic# E0.7 [1] (🗡️) dagger
|
||||
1F5E2 ; Extended_Pictographic# E0.0 [1] (🗢) LIPS
|
||||
1F5E3 ; Extended_Pictographic# E0.7 [1] (🗣️) speaking head
|
||||
1F5E4..1F5E7 ; Extended_Pictographic# E0.0 [4] (🗤..🗧) THREE RAYS ABOVE..THREE RAYS RIGHT
|
||||
1F5E8 ; Extended_Pictographic# E2.0 [1] (🗨️) left speech bubble
|
||||
1F5E9..1F5EE ; Extended_Pictographic# E0.0 [6] (🗩..🗮) RIGHT SPEECH BUBBLE..LEFT ANGER BUBBLE
|
||||
1F5EF ; Extended_Pictographic# E0.7 [1] (🗯️) right anger bubble
|
||||
1F5F0..1F5F2 ; Extended_Pictographic# E0.0 [3] (🗰..🗲) MOOD BUBBLE..LIGHTNING MOOD
|
||||
1F5F3 ; Extended_Pictographic# E0.7 [1] (🗳️) ballot box with ballot
|
||||
1F5F4..1F5F9 ; Extended_Pictographic# E0.0 [6] (🗴..🗹) BALLOT SCRIPT X..BALLOT BOX WITH BOLD CHECK
|
||||
1F5FA ; Extended_Pictographic# E0.7 [1] (🗺️) world map
|
||||
1F5FB..1F5FF ; Extended_Pictographic# E0.6 [5] (🗻..🗿) mount fuji..moai
|
||||
1F600 ; Extended_Pictographic# E1.0 [1] (😀) grinning face
|
||||
|
|
@ -1210,26 +1152,22 @@ E0020..E007F ; Emoji_Component # E0.0 [96] (..) tag space..c
|
|||
1F6BF ; Extended_Pictographic# E1.0 [1] (🚿) shower
|
||||
1F6C0 ; Extended_Pictographic# E0.6 [1] (🛀) person taking bath
|
||||
1F6C1..1F6C5 ; Extended_Pictographic# E1.0 [5] (🛁..🛅) bathtub..left luggage
|
||||
1F6C6..1F6CA ; Extended_Pictographic# E0.0 [5] (🛆..🛊) TRIANGLE WITH ROUNDED CORNERS..GIRLS SYMBOL
|
||||
1F6CB ; Extended_Pictographic# E0.7 [1] (🛋️) couch and lamp
|
||||
1F6CC ; Extended_Pictographic# E1.0 [1] (🛌) person in bed
|
||||
1F6CD..1F6CF ; Extended_Pictographic# E0.7 [3] (🛍️..🛏️) shopping bags..bed
|
||||
1F6D0 ; Extended_Pictographic# E1.0 [1] (🛐) place of worship
|
||||
1F6D1..1F6D2 ; Extended_Pictographic# E3.0 [2] (🛑..🛒) stop sign..shopping cart
|
||||
1F6D3..1F6D4 ; Extended_Pictographic# E0.0 [2] (🛓..🛔) STUPA..PAGODA
|
||||
1F6D5 ; Extended_Pictographic# E12.0 [1] (🛕) hindu temple
|
||||
1F6D6..1F6D7 ; Extended_Pictographic# E13.0 [2] (🛖..🛗) hut..elevator
|
||||
1F6D8..1F6DB ; Extended_Pictographic# E0.0 [4] (..) <reserved-1F6D8>..<reserved-1F6DB>
|
||||
1F6D8 ; Extended_Pictographic# E17.0 [1] () landslide
|
||||
1F6D9..1F6DB ; Extended_Pictographic# E0.0 [3] (..) <reserved-1F6D9>..<reserved-1F6DB>
|
||||
1F6DC ; Extended_Pictographic# E15.0 [1] (🛜) wireless
|
||||
1F6DD..1F6DF ; Extended_Pictographic# E14.0 [3] (🛝..🛟) playground slide..ring buoy
|
||||
1F6E0..1F6E5 ; Extended_Pictographic# E0.7 [6] (🛠️..🛥️) hammer and wrench..motor boat
|
||||
1F6E6..1F6E8 ; Extended_Pictographic# E0.0 [3] (🛦..🛨) UP-POINTING MILITARY AIRPLANE..UP-POINTING SMALL AIRPLANE
|
||||
1F6E9 ; Extended_Pictographic# E0.7 [1] (🛩️) small airplane
|
||||
1F6EA ; Extended_Pictographic# E0.0 [1] (🛪) NORTHEAST-POINTING AIRPLANE
|
||||
1F6EB..1F6EC ; Extended_Pictographic# E1.0 [2] (🛫..🛬) airplane departure..airplane arrival
|
||||
1F6ED..1F6EF ; Extended_Pictographic# E0.0 [3] (..) <reserved-1F6ED>..<reserved-1F6EF>
|
||||
1F6F0 ; Extended_Pictographic# E0.7 [1] (🛰️) satellite
|
||||
1F6F1..1F6F2 ; Extended_Pictographic# E0.0 [2] (🛱..🛲) ONCOMING FIRE ENGINE..DIESEL LOCOMOTIVE
|
||||
1F6F3 ; Extended_Pictographic# E0.7 [1] (🛳️) passenger ship
|
||||
1F6F4..1F6F6 ; Extended_Pictographic# E3.0 [3] (🛴..🛶) kick scooter..canoe
|
||||
1F6F7..1F6F8 ; Extended_Pictographic# E5.0 [2] (🛷..🛸) sled..flying saucer
|
||||
|
|
@ -1237,8 +1175,7 @@ E0020..E007F ; Emoji_Component # E0.0 [96] (..) tag space..c
|
|||
1F6FA ; Extended_Pictographic# E12.0 [1] (🛺) auto rickshaw
|
||||
1F6FB..1F6FC ; Extended_Pictographic# E13.0 [2] (🛻..🛼) pickup truck..roller skate
|
||||
1F6FD..1F6FF ; Extended_Pictographic# E0.0 [3] (..) <reserved-1F6FD>..<reserved-1F6FF>
|
||||
1F774..1F77F ; Extended_Pictographic# E0.0 [12] (🝴..🝿) LOT OF FORTUNE..ORCUS
|
||||
1F7D5..1F7DF ; Extended_Pictographic# E0.0 [11] (🟕..) CIRCLED TRIANGLE..<reserved-1F7DF>
|
||||
1F7DA..1F7DF ; Extended_Pictographic# E0.0 [6] (..) <reserved-1F7DA>..<reserved-1F7DF>
|
||||
1F7E0..1F7EB ; Extended_Pictographic# E12.0 [12] (🟠..🟫) orange circle..brown square
|
||||
1F7EC..1F7EF ; Extended_Pictographic# E0.0 [4] (..) <reserved-1F7EC>..<reserved-1F7EF>
|
||||
1F7F0 ; Extended_Pictographic# E14.0 [1] (🟰) heavy equals sign
|
||||
|
|
@ -1247,7 +1184,10 @@ E0020..E007F ; Emoji_Component # E0.0 [96] (..) tag space..c
|
|||
1F848..1F84F ; Extended_Pictographic# E0.0 [8] (..) <reserved-1F848>..<reserved-1F84F>
|
||||
1F85A..1F85F ; Extended_Pictographic# E0.0 [6] (..) <reserved-1F85A>..<reserved-1F85F>
|
||||
1F888..1F88F ; Extended_Pictographic# E0.0 [8] (..) <reserved-1F888>..<reserved-1F88F>
|
||||
1F8AE..1F8FF ; Extended_Pictographic# E0.0 [82] (..) <reserved-1F8AE>..<reserved-1F8FF>
|
||||
1F8AE..1F8AF ; Extended_Pictographic# E0.0 [2] (..) <reserved-1F8AE>..<reserved-1F8AF>
|
||||
1F8BC..1F8BF ; Extended_Pictographic# E0.0 [4] (..) <reserved-1F8BC>..<reserved-1F8BF>
|
||||
1F8C2..1F8CF ; Extended_Pictographic# E0.0 [14] (..) <reserved-1F8C2>..<reserved-1F8CF>
|
||||
1F8D9..1F8FF ; Extended_Pictographic# E0.0 [39] (..) <reserved-1F8D9>..<reserved-1F8FF>
|
||||
1F90C ; Extended_Pictographic# E13.0 [1] (🤌) pinched fingers
|
||||
1F90D..1F90F ; Extended_Pictographic# E12.0 [3] (🤍..🤏) white heart..pinching hand
|
||||
1F910..1F918 ; Extended_Pictographic# E1.0 [9] (🤐..🤘) zipper-mouth face..sign of the horns
|
||||
|
|
@ -1293,7 +1233,8 @@ E0020..E007F ; Emoji_Component # E0.0 [96] (..) tag space..c
|
|||
1F9CD..1F9CF ; Extended_Pictographic# E12.0 [3] (🧍..🧏) person standing..deaf person
|
||||
1F9D0..1F9E6 ; Extended_Pictographic# E5.0 [23] (🧐..🧦) face with monocle..socks
|
||||
1F9E7..1F9FF ; Extended_Pictographic# E11.0 [25] (🧧..🧿) red envelope..nazar amulet
|
||||
1FA00..1FA6F ; Extended_Pictographic# E0.0 [112] (🨀..) NEUTRAL CHESS KING..<reserved-1FA6F>
|
||||
1FA58..1FA5F ; Extended_Pictographic# E0.0 [8] (..) <reserved-1FA58>..<reserved-1FA5F>
|
||||
1FA6E..1FA6F ; Extended_Pictographic# E0.0 [2] (..) <reserved-1FA6E>..<reserved-1FA6F>
|
||||
1FA70..1FA73 ; Extended_Pictographic# E12.0 [4] (🩰..🩳) ballet shoes..shorts
|
||||
1FA74 ; Extended_Pictographic# E13.0 [1] (🩴) thong sandal
|
||||
1FA75..1FA77 ; Extended_Pictographic# E15.0 [3] (🩵..🩷) light blue heart..pink heart
|
||||
|
|
@ -1304,7 +1245,9 @@ E0020..E007F ; Emoji_Component # E0.0 [96] (..) tag space..c
|
|||
1FA83..1FA86 ; Extended_Pictographic# E13.0 [4] (🪃..🪆) boomerang..nesting dolls
|
||||
1FA87..1FA88 ; Extended_Pictographic# E15.0 [2] (🪇..🪈) maracas..flute
|
||||
1FA89 ; Extended_Pictographic# E16.0 [1] () harp
|
||||
1FA8A..1FA8E ; Extended_Pictographic# E0.0 [5] (..) <reserved-1FA8A>..<reserved-1FA8E>
|
||||
1FA8A ; Extended_Pictographic# E17.0 [1] () trombone
|
||||
1FA8B..1FA8D ; Extended_Pictographic# E0.0 [3] (..) <reserved-1FA8B>..<reserved-1FA8D>
|
||||
1FA8E ; Extended_Pictographic# E17.0 [1] () treasure chest
|
||||
1FA8F ; Extended_Pictographic# E16.0 [1] () shovel
|
||||
1FA90..1FA95 ; Extended_Pictographic# E12.0 [6] (🪐..🪕) ringed planet..banjo
|
||||
1FA96..1FAA8 ; Extended_Pictographic# E13.0 [19] (🪖..🪨) military helmet..rock
|
||||
|
|
@ -1318,7 +1261,10 @@ E0020..E007F ; Emoji_Component # E0.0 [96] (..) tag space..c
|
|||
1FAC0..1FAC2 ; Extended_Pictographic# E13.0 [3] (🫀..🫂) anatomical heart..people hugging
|
||||
1FAC3..1FAC5 ; Extended_Pictographic# E14.0 [3] (🫃..🫅) pregnant man..person with crown
|
||||
1FAC6 ; Extended_Pictographic# E16.0 [1] () fingerprint
|
||||
1FAC7..1FACD ; Extended_Pictographic# E0.0 [7] (..) <reserved-1FAC7>..<reserved-1FACD>
|
||||
1FAC7 ; Extended_Pictographic# E0.0 [1] () <reserved-1FAC7>
|
||||
1FAC8 ; Extended_Pictographic# E17.0 [1] () hairy creature
|
||||
1FAC9..1FACC ; Extended_Pictographic# E0.0 [4] (..) <reserved-1FAC9>..<reserved-1FACC>
|
||||
1FACD ; Extended_Pictographic# E17.0 [1] () orca
|
||||
1FACE..1FACF ; Extended_Pictographic# E15.0 [2] (🫎..🫏) moose..donkey
|
||||
1FAD0..1FAD6 ; Extended_Pictographic# E13.0 [7] (🫐..🫖) blueberries..teapot
|
||||
1FAD7..1FAD9 ; Extended_Pictographic# E14.0 [3] (🫗..🫙) pouring liquid..jar
|
||||
|
|
@ -1329,12 +1275,14 @@ E0020..E007F ; Emoji_Component # E0.0 [96] (..) tag space..c
|
|||
1FAE0..1FAE7 ; Extended_Pictographic# E14.0 [8] (🫠..🫧) melting face..bubbles
|
||||
1FAE8 ; Extended_Pictographic# E15.0 [1] (🫨) shaking face
|
||||
1FAE9 ; Extended_Pictographic# E16.0 [1] () face with bags under eyes
|
||||
1FAEA..1FAEF ; Extended_Pictographic# E0.0 [6] (..) <reserved-1FAEA>..<reserved-1FAEF>
|
||||
1FAEA ; Extended_Pictographic# E17.0 [1] () distorted face
|
||||
1FAEB..1FAEE ; Extended_Pictographic# E0.0 [4] (..) <reserved-1FAEB>..<reserved-1FAEE>
|
||||
1FAEF ; Extended_Pictographic# E17.0 [1] () fight cloud
|
||||
1FAF0..1FAF6 ; Extended_Pictographic# E14.0 [7] (🫰..🫶) hand with index finger and thumb crossed..heart hands
|
||||
1FAF7..1FAF8 ; Extended_Pictographic# E15.0 [2] (🫷..🫸) leftwards pushing hand..rightwards pushing hand
|
||||
1FAF9..1FAFF ; Extended_Pictographic# E0.0 [7] (..) <reserved-1FAF9>..<reserved-1FAFF>
|
||||
1FC00..1FFFD ; Extended_Pictographic# E0.0[1022] (..) <reserved-1FC00>..<reserved-1FFFD>
|
||||
|
||||
# Total elements: 3537
|
||||
# Total elements: 2848
|
||||
|
||||
#EOF
|
||||
|
|
|
|||
|
|
@ -52,16 +52,14 @@ function __do_upload_to_testflight() {
|
|||
local FASTLANE_ITC_PROVIDER="$1"
|
||||
local FASTLANE_API_KEY_ID="$2"
|
||||
local APP_IPA_DST
|
||||
local BUILD_NUMBER
|
||||
|
||||
export FASTLANE_ITC_TEAM_ID="$3"
|
||||
export LC_ALL=en_US.UTF-8
|
||||
export LANG=en_US.UTF-8
|
||||
|
||||
BUILD_NUMBER=$(cat ../VERSION.md)
|
||||
APP_IPA_DST="$4-ios-${BUILD_NUMBER}.ipa"
|
||||
APP_IPA_DST="$4-ios-${KEYMAN_VERSION_FOR_FILENAME}.ipa"
|
||||
|
||||
cd "upload/${BUILD_NUMBER}"
|
||||
cd "upload/${KEYMAN_VERSION}"
|
||||
command -v fastlane
|
||||
# shellcheck disable=SC2154
|
||||
fastlane pilot upload \
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ function make_source_tarball_action() {
|
|||
if builder_is_ci_build_level_release; then
|
||||
builder_echo start "make source tarball" "Make source tarball"
|
||||
rm -rf dist
|
||||
make tmpsources
|
||||
PKG_CONFIG_PATH="${KEYMAN_ROOT}/core/build/arch/release/meson-private" "${KEYMAN_ROOT}/linux/scripts/dist.sh"
|
||||
builder_echo end "make source tarball" success "Finished making source tarball"
|
||||
else
|
||||
builder_echo "Skipping source tarball creation - not release build level"
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")"
|
|||
. "${THIS_SCRIPT%/*}/../../../resources/build/builder-full.inc.sh"
|
||||
## END STANDARD BUILD SCRIPT INCLUDE
|
||||
|
||||
# shellcheck disable=SC2154
|
||||
. "${KEYMAN_ROOT}/resources/build/ci/trigger-definitions.inc.sh"
|
||||
. "${KEYMAN_ROOT}/resources/build/ci/trigger-builds.inc.sh"
|
||||
. "${KEYMAN_ROOT}/resources/build/ci/trigger-build-bot.inc.sh"
|
||||
|
|
@ -29,15 +30,15 @@ if ! builder_has_option --branch; then
|
|||
builder_die "--branch parameter is required"
|
||||
fi
|
||||
|
||||
if [[ ! "$PRNUM" =~ ^([0-9]+|master|beta|stable-[0-9]+\.[0-9]+)$ ]]; then
|
||||
builder_die "Invalid parameter --branch '$PRNUM'; expected 'master', 'beta', 'stable-x.y', or PR number"
|
||||
if [[ ! "${PRNUM}" =~ ^([0-9]+|master|beta|stable-[0-9]+\.[0-9]+)$ ]]; then
|
||||
builder_die "Invalid parameter --branch '${PRNUM}'; expected 'master', 'beta', 'stable-x.y', or PR number"
|
||||
fi
|
||||
|
||||
#
|
||||
# Debug logging
|
||||
#
|
||||
function debug_echo() {
|
||||
if [ ! -z ${DEBUG:-} ]; then
|
||||
if [[ ! -z ${DEBUG:-} ]]; then
|
||||
echo "DEBUG: $1"
|
||||
fi
|
||||
true
|
||||
|
|
@ -59,44 +60,45 @@ function triggerTestBuilds() {
|
|||
|
||||
# Cancel any already running builds for this branch
|
||||
if builder_has_option --dry-run; then
|
||||
builder_echo "DRY RUN: cancel current builds for $branch"
|
||||
builder_echo "DRY RUN: cancel current builds for ${branch}"
|
||||
else
|
||||
node "$KEYMAN_ROOT/resources/build/ci/cancel-builds/cancel-test-builds.mjs" "$branch" "$TEAMCITY_TOKEN"
|
||||
node "${KEYMAN_ROOT}/resources/build/ci/cancel-builds/cancel-test-builds.mjs" "${branch}" "${TEAMCITY_TOKEN}"
|
||||
fi
|
||||
|
||||
for platform in "${!platforms[@]}"; do
|
||||
local platformBuildLevel=${platforms[$platform]}
|
||||
if [[ $platformBuildLevel == skip ]]; then
|
||||
builder_echo heading "$platform: skipping build"
|
||||
local platformBuildLevel=${platforms[${platform}]}
|
||||
if [[ ${platformBuildLevel} == skip ]]; then
|
||||
builder_echo heading "${platform}: skipping build"
|
||||
continue
|
||||
fi
|
||||
|
||||
builder_echo heading "$platform: checking for git changes"
|
||||
eval test_builds='(${'bc_test_$platform'[@]})'
|
||||
builder_echo heading "${platform}: checking for git changes"
|
||||
eval test_builds='(${'bc_test_${platform}'[@]})'
|
||||
# shellcheck disable=SC2154
|
||||
for test_build in "${test_builds[@]}"; do
|
||||
if [[ $test_build == "" ]]; then continue; fi
|
||||
if [[ ${test_build} == "" ]]; then continue; fi
|
||||
found_build=true
|
||||
if [ "${test_build:(-7)}" == "_GitHub" ]; then
|
||||
if [[ "${test_build:(-7)}" == "_GitHub" ]]; then
|
||||
local job=${test_build%_GitHub}
|
||||
|
||||
if builder_has_option --dry-run; then
|
||||
builder_echo "DRY RUN: Triggering GitHub action build $job/$branch, level = $platformBuildLevel"
|
||||
builder_echo "DRY RUN: Triggering GitHub action build ${job}/${branch}, level = ${platformBuildLevel}"
|
||||
else
|
||||
builder_echo "Triggering GitHub action build $job/$branch, level = $platformBuildLevel"
|
||||
triggerGitHubActionsBuild true $platformBuildLevel "$job" "$branch"
|
||||
builder_echo "Triggering GitHub action build ${job}/${branch}, level = ${platformBuildLevel}"
|
||||
triggerGitHubActionsBuild true "${platformBuildLevel}" "${job}" "${branch}" "${KEYMAN_API_CHECK_SKIP}"
|
||||
fi
|
||||
else
|
||||
if builder_has_option --dry-run; then
|
||||
builder_echo "DRY RUN: Triggering build configuration $test_build on teamcity for $branch, level = $platformBuildLevel"
|
||||
builder_echo "DRY RUN: Triggering build configuration ${test_build} on teamcity for ${branch}, level = ${platformBuildLevel}"
|
||||
else
|
||||
builder_echo "Triggering build configuration $test_build on teamcity for $branch, level = $platformBuildLevel"
|
||||
triggerTeamCityBuild true $platformBuildLevel "$test_build" "$vcs_test" "$branch"
|
||||
builder_echo "Triggering build configuration ${test_build} on teamcity for ${branch}, level = ${platformBuildLevel}"
|
||||
triggerTeamCityBuild true "${platformBuildLevel}" "${test_build}" "${vcs_test}" "${branch}"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
done
|
||||
|
||||
if [[ $found_build == false ]]; then
|
||||
if [[ ${found_build} == false ]]; then
|
||||
postSkippedBuildsStatusResult
|
||||
fi
|
||||
}
|
||||
|
|
@ -111,7 +113,7 @@ function postSkippedBuildsStatusResult() {
|
|||
curl --silent --write-out '\n' \
|
||||
--request POST \
|
||||
--header "Accept: application/vnd.github+json" \
|
||||
--header "Authorization: token $GITHUB_TOKEN" \
|
||||
--header "Authorization: token ${GITHUB_TOKEN}" \
|
||||
--data '{"state":"success","description":"Skipping since no platform builds necessary","context":"Test Build (Keyman)"}' \
|
||||
"https://api.github.com/repos/keymanapp/keyman/statuses/${BUILD_VCS_NUMBER}"
|
||||
fi
|
||||
|
|
@ -122,10 +124,10 @@ function postSkippedBuildsStatusResult() {
|
|||
# branches as well as pull requests
|
||||
#
|
||||
|
||||
if [[ ! "$PRNUM" =~ ^[[:digit:]]+$ ]]; then
|
||||
if [[ ! "${PRNUM}" =~ ^[[:digit:]]+$ ]]; then
|
||||
# branch name is 'master', 'beta', or 'stable-x.y'
|
||||
builder_echo "Branch $PRNUM needs to pass tests on all platforms."
|
||||
triggerTestBuilds main_branch_platform_build_levels $PRNUM
|
||||
builder_echo "Branch ${PRNUM} needs to pass tests on all platforms."
|
||||
triggerTestBuilds main_branch_platform_build_levels "${PRNUM}"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
|
|
@ -136,20 +138,20 @@ fi
|
|||
# targeted by the PR other than to ask GitHub, anyway.)
|
||||
#
|
||||
|
||||
builder_echo grey "# Get information about pull request #$PRNUM from GitHub"
|
||||
prinfo=`curl -s -H "User-Agent: @keymanapp" -H "Authorization: Bearer $GITHUB_TOKEN" https://api.github.com/repos/keymanapp/keyman/pulls/$PRNUM`
|
||||
prbase=`echo ${prinfo} | "$JQ" -r '.base.ref'`
|
||||
prhead=`echo ${prinfo} | "$JQ" -r '.head.ref'`
|
||||
prbaserepo=`echo ${prinfo} | "$JQ" -r '.base.repo.html_url'`
|
||||
prheadrepo=`echo ${prinfo} | "$JQ" -r '.head.repo.html_url'`
|
||||
builder_echo grey "# Get information about pull request #${PRNUM} from GitHub"
|
||||
prinfo=$(curl -s -H "User-Agent: @keymanapp" -H "Authorization: Bearer ${GITHUB_TOKEN}" "https://api.github.com/repos/keymanapp/keyman/pulls/${PRNUM}")
|
||||
prbase=$(echo "${prinfo}" | "${JQ}" -r '.base.ref')
|
||||
prhead=$(echo "${prinfo}" | "${JQ}" -r '.head.ref')
|
||||
prbaserepo=$(echo "${prinfo}" | "${JQ}" -r '.base.repo.html_url')
|
||||
prheadrepo=$(echo "${prinfo}" | "${JQ}" -r '.head.repo.html_url')
|
||||
|
||||
debug_echo "PRNUM: $PRNUM"
|
||||
debug_echo "BASE: $prbase ($prbaserepo)"
|
||||
debug_echo "HEAD: $prhead ($prheadrepo)"
|
||||
debug_echo "PRNUM: ${PRNUM}"
|
||||
debug_echo "BASE: ${prbase} (${prbaserepo})"
|
||||
debug_echo "HEAD: ${prhead} (${prheadrepo})"
|
||||
|
||||
prremote=origin
|
||||
if [ "$prbaserepo" != "https://github.com/keymanapp/keyman" ]; then
|
||||
echo "Unknown base repository $prbaserepo."
|
||||
if [[ "${prbaserepo}" != "https://github.com/keymanapp/keyman" ]]; then
|
||||
echo "Unknown base repository ${prbaserepo}."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
|
@ -160,7 +162,7 @@ fi
|
|||
|
||||
# (Ensure we are within the repository before running git calls)
|
||||
builder_echo grey "# Ensure our local branch is up to date"
|
||||
pushd "$KEYMAN_ROOT" > /dev/null
|
||||
pushd "${KEYMAN_ROOT}" > /dev/null
|
||||
git fetch origin > /dev/null
|
||||
|
||||
#
|
||||
|
|
@ -169,10 +171,10 @@ git fetch origin > /dev/null
|
|||
# on untrusted forks.
|
||||
#
|
||||
|
||||
if [ "$prheadrepo" != "https://github.com/keymanapp/keyman" ]; then
|
||||
if [[ "${prheadrepo}" != "https://github.com/keymanapp/keyman" ]]; then
|
||||
prremote=external-rrtb
|
||||
git remote add "$prremote" "$prheadrepo"
|
||||
git fetch "$prremote" > /dev/null
|
||||
git remote add "${prremote}" "${prheadrepo}"
|
||||
git fetch "${prremote}" > /dev/null
|
||||
fi
|
||||
|
||||
#
|
||||
|
|
@ -181,18 +183,18 @@ fi
|
|||
#
|
||||
|
||||
builder_echo grey "# Get list of changed files in the pull request"
|
||||
prfiles=`git diff --name-only "origin/$prbase"..."$prremote/$prhead" || ( if [ $? == 128 ]; then echo abort; else exit $?; fi )`
|
||||
if [ "$prfiles" == "abort" ]; then
|
||||
prfiles=$(git diff --name-only "origin/${prbase}...${prremote}/${prhead}" || ( if [[ $? == 128 ]]; then echo abort; else exit $?; fi ))
|
||||
if [[ "${prfiles}" == "abort" ]]; then
|
||||
# Don't trigger any builds, exit with success
|
||||
if [ "$prremote" != "origin" ]; then
|
||||
git remote remove "$prremote"
|
||||
if [[ "${prremote}" != "origin" ]]; then
|
||||
git remote remove "${prremote}"
|
||||
fi
|
||||
echo "Remote branch origin/$prhead has gone away; probably an automatic pull request. Skipping build."
|
||||
echo "Remote branch origin/${prhead} has gone away; probably an automatic pull request. Skipping build."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ "$prremote" != "origin" ]; then
|
||||
git remote remove "$prremote"
|
||||
if [[ "${prremote}" != "origin" ]]; then
|
||||
git remote remove "${prremote}"
|
||||
fi
|
||||
|
||||
debug_echo "Files found: ${prfiles[*]}"
|
||||
|
|
@ -212,23 +214,23 @@ function find_platform_changes() {
|
|||
while IFS= read -r line; do
|
||||
# for each platform
|
||||
for platform in "${available_platforms[@]}"; do
|
||||
if [[ ! " ${!build_platforms[@]} " =~ " $platform " ]]; then
|
||||
if [[ ! " ${!build_platforms[*]} " =~ " ${platform} " ]]; then
|
||||
# Which platform are we watching?
|
||||
eval watch='$'watch_$platform
|
||||
eval watch="'$'watch_${platform}"
|
||||
|
||||
# Add common patterns to the watch list
|
||||
watch="^(${platform}|(oem/[^/]+/${platform})|resources/((?!teamcity)|teamcity/(${platform}|includes))|${watch})"
|
||||
watch="^(${platform}|(oem/[^/]+/${platform})|resources/((?!teamcity|docker-images)|teamcity/(${platform}|includes)|docker-images/(${platform}|base))|${watch})"
|
||||
# Since bash doesn't support negative look-aheads we use perl to test
|
||||
# (grep has a --perl-regexp option, but not the version on macOS)
|
||||
if perl -e 'exit($ARGV[0] =~ /$ARGV[1]/ ? 0 : 1)' "${line}" "${watch}"; then
|
||||
# By default, we'll build a 'release' test build for touched platforms
|
||||
build_platforms[$platform]=$build_level_release
|
||||
build_platforms[${platform}]=${build_level_release}
|
||||
fi
|
||||
fi
|
||||
done
|
||||
done <<< "$prfiles"
|
||||
done <<< "${prfiles}"
|
||||
|
||||
builder_echo blue "Default build platforms: ${!build_platforms[@]}"
|
||||
builder_echo blue "Default build platforms: ${!build_platforms[*]}"
|
||||
}
|
||||
|
||||
find_platform_changes
|
||||
|
|
@ -238,7 +240,9 @@ find_platform_changes
|
|||
# This will modify the build_platforms array
|
||||
#
|
||||
|
||||
if [ "$prremote" == "origin" ]; then
|
||||
KEYMAN_API_CHECK_SKIP="false"
|
||||
|
||||
if [[ "${prremote}" == "origin" ]]; then
|
||||
# We only accept Build-bot commands on trusted local origin PRs
|
||||
cd "${KEYMAN_ROOT}/resources/build/ci/github"
|
||||
npm ci
|
||||
|
|
@ -249,9 +253,10 @@ if [ "$prremote" == "origin" ]; then
|
|||
NODE_WRAPPER=node
|
||||
fi
|
||||
# Note: we may move all of this into javascript at some point!
|
||||
prcommits=$(${NODE_WRAPPER} api-pull-commits.mjs $GITHUB_TOKEN $PRNUM)
|
||||
test_bot_check_pr_body "$PRNUM" "$prinfo"
|
||||
build_bot_check_messages $PRNUM "$prinfo" "$prcommits"
|
||||
prcommits=$(${NODE_WRAPPER} api-pull-commits.mjs "${GITHUB_TOKEN}" "${PRNUM}")
|
||||
test_bot_check_pr_body "${PRNUM}" "${prinfo}"
|
||||
build_bot_check_messages "${PRNUM}" "${prinfo}" "${prcommits}"
|
||||
KEYMAN_API_CHECK_SKIP="$(is_skip_keyman_api_check "${PRNUM}" "${prinfo}")"
|
||||
fi
|
||||
|
||||
#
|
||||
|
|
@ -260,7 +265,7 @@ fi
|
|||
|
||||
if [[ ! -z "${build_platforms[*]:-}" ]] && (( ${#build_platforms[@]} > 0)); then
|
||||
builder_echo heading "Start test builds"
|
||||
triggerTestBuilds build_platforms $PRNUM
|
||||
triggerTestBuilds build_platforms "${PRNUM}"
|
||||
else
|
||||
builder_echo heading "No builds to start"
|
||||
postSkippedBuildsStatusResult
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ computer browsers.
|
|||
|
||||
<!-- -->
|
||||
|
||||
[What's New](whats-new)
|
||||
[What's New](whatsnew)
|
||||
: What's new in Keyman Engine for Web 19.0
|
||||
|
||||
<!-- -->
|
||||
|
|
|
|||
|
|
@ -1,3 +0,0 @@
|
|||
---
|
||||
title: What's New in KeymanWeb 19.0
|
||||
---
|
||||
7
web/docs/engine/whatsnew.md
Normal file
7
web/docs/engine/whatsnew.md
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
---
|
||||
title: What's New in KeymanWeb 19.0
|
||||
---
|
||||
|
||||
## See also
|
||||
|
||||
* [Keyman Engine for Web Documentation](index)
|
||||
|
|
@ -797,6 +797,7 @@ export default class VisualKeyboard extends EventEmitter<EventMap> implements Ke
|
|||
if (this.usesFixedWidthScaling) {
|
||||
let baseWidth = this.width;
|
||||
baseWidth -= this._borderWidth * 2;
|
||||
baseWidth = (isNaN(baseWidth) || baseWidth < 0) ? 0 : baseWidth;
|
||||
return ParsedLengthStyle.inPixels(baseWidth);
|
||||
} else {
|
||||
return ParsedLengthStyle.forScalar(1);
|
||||
|
|
@ -821,7 +822,9 @@ export default class VisualKeyboard extends EventEmitter<EventMap> implements Ke
|
|||
// Touch OSKs may apply internal padding to prevent row cropping at the edges.
|
||||
// ... why not precompute both, rather than recalculate each time?
|
||||
// - appears to contribute to layout reflow costs on layer swaps!
|
||||
return ParsedLengthStyle.inPixels(this.layoutHeight.val - this._borderWidth * 2 - this.layerGroup.verticalPadding);
|
||||
let baseHeight = this.layoutHeight.val - this._borderWidth * 2 - this.layerGroup.verticalPadding;
|
||||
baseHeight = (isNaN(baseHeight) || baseHeight < 0) ? 0 : baseHeight;
|
||||
return ParsedLengthStyle.inPixels(baseHeight);
|
||||
} else {
|
||||
return ParsedLengthStyle.forScalar(1);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -555,7 +555,6 @@ export class ClassicalDistanceCalculation<
|
|||
return trimmedInstance;
|
||||
}
|
||||
|
||||
// Inputs add an extra row / first index entry.
|
||||
// Inputs add an extra row / first index entry.
|
||||
addInputChar(token: TUnit): this {
|
||||
const returnBuffer = new ClassicalDistanceCalculation<TUnit, TOpSet>(this);
|
||||
|
|
@ -583,7 +582,7 @@ export class ClassicalDistanceCalculation<
|
|||
}
|
||||
|
||||
addMatchChar(token: TUnit): this {
|
||||
let returnBuffer = new ClassicalDistanceCalculation<TUnit, TOpSet>(this);
|
||||
const returnBuffer = new ClassicalDistanceCalculation<TUnit, TOpSet>(this);
|
||||
returnBuffer._addMatchChar(token);
|
||||
return returnBuffer as this;
|
||||
}
|
||||
|
|
|
|||
241
web/src/test/auto/headless/engine/osk/visualKeyboard.tests.ts
Normal file
241
web/src/test/auto/headless/engine/osk/visualKeyboard.tests.ts
Normal file
|
|
@ -0,0 +1,241 @@
|
|||
/*
|
||||
* Keyman is copyright (C) SIL Global. MIT License.
|
||||
*/
|
||||
import { assert } from 'chai';
|
||||
import sinon from 'sinon';
|
||||
// @ts-ignore // Type info unavailable; doing a npm-install for it breaks things much worse in other ways.
|
||||
import { JSDOM } from 'jsdom';
|
||||
|
||||
import { VisualKeyboard } from 'keyman/engine/osk';
|
||||
import { ActiveLayout, Keyboard, KeyboardProperties } from 'keyman/engine/keyboard';
|
||||
import { StylesheetManager } from 'keyman/engine/dom-utils';
|
||||
import { DeviceSpec } from "@keymanapp/web-utils";
|
||||
|
||||
describe('VisualKeyboard', () => {
|
||||
let dom: JSDOM;
|
||||
let mockConfig: any;
|
||||
|
||||
beforeEach(() => {
|
||||
dom = new JSDOM('<!DOCTYPE html><p>Hello world</p>');
|
||||
global.document = dom.window.document;
|
||||
global.getComputedStyle = dom.window.getComputedStyle;
|
||||
|
||||
const mockDevice = { browser: DeviceSpec.Browser.Chrome, formFactor: DeviceSpec.FormFactor.Desktop, OS: DeviceSpec.OperatingSystem.Windows, touchable: false };
|
||||
const mockLayout = sinon.createStubInstance(ActiveLayout) as any;
|
||||
|
||||
const keyboard = sinon.createStubInstance(Keyboard) as any;
|
||||
keyboard.layout.returns(mockLayout);
|
||||
sinon.stub(keyboard, 'isRTL').get(() => false);
|
||||
sinon.stub(keyboard, 'id').get(() => 'test');
|
||||
sinon.stub(keyboard, 'name').get(() => 'Test Keyboard');
|
||||
|
||||
mockConfig = {
|
||||
device: mockDevice,
|
||||
hostDevice: mockDevice,
|
||||
pathConfig: { fonts: '', resources: '' },
|
||||
keyboard: keyboard,
|
||||
keyboardMetadata: sinon.createStubInstance(KeyboardProperties),
|
||||
topContainer: document.createElement('div'),
|
||||
styleSheetManager: sinon.createStubInstance(StylesheetManager),
|
||||
};
|
||||
});
|
||||
|
||||
function createVisualKeyboard(fixedScaling: boolean = true): VisualKeyboard {
|
||||
const vk = new VisualKeyboard(mockConfig);
|
||||
vk.usesFixedHeightScaling = fixedScaling;
|
||||
vk.usesFixedWidthScaling = fixedScaling;
|
||||
vk['_borderWidth'] = 3;
|
||||
return vk;
|
||||
}
|
||||
|
||||
describe('LayoutHeight', () => {
|
||||
it('calculates LayoutHeight correctly for number', () => {
|
||||
const vk = createVisualKeyboard();
|
||||
vk['_height'] = 100;
|
||||
assert.equal(vk.layoutHeight.val, 94);
|
||||
});
|
||||
|
||||
it('calculates LayoutHeight correctly for number string', () => {
|
||||
const vk = createVisualKeyboard();
|
||||
vk['_height'] = "100";
|
||||
assert.equal(vk.layoutHeight.val, 94);
|
||||
});
|
||||
|
||||
it('accepts small heights for LayoutHeight', () => {
|
||||
const vk = createVisualKeyboard();
|
||||
vk['_height'] = "5";
|
||||
assert.equal(vk.layoutHeight.val, 0);
|
||||
});
|
||||
|
||||
it('ignores non-number string for LayoutHeight', () => {
|
||||
const vk = createVisualKeyboard();
|
||||
vk['_height'] = "100px";
|
||||
assert.equal(vk.layoutHeight.val, 0);
|
||||
});
|
||||
|
||||
it('ignores invalid string for LayoutHeight', () => {
|
||||
const vk = createVisualKeyboard();
|
||||
vk['_height'] = "invalid";
|
||||
assert.equal(vk.layoutHeight.val, 0);
|
||||
});
|
||||
|
||||
it('ignores undefined value for LayoutHeight', () => {
|
||||
const vk = createVisualKeyboard();
|
||||
vk['_height'] = undefined;
|
||||
assert.equal(vk.layoutHeight.val, 0);
|
||||
});
|
||||
|
||||
it('ignores null value for LayoutHeight', () => {
|
||||
const vk = createVisualKeyboard();
|
||||
vk['_height'] = null;
|
||||
assert.equal(vk.layoutHeight.val, 0);
|
||||
});
|
||||
|
||||
it('calculates LayoutHeight correctly with fixed scaling', () => {
|
||||
const vk = createVisualKeyboard(true);
|
||||
vk['_height'] = 100;
|
||||
assert.equal(vk.layoutHeight.val, 94);
|
||||
});
|
||||
|
||||
it('calculates LayoutHeight correctly with fixed scaling and string', () => {
|
||||
const vk = createVisualKeyboard(true);
|
||||
vk['_height'] = "100px";
|
||||
assert.equal(vk.layoutHeight.val, 0);
|
||||
});
|
||||
|
||||
it('ignores invalid borderWidth for LayoutHeight', () => {
|
||||
const vk = createVisualKeyboard();
|
||||
vk['_height'] = 100;
|
||||
vk['_borderWidth'] = "3px";
|
||||
assert.equal(vk.layoutHeight.val, 0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('LayoutWidth', () => {
|
||||
it('calculates LayoutWidth correctly for number', () => {
|
||||
const vk = createVisualKeyboard();
|
||||
vk['_width'] = 100;
|
||||
assert.equal(vk.layoutWidth.val, 94);
|
||||
});
|
||||
|
||||
it('calculates LayoutWidth correctly for number string', () => {
|
||||
const vk = createVisualKeyboard();
|
||||
vk['_width'] = "100";
|
||||
assert.equal(vk.layoutWidth.val, 94);
|
||||
});
|
||||
|
||||
it('accepts small heights for LayoutWidth', () => {
|
||||
const vk = createVisualKeyboard();
|
||||
vk['_width'] = "5";
|
||||
assert.equal(vk.layoutWidth.val, 0);
|
||||
});
|
||||
|
||||
it('ignores non-number string for LayoutWidth', () => {
|
||||
const vk = createVisualKeyboard();
|
||||
vk['_width'] = "100px";
|
||||
assert.equal(vk.layoutWidth.val, 0);
|
||||
});
|
||||
|
||||
it('ignores invalid string for LayoutWidth', () => {
|
||||
const vk = createVisualKeyboard();
|
||||
vk['_width'] = "invalid";
|
||||
assert.equal(vk.layoutWidth.val, 0);
|
||||
});
|
||||
|
||||
it('ignores undefined value for LayoutWidth', () => {
|
||||
const vk = createVisualKeyboard();
|
||||
vk['_width'] = undefined;
|
||||
assert.equal(vk.layoutWidth.val, 0);
|
||||
});
|
||||
|
||||
it('ignores null value for LayoutWidth', () => {
|
||||
const vk = createVisualKeyboard();
|
||||
vk['_width'] = null;
|
||||
assert.equal(vk.layoutWidth.val, 0);
|
||||
});
|
||||
|
||||
it('calculates LayoutWidth correctly with fixed scaling', () => {
|
||||
const vk = createVisualKeyboard(true);
|
||||
vk['_width'] = 100;
|
||||
assert.equal(vk.layoutWidth.val, 94);
|
||||
});
|
||||
|
||||
it('calculates LayoutWidth correctly with fixed scaling and string', () => {
|
||||
const vk = createVisualKeyboard(true);
|
||||
vk['_width'] = "100px";
|
||||
assert.equal(vk.layoutWidth.val, 0);
|
||||
});
|
||||
|
||||
it('ignores invalid borderWidth for LayoutWidth', () => {
|
||||
const vk = createVisualKeyboard();
|
||||
vk['_width'] = 100;
|
||||
vk['_borderWidth'] = "3px";
|
||||
assert.equal(vk.layoutWidth.val, 0);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('InternalHeight', () => {
|
||||
it('calculates InternalHeight correctly for number', () => {
|
||||
const vk = createVisualKeyboard();
|
||||
vk['_height'] = 100;
|
||||
assert.equal(vk.internalHeight.val, 88);
|
||||
});
|
||||
|
||||
it('calculates InternalHeight correctly for number string', () => {
|
||||
const vk = createVisualKeyboard();
|
||||
vk['_height'] = "100";
|
||||
assert.equal(vk.internalHeight.val, 88);
|
||||
});
|
||||
|
||||
it('accepts small heights for InternalHeight', () => {
|
||||
const vk = createVisualKeyboard();
|
||||
vk['_height'] = "5";
|
||||
assert.equal(vk.internalHeight.val, 0);
|
||||
});
|
||||
|
||||
it('ignores non-number string for InternalHeight', () => {
|
||||
const vk = createVisualKeyboard();
|
||||
vk['_height'] = "100px";
|
||||
assert.equal(vk.internalHeight.val, 0);
|
||||
});
|
||||
|
||||
it('ignores invalid string for InternalHeight', () => {
|
||||
const vk = createVisualKeyboard();
|
||||
vk['_height'] = "invalid";
|
||||
assert.equal(vk.internalHeight.val, 0);
|
||||
});
|
||||
|
||||
it('ignores undefined value for InternalHeight', () => {
|
||||
const vk = createVisualKeyboard();
|
||||
vk['_height'] = undefined;
|
||||
assert.equal(vk.internalHeight.val, 0);
|
||||
});
|
||||
|
||||
it('ignores null value for InternalHeight', () => {
|
||||
const vk = createVisualKeyboard();
|
||||
vk['_height'] = null;
|
||||
assert.equal(vk.internalHeight.val, 0);
|
||||
});
|
||||
|
||||
it('calculates InternalHeight correctly with fixed scaling', () => {
|
||||
const vk = createVisualKeyboard(true);
|
||||
vk['_height'] = 100;
|
||||
assert.equal(vk.internalHeight.val, 88);
|
||||
});
|
||||
|
||||
it('calculates InternalHeight correctly with fixed scaling and string', () => {
|
||||
const vk = createVisualKeyboard(true);
|
||||
vk['_height'] = "100px";
|
||||
assert.equal(vk.internalHeight.val, 0);
|
||||
});
|
||||
|
||||
it('ignores invalid borderWidth for InternalHeight', () => {
|
||||
const vk = createVisualKeyboard();
|
||||
vk['_height'] = 100;
|
||||
vk['_borderWidth'] = "3px";
|
||||
assert.equal(vk.internalHeight.val, 0);
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
|
@ -188,8 +188,8 @@ describe('computeAlignment', () => {
|
|||
canAlign: true,
|
||||
editPath: [
|
||||
{op: 'substitute', input: 0, match: 0},
|
||||
{op: 'insert', match: 1},
|
||||
{op: 'insert', match: 2}
|
||||
{op: 'insert', match: 1},
|
||||
{op: 'insert', match: 2}
|
||||
],
|
||||
leadTokenShift: 0,
|
||||
leadEditLength: 0,
|
||||
|
|
@ -347,7 +347,7 @@ describe('computeAlignment', () => {
|
|||
assert.deepEqual(computedAlignment, {
|
||||
canAlign: true,
|
||||
editPath: [
|
||||
{op: 'insert', match: 0},
|
||||
{op: 'insert', match: 0},
|
||||
{op: 'match', input: 0, match: 1},
|
||||
{op: 'match', input: 1, match: 2},
|
||||
{op: 'match', input: 2, match: 3},
|
||||
|
|
@ -399,7 +399,7 @@ describe('computeAlignment', () => {
|
|||
assert.deepEqual(computedAlignment, {
|
||||
canAlign: true,
|
||||
editPath: [
|
||||
{op: 'insert', match: 0},
|
||||
{op: 'insert', match: 0},
|
||||
{op: 'substitute', input: 0, match: 1},
|
||||
{op: 'match', input: 1, match: 2},
|
||||
{op: 'match', input: 2, match: 3},
|
||||
|
|
@ -430,7 +430,7 @@ describe('computeAlignment', () => {
|
|||
{op: 'match', input: 2, match: 1},
|
||||
{op: 'match', input: 3, match: 2},
|
||||
{op: 'match', input: 4, match: 3},
|
||||
{op: 'insert', match: 4}
|
||||
{op: 'insert', match: 4}
|
||||
],
|
||||
leadTokenShift: -1,
|
||||
leadEditLength: 0,
|
||||
|
|
@ -483,7 +483,7 @@ describe('computeAlignment', () => {
|
|||
{op: 'match', input: 2, match: 2},
|
||||
{op: 'match', input: 3, match: 3},
|
||||
{op: 'substitute', input: 4, match: 4},
|
||||
{op: 'insert', match: 5}
|
||||
{op: 'insert', match: 5}
|
||||
],
|
||||
leadTokenShift: 0,
|
||||
leadEditLength: 1,
|
||||
|
|
@ -505,7 +505,7 @@ describe('computeAlignment', () => {
|
|||
assert.deepEqual(computedAlignment, {
|
||||
canAlign: true,
|
||||
editPath: [
|
||||
{op: 'insert', match: 0},
|
||||
{op: 'insert', match: 0},
|
||||
{op: 'match', input: 0, match: 1},
|
||||
{op: 'match', input: 1, match: 2},
|
||||
{op: 'match', input: 2, match: 3},
|
||||
|
|
@ -532,7 +532,7 @@ describe('computeAlignment', () => {
|
|||
assert.deepEqual(computedAlignment, {
|
||||
canAlign: true,
|
||||
editPath: [
|
||||
{op: 'insert', match: 0},
|
||||
{op: 'insert', match: 0},
|
||||
{op: 'match', input: 0, match: 1},
|
||||
{op: 'match', input: 1, match: 2},
|
||||
{op: 'match', input: 2, match: 3},
|
||||
|
|
@ -559,7 +559,7 @@ describe('computeAlignment', () => {
|
|||
assert.deepEqual(computedAlignment, {
|
||||
canAlign: true,
|
||||
editPath: [
|
||||
{op: 'insert', match: 0},
|
||||
{op: 'insert', match: 0},
|
||||
{op: 'match', input: 0, match: 1},
|
||||
{op: 'match', input: 1, match: 2},
|
||||
{op: 'match', input: 2, match: 3},
|
||||
|
|
@ -608,7 +608,7 @@ describe('computeAlignment', () => {
|
|||
canAlign: false,
|
||||
editPath: [
|
||||
{op: 'match', input: 0, match: 0},
|
||||
{op: 'insert', match: 1},
|
||||
{op: 'insert', match: 1},
|
||||
{op: 'match', input: 1, match: 2},
|
||||
{op: 'match', input: 2, match: 3},
|
||||
{op: 'match', input: 3, match: 4}
|
||||
|
|
@ -653,7 +653,7 @@ describe('computeAlignment', () => {
|
|||
{op: 'match', input: 1, match: 1},
|
||||
{op: 'match', input: 2, match: 2},
|
||||
{op: 'match', input: 3, match: 3},
|
||||
{op: 'insert', match: 4},
|
||||
{op: 'insert', match: 4},
|
||||
{op: 'match', input: 4, match: 5}
|
||||
]
|
||||
});
|
||||
|
|
@ -715,8 +715,8 @@ describe('computeAlignment', () => {
|
|||
{op: 'match', input: 8, match: 8},
|
||||
{op: 'match', input: 9, match: 9},
|
||||
{op: 'substitute', input: 10, match: 10},
|
||||
{op: 'insert', match: 11},
|
||||
{op: 'insert', match: 12}
|
||||
{op: 'insert', match: 11},
|
||||
{op: 'insert', match: 12}
|
||||
],
|
||||
leadTokenShift: 0,
|
||||
leadEditLength: 0,
|
||||
|
|
|
|||
|
|
@ -138,8 +138,8 @@ describe('ContextTokenization', function() {
|
|||
{op: 'match', input: 4, match: 4},
|
||||
{op: 'match', input: 5, match: 5},
|
||||
{op: 'match', input: 6, match: 6},
|
||||
{op: 'insert', match: 7},
|
||||
{op: 'insert', match: 8}
|
||||
{op: 'insert', match: 7},
|
||||
{op: 'insert', match: 8}
|
||||
],
|
||||
leadTokenShift: 0,
|
||||
leadEditLength: 0,
|
||||
|
|
@ -436,8 +436,8 @@ describe('ContextTokenization', function() {
|
|||
targetTokens, {
|
||||
canAlign: true,
|
||||
editPath: [
|
||||
{op: 'insert', match: 0},
|
||||
{op: 'insert', match: 1},
|
||||
{op: 'insert', match: 0},
|
||||
{op: 'insert', match: 1},
|
||||
{op: 'match', input: 0, match: 2},
|
||||
{op: 'match', input: 1, match: 3},
|
||||
{op: 'match', input: 2, match: 4},
|
||||
|
|
@ -614,8 +614,8 @@ describe('ContextTokenization', function() {
|
|||
{op: 'match', input: 10, match: 9},
|
||||
{op: 'match', input: 11, match: 10},
|
||||
{op: 'match', input: 12, match: 11},
|
||||
{op: 'insert', match: 12},
|
||||
{op: 'insert', match: 13}
|
||||
{op: 'insert', match: 12},
|
||||
{op: 'insert', match: 13}
|
||||
],
|
||||
leadTokenShift: 1, // "'",
|
||||
leadEditLength: 1, // "n't" / "t"
|
||||
|
|
|
|||
|
|
@ -592,7 +592,7 @@ describe('Classical Damerau-Levenshtein edit-distance calculation', function() {
|
|||
{ op: 'match', input: 1 /* 'c' */, match: 1 /* 'c' */},
|
||||
{ op: 'match', input: 2 /* 'c' */, match: 2 /* 'c' */},
|
||||
{ op: 'match', input: 3 /* 'o' */, match: 3 /* 'o' */},
|
||||
{ op: 'insert', match: 4 /* 'm' */}, // insert is earlier
|
||||
{ op: 'insert', match: 4 /* 'm' */}, // insert is earlier
|
||||
{ op: 'match', input: 4 /* 'm' */, match: 5 /* 'm' */}, // longer contiguous match sequence
|
||||
{ op: 'match', input: 5 /* 'o' */, match: 6 /* 'o' */},
|
||||
{ op: 'match', input: 6 /* 'd' */, match: 7 /* 'd' */},
|
||||
|
|
@ -605,7 +605,7 @@ describe('Classical Damerau-Levenshtein edit-distance calculation', function() {
|
|||
{ op: 'match', input: 2 /* 'c' */, match: 2 /* 'c' */},
|
||||
{ op: 'match', input: 3 /* 'o' */, match: 3 /* 'o' */},
|
||||
{ op: 'match', input: 4 /* 'm' */, match: 4 /* 'm' */},
|
||||
{ op: 'insert', match: 5 /* 'm' */}, // now inserting later.
|
||||
{ op: 'insert', match: 5 /* 'm' */}, // now inserting later.
|
||||
{ op: 'match', input: 5 /* 'o' */, match: 6 /* 'o' */},
|
||||
{ op: 'match', input: 6 /* 'd' */, match: 7 /* 'd' */},
|
||||
{ op: 'match', input: 7 /* 'a' */, match: 8 /* 'a' */},
|
||||
|
|
@ -635,7 +635,7 @@ describe('Classical Damerau-Levenshtein edit-distance calculation', function() {
|
|||
{ op: 'delete', input: 3},
|
||||
{ op: 'match', input: 4, match: 3},
|
||||
{ op: 'match', input: 5, match: 4},
|
||||
{ op: 'insert', match: 5}
|
||||
{ op: 'insert', match: 5}
|
||||
];
|
||||
|
||||
const viablePaths = buffer.editPath();
|
||||
|
|
@ -687,14 +687,14 @@ describe('Classical Damerau-Levenshtein edit-distance calculation', function() {
|
|||
{ op: 'match', input: 1, match: 1}, // best sequence: continguous matches
|
||||
{ op: 'match', input: 2, match: 2}, // + adjacent substitutes
|
||||
{ op: 'substitute', input: 3, match: 3},
|
||||
{ op: 'insert', match: 4},
|
||||
{ op: 'insert', match: 4},
|
||||
];
|
||||
|
||||
let altSequence: EditTuple<string>[] = [
|
||||
{ op: 'match', input: 0, match: 0},
|
||||
{ op: 'match', input: 1, match: 1},
|
||||
{ op: 'match', input: 2, match: 2},
|
||||
{ op: 'insert', match: 3},
|
||||
{ op: 'insert', match: 3},
|
||||
{ op: 'substitute', input: 3, match: 4},
|
||||
];
|
||||
|
||||
|
|
@ -717,7 +717,7 @@ describe('Classical Damerau-Levenshtein edit-distance calculation', function() {
|
|||
{ op: 'match', input: 5, match: 3},
|
||||
{ op: 'match', input: 6, match: 4},
|
||||
{ op: 'transpose-start', input: 7, match: 5},
|
||||
{ op: 'transpose-insert', match: 6},
|
||||
{ op: 'transpose-insert', match: 6},
|
||||
{ op: 'transpose-end', input: 8, match: 7}
|
||||
];
|
||||
|
||||
|
|
|
|||
|
|
@ -147,7 +147,6 @@ describe('Split/merge aware edit-distance calculation', () => {
|
|||
assert.equal(calc.getFinalCost(), 4);
|
||||
|
||||
const editPaths = calc.editPath();
|
||||
assert.isAbove(editPaths.length, 3);
|
||||
assert.sameDeepOrderedMembers(editPaths[0], [
|
||||
{ op: 'split', input: 0, match: 0 },
|
||||
{ op: 'split', input: 0, match: 1 },
|
||||
|
|
@ -156,6 +155,26 @@ describe('Split/merge aware edit-distance calculation', () => {
|
|||
{ op: 'merge', input: 3, match: 4 },
|
||||
{ op: 'merge', input: 4, match: 4 }
|
||||
]);
|
||||
|
||||
// ('insert', 'substitute') can be reordered
|
||||
// ('substitute', 'delete') can be reordered
|
||||
// There also exist cases where one pair or the other, but not both,
|
||||
// are considered for the edit path.
|
||||
assert.includeDeepMembers(editPaths, [[
|
||||
{ op: 'insert', match: 0 }, // -> 'b'
|
||||
{ op: 'substitute', input: 0, match: 1 }, // 'abc' -> 'c'
|
||||
{ op: 'match', input: 1, match: 2 }, // 'd' == 'd'
|
||||
{ op: 'match', input: 2, match: 3 }, // 'e' == 'e'
|
||||
{ op: 'substitute', input: 3, match: 4 }, // 'f' -> 'fgh'
|
||||
{ op: 'delete', input: 4 } // 'g' ->
|
||||
]]);
|
||||
|
||||
// both split and merge: 1 variation
|
||||
// split, but not merge: 2 variations
|
||||
// merge, but not split: 2 variations
|
||||
// neither: 2x2 = 4 variations
|
||||
// sum: 9
|
||||
assert.equal(editPaths.length, 9);
|
||||
});
|
||||
|
||||
it("abcd,e,f,g -> b,c,d,efgh = 4", () => {
|
||||
|
|
@ -180,10 +199,10 @@ describe('Split/merge aware edit-distance calculation', () => {
|
|||
]);
|
||||
|
||||
assert.sameDeepOrderedMembers(editPaths[1], [
|
||||
{ op: 'substitute', input: 0, match: 0 },
|
||||
{ op: 'substitute', input: 1, match: 1 },
|
||||
{ op: 'substitute', input: 2, match: 2 },
|
||||
{ op: 'substitute', input: 3, match: 3 }
|
||||
{ op: 'substitute', input: 0, match: 0 }, // 'abcd' -> 'b'
|
||||
{ op: 'substitute', input: 1, match: 1 }, // 'e' -> 'c'
|
||||
{ op: 'substitute', input: 2, match: 2 }, // 'f' -> 'd'
|
||||
{ op: 'substitute', input: 3, match: 3 } // 'g' -> 'efgh'
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
|
@ -3,5 +3,5 @@ title: Does Keyman support Unicode?
|
|||
---
|
||||
|
||||
Yes, since Keyman 5, Keyman fully supports the Unicode Standard, up to
|
||||
and including Unicode 13.0. We also update Keyman with each new release
|
||||
and including Unicode 17.0. We also update Keyman with each new release
|
||||
of the Unicode Standard.
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ builder_describe "Installation files for Keyman for Windows" \
|
|||
# after all other builds complete
|
||||
|
||||
builder_if_release_build_level builder_describe_outputs \
|
||||
publish /windows/release/${KEYMAN_VERSION}/keyman-${KEYMAN_VERSION}.exe
|
||||
publish /windows/release/${KEYMAN_VERSION}/keyman-${KEYMAN_VERSION_FOR_FILENAME}.exe
|
||||
|
||||
builder_parse "$@"
|
||||
|
||||
|
|
@ -104,7 +104,7 @@ function copy-installer() {
|
|||
|
||||
mkdir -p "$KEYMAN_ROOT/windows/release/${KEYMAN_VERSION}"
|
||||
cp keymandesktop.msi "$KEYMAN_ROOT/windows/release/${KEYMAN_VERSION}/keymandesktop.msi"
|
||||
cp keymandesktop.exe "$KEYMAN_ROOT/windows/release/${KEYMAN_VERSION}/keyman-${KEYMAN_VERSION}.exe"
|
||||
cp keymandesktop.exe "$KEYMAN_ROOT/windows/release/${KEYMAN_VERSION}/keyman-${KEYMAN_VERSION_FOR_FILENAME}.exe"
|
||||
cp "$WINDOWS_PROGRAM_APP/setup.exe" "$KEYMAN_ROOT/windows/release/${KEYMAN_VERSION}/setup.exe"
|
||||
|
||||
verify-installer-signatures
|
||||
|
|
|
|||
|
|
@ -88,14 +88,19 @@ type
|
|||
procedure HandleFirstRun;
|
||||
function CurrentStateName: string;
|
||||
(**
|
||||
* Checks if Keyman is the WaitingRestartState and that
|
||||
* Keyman has not run in this Windows session.
|
||||
* The sole purpose is for the calling code then produce
|
||||
* a UI to confirm the user wants to continue install.
|
||||
* Checks if Keyman is the WaitingRestartState, the cache is valid
|
||||
* and that Keyman has not run in this Windows session. It also confirms
|
||||
* that automatic updates are still enabled #14295.
|
||||
* The purpose is for the calling code can choose to produce
|
||||
* a UI to confirm the user wants to install an update,
|
||||
* if everything is ready to start a update.
|
||||
*
|
||||
* NOTE: If it finds the cache is invalid it will abort causing
|
||||
* the State Machine to change state, returning to idle.
|
||||
*
|
||||
* @returns True if the Keyman is ready to install.
|
||||
*)
|
||||
function ReadyToInstall: Boolean;
|
||||
function ValidateReadyToInstall: Boolean;
|
||||
function IsInstallingState: Boolean;
|
||||
|
||||
function GetAutomaticUpdates: Boolean;
|
||||
|
|
@ -558,14 +563,27 @@ begin
|
|||
Result := CurrentState.ClassName;
|
||||
end;
|
||||
|
||||
function TUpdateStateMachine.ReadyToInstall: Boolean;
|
||||
function TUpdateStateMachine.ValidateReadyToInstall: Boolean;
|
||||
begin
|
||||
if not IsCurrentStateAssigned then
|
||||
Exit(False);
|
||||
if (CurrentState is WaitingRestartState) and not HasKeymanRun then
|
||||
Result := True
|
||||
else
|
||||
Result := False;
|
||||
|
||||
if not (CurrentState is WaitingRestartState) then
|
||||
Exit(False);
|
||||
|
||||
// Verify conditions since entering WaitingRestartState:
|
||||
// If the cache is not valid or automatic updates have
|
||||
// been disabled clear the cache and return to the idle state.
|
||||
if not TUpdateCheckStorage.CheckMetaDataForUpdate or not Self.GetAutomaticUpdates then
|
||||
begin
|
||||
HandleAbort;
|
||||
Exit(False);
|
||||
end;
|
||||
|
||||
if not HasKeymanRun then
|
||||
Exit(True);
|
||||
|
||||
Result := False;
|
||||
end;
|
||||
|
||||
function TUpdateStateMachine.IsInstallingState: Boolean;
|
||||
|
|
@ -955,7 +973,7 @@ begin
|
|||
// Return to Idle state and check for Updates state
|
||||
ChangeState(IdleState);
|
||||
bucStateContext.CurrentState.HandleCheck;
|
||||
Result := kmShellExit;
|
||||
Result := kmShellContinue;
|
||||
end
|
||||
else
|
||||
begin
|
||||
|
|
|
|||
|
|
@ -668,20 +668,11 @@ function ShouldSendToBUpdateSM(FSilent: Boolean; BUpdateSM: TUpdateStateMachine;
|
|||
// UI elements from the state machine we have bring some of logic here.
|
||||
var
|
||||
frmStartInstall: TfrmStartInstall;
|
||||
ReadyToInstall: Boolean;
|
||||
ValidateReadyToInstall: Boolean;
|
||||
begin
|
||||
ReadyToInstall := BUpdateSM.ReadyToInstall;
|
||||
// The setting for automatic updates may have been set to disable
|
||||
// after updates were checked and downloaded. The user should
|
||||
// not be prompted for an update in this case and the update should
|
||||
// abort.
|
||||
if not BUpdateSM.GetAutomaticUpdates and ReadyToInstall then
|
||||
begin
|
||||
BUpdateSM.HandleAbort;
|
||||
Exit(False);
|
||||
end;
|
||||
ValidateReadyToInstall := BUpdateSM.ValidateReadyToInstall;
|
||||
|
||||
if not FSilent and ReadyToInstall and
|
||||
if not FSilent and ValidateReadyToInstall and
|
||||
(FMode in [fmStart, fmSplash, fmMain, fmAbout,
|
||||
fmHelp, fmShowHelp, fmSettings, fmBoot]) then
|
||||
begin
|
||||
|
|
@ -692,7 +683,7 @@ begin
|
|||
frmStartInstall.Free;
|
||||
end;
|
||||
end
|
||||
else if FSilent and ReadyToInstall then
|
||||
else if FSilent and ValidateReadyToInstall then
|
||||
Result := False
|
||||
else
|
||||
Result := True;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue