#!/usr/bin/env bash # Build and validate the EurKEY-macOS keyboard layout bundle. # # Regenerates Info.plist with correct KLInfo entries for all layout versions, # sets the bundle version, and validates the bundle structure. # # Usage: bash scripts/build-bundle.sh [--version YYYY.MM.DD] set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)" BUILD_DIR="${PROJECT_DIR}/build" BUNDLE_DIR="${BUILD_DIR}/EurKEY-Next.bundle" CONTENTS_DIR="${BUNDLE_DIR}/Contents" RESOURCES_DIR="${CONTENTS_DIR}/Resources" # parse arguments VERSION="${1:-$(date +%Y.%m.%d)}" if [[ "${1:-}" == "--version" ]]; then VERSION="${2:?missing version argument}" fi BUNDLE_ID="de.felixfoertsch.keyboardlayout.EurKEY-Next" BUNDLE_NAME="EurKEY-Next" # layout names to include (EurKEY Next is the main layout, others are legacy versions) LAYOUTS=("EurKEY Next" "EurKEY v1.4" "EurKEY v1.3" "EurKEY v1.2") SRC_DIR="${PROJECT_DIR}/src" echo "Building ${BUNDLE_NAME} ${VERSION}" echo "Bundle: ${BUNDLE_DIR}" echo # --- generate icons from SVG sources --- bash "${SCRIPT_DIR}/build-icons.sh" # --- assemble bundle from src/ --- rm -rf "${BUNDLE_DIR}" mkdir -p "${RESOURCES_DIR}" for layout in "${LAYOUTS[@]}"; do cp "${SRC_DIR}/keylayouts/${layout}.keylayout" "${RESOURCES_DIR}/" cp "${SRC_DIR}/icons/${layout}.icns" "${RESOURCES_DIR}/" done for lang in en de es; do mkdir -p "${RESOURCES_DIR}/${lang}.lproj" cp "${SRC_DIR}/lproj/${lang}.lproj/InfoPlist.strings" "${RESOURCES_DIR}/${lang}.lproj/" done echo "Assembled bundle from src/" # --- generate Info.plist --- cat > "${CONTENTS_DIR}/Info.plist" << 'PLIST_HEADER' CFBundleIdentifier PLIST_HEADER echo " ${BUNDLE_ID}" >> "${CONTENTS_DIR}/Info.plist" cat >> "${CONTENTS_DIR}/Info.plist" << 'PLIST_NAME' CFBundleName PLIST_NAME echo " ${BUNDLE_NAME}" >> "${CONTENTS_DIR}/Info.plist" cat >> "${CONTENTS_DIR}/Info.plist" << 'PLIST_VERSION' CFBundleVersion PLIST_VERSION echo " ${VERSION}" >> "${CONTENTS_DIR}/Info.plist" # add KLInfo for each layout for layout in "${LAYOUTS[@]}"; do # generate input source ID: bundle id + layout name lowercased, spaces removed source_id_suffix=$(echo "${layout}" | tr '[:upper:]' '[:lower:]' | tr -d ' ') source_id="${BUNDLE_ID}.${source_id_suffix}" cat >> "${CONTENTS_DIR}/Info.plist" << KLINFO_ENTRY KLInfo_${layout} TICapsLockLanguageSwitchCapable TISIconIsTemplate TISInputSourceID ${source_id} TISIntendedLanguage en KLINFO_ENTRY done cat >> "${CONTENTS_DIR}/Info.plist" << 'PLIST_FOOTER' PLIST_FOOTER echo "Generated Info.plist with ${#LAYOUTS[@]} layout entries" # --- generate version.plist --- cat > "${CONTENTS_DIR}/version.plist" << VPLIST BuildVersion ${VERSION} ProjectName ${BUNDLE_NAME} SourceVersion ${VERSION} VPLIST echo "Generated version.plist (${VERSION})" # --- validate with plutil --- if command -v plutil &> /dev/null; then plutil -lint "${CONTENTS_DIR}/Info.plist" || exit 1 plutil -lint "${CONTENTS_DIR}/version.plist" || exit 1 echo "plist validation passed" fi # --- run layout validation --- if [[ -f "${SCRIPT_DIR}/validate_layouts.py" ]]; then echo python3 "${SCRIPT_DIR}/validate_layouts.py" || exit 1 fi echo echo "Bundle build complete: ${BUNDLE_DIR}" echo "Version: ${VERSION}"