From 34a1b3be69da6ddf09bf72cbbf974729c4c370d3 Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Fri, 24 Sep 2021 08:18:36 +0700 Subject: [PATCH 01/73] fix: Use css keyword `initial` instead of `unset` --- cdn/dev/keyboard-search/search.css | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cdn/dev/keyboard-search/search.css b/cdn/dev/keyboard-search/search.css index ba9720a0..239b69ac 100644 --- a/cdn/dev/keyboard-search/search.css +++ b/cdn/dev/keyboard-search/search.css @@ -295,7 +295,7 @@ h2 a { #keyboard-details-col .col { float: none; - max-width: unset; + max-width: initial; } table#keyboard-details, @@ -439,7 +439,7 @@ html[data-platform='unknown'] .download.download-unknown { } #search-results:empty + #search-results-empty { - display: unset; + display: initial; } /* Embedded formatting */ From 03711bdd3673a1909a0047b80ac42c857d76eec8 Mon Sep 17 00:00:00 2001 From: Darcy Date: Wed, 17 Aug 2022 11:06:34 +0700 Subject: [PATCH 02/73] chore: Start .htaccess files --- .htaccess | 126 ++++++++++++++++++++++++++++++++++ iphone-and-ipad/app/.htaccess | 3 + 2 files changed, 129 insertions(+) create mode 100644 .htaccess create mode 100644 iphone-and-ipad/app/.htaccess diff --git a/.htaccess b/.htaccess new file mode 100644 index 00000000..bc683718 --- /dev/null +++ b/.htaccess @@ -0,0 +1,126 @@ +# This file is used when running with Apache. Adapted from web.config. +# NOTE: this is not very well tested... + +php_value include_path "/var/www/html/_includes:." + +RewriteEngine on + +# TODO: SSL + + +# TODO: Add 301 permanent redirects, append query strings + +# macosx and macos to mac" (ignore case) +RedirectMatch "(?i)/(macosx|macos)\b(.*)$" "/mac$2" + +# Redirect deprecated Google Plus link +RedirectMatch "(?i)/plus.*" "/" + +# /donate -> donate.keyman.com +RedirectMatch "(?i)/donate(\/.*)?" "https://donate.keyman.com" + +# /privacy -> SIL Privacy policy +RedirectMatch "(?i)/privacy(\/.*)?" "https://software.sil.org/language-software-privacy-policy/" + +# desktop to windows +RedirectMatch "(?i)desktop(\/.*)?" "/windows$1" + + +# +# Keyboard landing pages (TODO) +# + + +# Synonym paths + +# 10.0 to 15.0 +# /1X.0 to /1X landing page +RedirectMatch "/1([0-5])(\.0)\/?" "/1$1/" + +# ios +RedirectMatch "/(?!iphone-and-ipad)(ios|iphone|ipad)(\/.*)?" "/iphone-and-ipad$2" + +# Connect With Art landing page +RedirectMatch "/connectwithart(\/|$)" "https://sites.google.com/sil.org/connectwithart/home" + +# per-language landing pages +RedirectMatch "/albanian(\/?)$" "/keyboards/basic_kbdal" +RedirectMatch "/ancient-egyptian(\/?)$" "/keyboards/hieroglyphic" +RedirectMatch "/ancient-hebrew(\/?)$" "/keyboards/galaxie_greek_hebrew_mnemonic" +RedirectMatch "/arabic(\/?)$" "/keyboards/basic_kbda1" +RedirectMatch "/assamese(\/?)$" "/keyboards/isis_bangla" +RedirectMatch "/basic_kbdsn1(\/?)$" "/keyboards/basic_kbdsn1" +RedirectMatch "/bengali(\/?)$" "/keyboards/basic_kbdinbe2" +RedirectMatch "/cherokee(\/?)$" "/keyboards/cherokee6" +RedirectMatch "/cheyenne(\/?)$" "/keyboards/sil_cheyenne" +RedirectMatch "/dinka(\/?)$" "/keyboards/el_dinka" +RedirectMatch "/dutch(\/?)$" "/keyboards/basic_kbdne" +RedirectMatch "/farsi(\/?)$" "/keyboards/farsi_unicode" +RedirectMatch "/hebrew(\/?)$" "/keyboards/basic_kbdheb" +RedirectMatch "/hindi(\/?)$" "/keyboards/basic_kbdindev" +RedirectMatch "/igbo(\/?)$" "/keyboards/sil_nigeria_dot" +RedirectMatch "/khmer(\/?)$" "/keyboards/khmer_angkor" +RedirectMatch "/lao(\/?)$" "/keyboards/basic_kbdlao" +RedirectMatch "/malayalam(\/?)$" "/keyboards/basic_kbdinmal" +RedirectMatch "/maltese(\/?)$" "/keyboards/maltese" +RedirectMatch "/marathi(\/?)$" "/keyboards/basic_kbdinmar" +RedirectMatch "/mongolian(\/?)$" "/keyboards/basic_kbdmon" +RedirectMatch "/nepali(\/?)$" "/keyboards/basic_kbdnepr" +RedirectMatch "/oriya(\/?)$" "/keyboards/basic_kbdinori" +RedirectMatch "/rawang(\/?)$" "/keyboards/rawang" +RedirectMatch "/russian(\/?)$" "/keyboards/basic_kbdru" +RedirectMatch "/serbian(\/?)$" "/keyboards/basic_kbdycc" +RedirectMatch "/sindhi(\/?)$" "/keyboards/mbsindhi" +RedirectMatch "/thai(\/?)$" "/keyboards/thai-uni" +RedirectMatch "/yiddish(\/?)$" "/keyboards/yiddish_pasekh" +RedirectMatch "/yoruba(\/?)$" "/keyboards/sil_yoruba8" + +RedirectMatch "/ancient-greek(\/?)$" "/keyboards/h/greek" +RedirectMatch "/(french|german|italian|spanish|swedish)(\/?)$" "/keyboards/h/eurolatin" + +# dedicated-keyboard-landing pages +RedirectMatch "/(amharic|burmese|cameroon|ethiopic|eurolatin|greek|ipa|sinhala|tamil|tibetan|tigrigna|urdu)(\/.*)?$" "/keyboards/h/$1$2" + +# +# PHP and Markdown rewriting +# + +# Remove index or index.php and redirect (and stop processing) +RewriteRule "^((.+)/)?index(\.php)?$" "$1" [R,L] + +# Remove .php extension and redirect +RewriteCond "%{DOCUMENT_ROOT}/$1" -f +RewriteRule "^(.+)\.php$" "$1" [R,L] + + +# Redirect folder without / to include / +RewriteCond "$1" -d +RewriteCond "%{DOCUMENT_ROOT}/$1.php" !-f +RewriteCond "%{DOCUMENT_ROOT}/$1.md" !-f +RewriteRule "^(.+[^/])$" "$1/" [R,L] + +# +# PHP rewriting +# + +# Rewrite file to file.md +RewriteCond "%{DOCUMENT_ROOT}/$1.md" -f +RewriteRule "^(.+)$" "/_includes/md/mdhost.php?file=$1.md" + +RewriteCond "%{DOCUMENT_ROOT}/$1.md" -f +RewriteRule "^(.+)\.md$" "/_includes/md/mdhost.php?file=$1.md" + +# Rewrite file to file.php +RewriteCond "%{DOCUMENT_ROOT}/$1.php" -f +RewriteCond "%{DOCUMENT_ROOT}/$1.md" !-f +RewriteRule "^(.+)$" "$1.php" + +# Rewrite folder/ to folder/index.md +RewriteCond "%{DOCUMENT_ROOT}/$1/index.md" -f +#RewriteCond "%{DOCUMENT_ROOT}/$1/index.php" !-f # not needed? +RewriteRule "^(.+)/$" "/_includes/md/mdhost.php?file=$1/index.md" + +# Rewrite folder/ to folder/index.php - Infinite redirection? +#RewriteCond "%{DOCUMENT_ROOT}/$1/index.php" -f +#RewriteCond "%{DOCUMENT_ROOT}/$1/index.md" !-f +#RewriteRule "^(.+)/$" "$1/index.php" diff --git a/iphone-and-ipad/app/.htaccess b/iphone-and-ipad/app/.htaccess new file mode 100644 index 00000000..c798b232 --- /dev/null +++ b/iphone-and-ipad/app/.htaccess @@ -0,0 +1,3 @@ + +# Redirect /iphone-and-ipad/app to help.keyman.com +RedirectMatch "/iphone-and-ipad/app/.*" "https://help.keyman.com/products/iphone-and-ipad/" From efea437e1512ee9ce7d70ff1e4c912aa507456c0 Mon Sep 17 00:00:00 2001 From: Darcy Date: Wed, 17 Aug 2022 15:33:54 +0700 Subject: [PATCH 03/73] chore: Start go redirects --- .htaccess | 47 ++++++++++++++++++++++++++++++-- _legacy/.htaccess | 31 +++++++++++++++++++++ android/app/.htaccess | 3 ++ archive/.htaccess | 4 +++ downloads/releases/.htaccess | 10 +++++++ go/.htaccess | 32 ++++++++++++++++++++++ go/android/.htaccess | 8 ++++++ go/desktop/.htaccess | 51 ++++++++++++++++++++++++++++++++++ go/developer/.htaccess | 53 ++++++++++++++++++++++++++++++++++++ go/download/.htaccess | 5 ++++ go/ios/.htaccess | 8 ++++++ go/linux/.htaccess | 18 ++++++++++++ go/macos/.htaccess | 5 ++++ go/windows/.htaccess | 20 ++++++++++++++ 14 files changed, 293 insertions(+), 2 deletions(-) create mode 100644 _legacy/.htaccess create mode 100644 android/app/.htaccess create mode 100644 archive/.htaccess create mode 100644 downloads/releases/.htaccess create mode 100644 go/.htaccess create mode 100644 go/android/.htaccess create mode 100644 go/desktop/.htaccess create mode 100644 go/developer/.htaccess create mode 100644 go/download/.htaccess create mode 100644 go/ios/.htaccess create mode 100644 go/linux/.htaccess create mode 100644 go/macos/.htaccess create mode 100644 go/windows/.htaccess diff --git a/.htaccess b/.htaccess index bc683718..cdf073db 100644 --- a/.htaccess +++ b/.htaccess @@ -5,7 +5,7 @@ php_value include_path "/var/www/html/_includes:." RewriteEngine on -# TODO: SSL +# TODO: SSL and WWW # TODO: Add 301 permanent redirects, append query strings @@ -30,12 +30,55 @@ RedirectMatch "(?i)desktop(\/.*)?" "/windows$1" # Keyboard landing pages (TODO) # +# Cleanup various URLS with permanent redirects + +# /keyboards/{install|download|share}/{id}/ to /keyboards/x/id +RedirectMatch "^keyboards/(install|download|share)/([^/]+)/$" "keyboards/$1/$2" + +# /keyboards/{id}/ to /keyboards/id +RedirectMatch "^keyboards/([^/]+)/$" "keyboards/$1" + +# /keyboards/ to /keyboards +RedirectMatch "^keyboards/$" "keyboards" + +# Old share url /keyboards/{id}/share[/] to /keyboards/share/id +RedirectMatch "^keyboards/(?!install|download|share)/share(/?)$" "/keyboards/share/$1" + +# /keyboard/{content} to /keyboards/... +RedirectMatch "/keyboard(/.*)$" "/keyboards$1" + +# +# Install | Download | Share | bare | .json --> +# + +# /keyboards/install/[id] to /keyboards/install.php +#RewriteRule "^keyboards/install/([^/]+)$" "https://keyman.com/keyboards/install.php?id=$1" + + +# +# Search +# + +# /keyboards?q=... to /keyboards/index.php +RewriteRule "^keyboards$" "keyboards/index.php" [L] + +# /keyboards/languages to /keyboards/index.php +RewriteRule "^keyboards/languages/(.*)" "keyboards/index.php?q=l:id:$1" [L] + +# /keyboards/download to /keyboards/download.php +RewriteRule "^keyboards/download(.php)?" "keyboards/download.php" [L] + +# /keyboards/legacy to /keyboards/keyboard.php +RewriteRule "^keyboards/legacy/(.*)" "keyboards/keyboard.php?legacy=$1" [L] + +# /keyboards/countries to /keyboards/index.php +RewriteRule "^keyboards/countries/(.*)" "keyboards/index.php?q=c:id:$1" [L] # Synonym paths # 10.0 to 15.0 # /1X.0 to /1X landing page -RedirectMatch "/1([0-5])(\.0)\/?" "/1$1/" +RedirectMatch "^/1([0-5])(\.0)\/?" "/1$1/" # ios RedirectMatch "/(?!iphone-and-ipad)(ios|iphone|ipad)(\/.*)?" "/iphone-and-ipad$2" diff --git a/_legacy/.htaccess b/_legacy/.htaccess new file mode 100644 index 00000000..ac4b07bc --- /dev/null +++ b/_legacy/.htaccess @@ -0,0 +1,31 @@ + +# Keyboard search +# legacy /keyboards?q=... to /keyboards/index.php +RedirectMatch "/_legacy/keyboards" "/keyboards/index.php" + +# legacy /keyboards/ to /keyboards +RedirectMatch "/_legacy/keyboards/" "/keyboards" + +# legacy /keyboards/languages to /keyboards/index.php +RedirectMatch "/_legacy/keyboards/languages/(.*)" "/keyboards/index.php?q=l:id:$1" + +# "legacy /keyboards/download to /keyboards/download.php" +RedirectMatch "/_legacy/keyboards/download(\.php)?" "/keyboards/download.php" + +# "legacy /keyboards/legacy to /keyboards/keyboard.php" +RedirectMatch "/_legacy/keyboards/legacy/(.*)" "/keyboards/keyboard.php?legacy=$1" + +# "legacy /keyboards/countries to /keyboards/index.php" +RedirectMatch "/_legacy/keyboards/countries/(.*)" "/keyboards/index.php?q=c:id:$1" + +# "legacy /keyboards/{name}/share to /keyboards/share.php" +RedirectMatch "/_legacy/keyboards/([^/]+)/share" "/keyboards/share.php?id=$1" + +# "legacy /keyboards/{name}.json to /keyboards/keyboard.json.php" +RedirectMatch "/_legacy/keyboards/(.*)\.json$" "/keyboards/keyboard.json.php?id=$1" + +# "legacy /keyboards/{name} to /keyboards/keyboard.php" +RedirectMatch "/_legacy/keyboards/(.*)" "/keyboards/keyboard.php?id=$1" + +# "legacy /keyboard/{name} to /keyboards/..." stopProcessing="true"> +RedirectMatch "/_legacy/keyboard/(.*)$" "/keyboards/$1" diff --git a/android/app/.htaccess b/android/app/.htaccess new file mode 100644 index 00000000..544cf4cf --- /dev/null +++ b/android/app/.htaccess @@ -0,0 +1,3 @@ + +# Redirect /android/app to help.keyman.com +RedirectMatch ".*" "https://help.keyman.com/products/android/" diff --git a/archive/.htaccess b/archive/.htaccess new file mode 100644 index 00000000..f616ce95 --- /dev/null +++ b/archive/.htaccess @@ -0,0 +1,4 @@ + +# Redirect /archive/downloads.php" +# TODO: Permanent +RedirectMatch "/archive/downloads.php" "/downloads/archive/" \ No newline at end of file diff --git a/downloads/releases/.htaccess b/downloads/releases/.htaccess new file mode 100644 index 00000000..11d14944 --- /dev/null +++ b/downloads/releases/.htaccess @@ -0,0 +1,10 @@ + +# releases-tier/download" +# note: the tier is currently ignored +RedirectMatch "/downloads/releases/(alpha|beta|stable)/(.+)$" "/downloads/releases/_version_downloads.php?tier=$1&version=$2" + +# "releases-download" +RedirectMatch "/downloads/releases/(?!_version_downloads.php)(.+)$" "/downloads/releases/_version_downloads.php?version=$1" + +# index" +RedirectMatch "/downloads/releases$" "/downloads/" diff --git a/go/.htaccess b/go/.htaccess new file mode 100644 index 00000000..271329fa --- /dev/null +++ b/go/.htaccess @@ -0,0 +1,32 @@ + +# why +RedirectMatch "/go/why\/?$" "https://marc.durdin.net/2018/03/the-case-for-keyman/" + +# Developer 10.0 onward redirects for package guide +RedirectMatch "/go/(([1-9][0-9])([.]?)([0-9]))/developer-help-(mobile|packages)(/)?" "https://help.keyman.com/developer/$1/guides/distribute/packages" + +# TODO: Download redirects for keyboard permalinks (these three rules need refresh) + +# +# go/package/download +# + +# download-model/keyboard package +#RedirectMatch "/go/package/download/model/([^/]+)$" "https://keyman.com/go/package/download.php?type=model&id=$1" +RedirectMatch "/go/package/download/(model|keyboard)/([^\/]+)\/?$" "https://keyman2.com/go/package/download.php?type=$1&id=$2" + +# keyboard/id/share +RedirectMatch "/go/keyboard/([^/?]+)/share$" "/keyboards/share/$1" + +# +# Non-app-specific endpoints +# + +# go/support +RedirectMatch "/go/([1-9][0-9]\.[0-9])/support$" "https://help.keyman.com/" + +# go/privacy +RedirectMatch "/go/([1-9][0-9]\.[0-9])/privacy$" "/privacy" + +# go/community +RedirectMatch "/go/([1-9][0-9]\.[0-9])/community$" "https://community.software.sil.org/c/keyman" diff --git a/go/android/.htaccess b/go/android/.htaccess new file mode 100644 index 00000000..16d5cec2 --- /dev/null +++ b/go/android/.htaccess @@ -0,0 +1,8 @@ + +# Links for Android 14.0 onward + +# /go/android/X.Y/download-keyboards/languages" +RedirectMatch "/go/android/([1-9][0-9]\.[0-9])/download-keyboards/languages/(.*)" "/keyboards/languages/$2?embed=android&embed_version=$1" + +# "/go/android/X.Y/download-keyboards" +RedirectMatch "/go/android/([1-9][0-9]\.[0-9])/download-keyboards" "/keyboards?embed=android&embed_version=$1" diff --git a/go/desktop/.htaccess b/go/desktop/.htaccess new file mode 100644 index 00000000..81c358b8 --- /dev/null +++ b/go/desktop/.htaccess @@ -0,0 +1,51 @@ + +# Links for Desktop 10.0-13.0 (for 14.0 onward, see ../windows/web.config) + +# /go/desktop/13.0/download-keyboards" +RedirectMatch "/go/desktop/(7|8|9|10|11|12|13)\.0/download-keyboards" "/_legacy/keyboards/?embed=windows" + + +# /go/desktop/X.Y/download-keyboards" +RedirectMatch "/go/desktop/([1-9][0-9]\.[0-9])/download-keyboards" "/keyboards?embed=windows" + + +# /go/desktop/X.Y/keep-in-touch" +RedirectMatch "/go/desktop/([1-9][0-9]\.[0-9])/keep-in-touch" "/desktop/keepintouch-100" + + +# /go/desktop/X.Y/forums" +RedirectMatch "/go/desktop/([1-9][0-9]\.[0-9])/forums" "https://community.software.sil.org/c/keyman" + + +# /go/desktop/X.Y/issue-1285" +RedirectMatch "/go/desktop/([1-9][0-9]\.[0-9])/issue-1285" "https://blog.keyman.com/2018/11/keyman-windows-10-1803-and-amharic-tigrinya-sinhala" + + +# /go/desktop/X.Y/support" +RedirectMatch "/go/desktop/([1-9][0-9]\.[0-9])/support" "/support" + + +# /go/desktop/X.Y/create-locale" +RedirectMatch "/go/desktop/([1-9][0-9]\.[0-9])/create-locale" "https://secure.tavultesoft.com/keyman/support/locale/" + + +# /go/desktop/X.Y/view-exception/ to /contact/exception" +# This endpoint is not used in 14.0 or later +RedirectMatch "/go/desktop/1[0123]\.0/view-exception(/)?$" "/contact/exception.php" + + +# /go/desktop/X.Y/view-exception?id=" +# This endpoint is not used in 14.0 or later --> +RedirectMatch "/go/desktop/1[0123]\.0/view-exception?id=(.+)$" "/contact/exception.php?id=$1" + + +# /go/desktop/X.Y/home" +RedirectMatch "/go/desktop/([1-9][0-9]\.[0-9])/home" "/desktop/" + + +# /go/desktop/X.Y/archived-downloads" +RedirectMatch "/go/desktop/([1-9][0-9]\.[0-9])/archived-downloads" "/downloads/archive" + + +# /go/desktop/X.Y/privacy" +RedirectMatch "/go/desktop/([1-9][0-9]\.[0-9])/privacy" "/privacy" diff --git a/go/developer/.htaccess b/go/developer/.htaccess new file mode 100644 index 00000000..a058071f --- /dev/null +++ b/go/developer/.htaccess @@ -0,0 +1,53 @@ + +# Links for Developer 10.0 onward + +# "/go/developer/X.Y/help-keyboards" +RedirectMatch "/go/developer/([1-9][0-9]\.[0-9])/help-keyboards" "https://help.keyman.com/developer/keyboards/" + + +# Direct help to the major version +# "/go/developer/X.Y/help-(mobile|packages)" +RedirectMatch "/go/developer/([1-9][0-9])\.([0-9])/help-(mobile|packages)" "https://help.keyman.com/developer/$1.0/guides/distribute/packages" + +# "/go/developer/X.Y/keymanweb" +RedirectMatch "/go/developer/([1-9][0-9]\.[0-9])/keymanweb" "/developer/keymanweb/" + +# "/go/developer/X.Y/keyman-engine-home" +RedirectMatch "/go/developer/([1-9][0-9]\.[0-9])/keyman-engine-home" "/engine/" + + +# "/go/developer/X.Y/language-lookup" +RedirectMatch "/go/developer/([1-9][0-9]\.[0-9])/language-lookup" "https://www.ethnologue.com/" + + +# "/go/developer/X.Y/view-exception/ to /contact/exception" +RedirectMatch "/go/developer/([1-9][0-9]\.[0-9])/view-exception(/)?$" "/contact/exception.php" + + +# "/go/developer/X.Y/view-exception?id=" +RedirectMatch "/go/developer/([1-9][0-9]\.[0-9])/view-exception?id=(.+)$" "/contact/exception.php?id=$2" + + +# Context-sensitive help in Keyman Developer + +# "/go/developer/X.Y/docs/language" +RedirectMatch "/go/developer/([1-9][0-9]\.[0-9])/docs/language(\/?(.*))" "https://help.keyman.com/developer/language/$3" + + +# All other context help, direct to the major version +# "/go/developer/X.Y/docs" +RedirectMatch "/go/developer/([1-9][0-9])\.[0-9]/docs(\/?(.*))" "https://help.keyman.com/developer/$1.0/$3" + + +# "/go/developer/X.Y/home" +RedirectMatch "/go/developer/([1-9][0-9]\.[0-9])/home" "/developer/" + + +# "/go/developer/X.Y/ios-app" +# see includes/appstore.php +RedirectMatch "/go/developer/([1-9][0-9]\.[0-9])/ios-app" "https://itunes.apple.com/us/app/keyman/id933676545?ls=1&mt=8" + + +# "/go/developer/X.Y/android-app" +# see includes/playstore.php +RedirectMatch "/go/developer/([1-9][0-9]\.[0-9])/android-app" "https://play.google.com/store/apps/details?id=com.tavultesoft.kmapro" diff --git a/go/download/.htaccess b/go/download/.htaccess new file mode 100644 index 00000000..3220c485 --- /dev/null +++ b/go/download/.htaccess @@ -0,0 +1,5 @@ + +# Links for Developer 10.0 onward + +# /go/download/program +RedirectMatch "/go/download/(?!_download.php)(.+)" "/go/download/_download.php?object=$1" diff --git a/go/ios/.htaccess b/go/ios/.htaccess new file mode 100644 index 00000000..53561877 --- /dev/null +++ b/go/ios/.htaccess @@ -0,0 +1,8 @@ + +# Links for iOS 14.0 onward + +# "/go/ios/X.Y/download-keyboards/languages" +RedirectMatch "/go/ios/([1-9][0-9]\.[0-9])/download-keyboards/languages/(.*)" "/keyboards/languages/$2?embed=ios&embed_version=$1" + +# "/go/ios/X.Y/download-keyboards" +RedirectMatch "/go/ios/([1-9][0-9]\.[0-9])/download-keyboards" "/keyboards?embed=ios&embed_version=$1" diff --git a/go/linux/.htaccess b/go/linux/.htaccess new file mode 100644 index 00000000..ee303088 --- /dev/null +++ b/go/linux/.htaccess @@ -0,0 +1,18 @@ + +# Redirects for Keyman for Linux 11.0 onward + +# "/go/linux/X.Y/download-keyboards" +RedirectMatch "/go/linux/([1-9][0-9]\.[0-9])/download-keyboards" "/keyboards?embed=linux" + +# "/go/linux/X.Y/forums" stopProcessing="true"> +RedirectMatch "/go/linux/([1-9][0-9]\.[0-9])/forums" "https://community.software.sil.org/c/keyman" + +# "/go/linux/X.Y/support" stopProcessing="true"> +RedirectMatch "/go/linux/([1-9][0-9]\.[0-9])/support" "/support" + +# "/go/linux/X.Y/privacy" stopProcessing="true"> +RedirectMatch "/go/linux/([1-9][0-9]\.[0-9])/privacy" "/privacy" + +# permanent link to screenshot of linux-configuration +# "/go/linux/X.Y/linux-configuration.png" +RedirectMatch "/go/linux/([1-9][0-9]\.[0-9])/linux-configuration.png" "/cdn/dev/img/linux-configuration.png" diff --git a/go/macos/.htaccess b/go/macos/.htaccess new file mode 100644 index 00000000..5945fd4c --- /dev/null +++ b/go/macos/.htaccess @@ -0,0 +1,5 @@ + +# Redirects for Keyman 10.0 for macOS onward + +# /go/macos/X.Y/download-keyboards +RedirectMatch "/go/macos/([1-9][0-9]\.[0-9])/download-keyboards" "/keyboards?embed=macos" diff --git a/go/windows/.htaccess b/go/windows/.htaccess new file mode 100644 index 00000000..4b02e5e1 --- /dev/null +++ b/go/windows/.htaccess @@ -0,0 +1,20 @@ + +# Links for Keyman for Windows 14.0 onward + +# "/go/windows/X.Y/download-keyboards" stopProcessing="true"> +RedirectMatch "/go/windows/([1-9][0-9]\.[0-9])/download-keyboards" "/keyboards?embed=windows" + +# "/go/windows/X.Y/keep-in-touch" stopProcessing="true">0 +RedirectMatch "/go/windows/([1-9][0-9]\.[0-9])/keep-in-touch" "/windows/keepintouch-140" + +# "/go/windows/X.Y/issue-1285" stopProcessing="true"> +RedirectMatch "/go/windows/([1-9][0-9]\.[0-9])/issue-1285" "https://blog.keyman.com/2018/11/keyman-windows-10-1803-and-amharic-tigrinya-sinhala" + +# "/go/windows/X.Y/create-locale" stopProcessing="true"> +RedirectMatch "/go/windows/([1-9][0-9]\.[0-9])/create-locale" "https://translate.keyman.com/" + +# "/go/windows/X.Y/home" stopProcessing="true"> +RedirectMatch "/go/windows/([1-9][0-9]\.[0-9])/home" "/windows/" + +# "/go/windows/X.Y/archived-downloads" stopProcessing="true"> +RedirectMatch "/go/windows/([1-9][0-9]\.[0-9])/archived-downloads" "/downloads/archive" From ddb67324ff2ccb4bd4a094ed312510be9e73d78e Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Thu, 1 Sep 2022 11:03:27 +0700 Subject: [PATCH 04/73] chore: Fix redirects (esp for mdhost) --- .htaccess | 69 ++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 51 insertions(+), 18 deletions(-) diff --git a/.htaccess b/.htaccess index cdf073db..7c0dc388 100644 --- a/.htaccess +++ b/.htaccess @@ -5,7 +5,15 @@ php_value include_path "/var/www/html/_includes:." RewriteEngine on -# TODO: SSL and WWW +# Redirect http://keyman.com to https://keyman.com, +# but only if on a live site (keyman.com) and not +# matching `/.well-known/(.*)$` (for Let's Encrypt) + + Redirect "/" "https://keyman.com" + + +# Custom error messages +# ErrorDocument 404 /_includes/errors/404.php # TODO: Add 301 permanent redirects, append query strings @@ -32,14 +40,21 @@ RedirectMatch "(?i)desktop(\/.*)?" "/windows$1" # Cleanup various URLS with permanent redirects +# TODO: Permanent redirects 301? + + +# Stop processing dedicated keyboard landing pages +#RewriteRule "^keyboards/h/.*$" - [L] + # /keyboards/{install|download|share}/{id}/ to /keyboards/x/id -RedirectMatch "^keyboards/(install|download|share)/([^/]+)/$" "keyboards/$1/$2" +#RedirectMatch "^keyboards/(install|download|share)/([^/]+)/$" "/keyboards/$1/$2" +RewriteRule "^keyboards/(install|download|share)/([^/]+)/$" "/keyboards/$1/$2" [R,L] # /keyboards/{id}/ to /keyboards/id -RedirectMatch "^keyboards/([^/]+)/$" "keyboards/$1" +RedirectMatch "^keyboards/([^/]+)/$" "/keyboards/$1" # /keyboards/ to /keyboards -RedirectMatch "^keyboards/$" "keyboards" +RedirectMatch "^keyboards/$" "/keyboards" # Old share url /keyboards/{id}/share[/] to /keyboards/share/id RedirectMatch "^keyboards/(?!install|download|share)/share(/?)$" "/keyboards/share/$1" @@ -52,7 +67,22 @@ RedirectMatch "/keyboard(/.*)$" "/keyboards$1" # # /keyboards/install/[id] to /keyboards/install.php -#RewriteRule "^keyboards/install/([^/]+)$" "https://keyman.com/keyboards/install.php?id=$1" +RewriteRule "^keyboards/install/([^/]+)$" "/keyboards/install.php?id=$1" [L] + +# /keyboards/download/[id] to /keyboards/keyboard.php +# This formerly redirected to a download, but we no longer need it; keep it for +# legacy links +RewriteRule "^keyboards/download/([^/]+)$" "/keyboards/keyboard.php?id=$1" [L] + +# /keyboards/share/[id] to /keyboards/share.php +# if the keyboard exists in the repo, then share.php will redirecct to /keyboards/ +RewriteRule "^keyboards/share/(^/]+)$" "/keyboards/share.php?id=$1" [L] + +# /keyboards/{id}.json to /keyboards/keyboard.json.php +RewriteRule "^keyboards/(.*)\.json$" "/keyboards/keyboard.json.php?id=$1" + +# /keyboards/{id} to /keyboards/keyboard.php +RewriteRule "^keyboards/([^/]+)$" "/keyboards/keyboard.php?id=$1" [L] # @@ -60,19 +90,19 @@ RedirectMatch "/keyboard(/.*)$" "/keyboards$1" # # /keyboards?q=... to /keyboards/index.php -RewriteRule "^keyboards$" "keyboards/index.php" [L] +RewriteRule "^keyboards$" "/keyboards/index.php" [L] # /keyboards/languages to /keyboards/index.php -RewriteRule "^keyboards/languages/(.*)" "keyboards/index.php?q=l:id:$1" [L] +RewriteRule "^keyboards/languages/(.*)" "/keyboards/index.php?q=l:id:$1" [L] # /keyboards/download to /keyboards/download.php -RewriteRule "^keyboards/download(.php)?" "keyboards/download.php" [L] +RewriteRule "^keyboards/download(.php)?" "/keyboards/download.php" [L] # /keyboards/legacy to /keyboards/keyboard.php -RewriteRule "^keyboards/legacy/(.*)" "keyboards/keyboard.php?legacy=$1" [L] +RewriteRule "^keyboards/legacy/(.*)" "/keyboards/keyboard.php?legacy=$1" [L] # /keyboards/countries to /keyboards/index.php -RewriteRule "^keyboards/countries/(.*)" "keyboards/index.php?q=c:id:$1" [L] +RewriteRule "^keyboards/countries/(.*)" "/keyboards/index.php?q=c:id:$1" [L] # Synonym paths @@ -129,39 +159,42 @@ RedirectMatch "/(amharic|burmese|cameroon|ethiopic|eurolatin|greek|ipa|sinhala|t # # Remove index or index.php and redirect (and stop processing) -RewriteRule "^((.+)/)?index(\.php)?$" "$1" [R,L] +RewriteCond "$1/index" -f [OR] +RewriteCond "$1/index.php" -f +RewriteRule "^((.+)/)?index(\.php)?$" "/$1" [R,L] # Remove .php extension and redirect -RewriteCond "%{DOCUMENT_ROOT}/$1" -f +RewriteCond "$1.php" -f RewriteRule "^(.+)\.php$" "$1" [R,L] # Redirect folder without / to include / RewriteCond "$1" -d -RewriteCond "%{DOCUMENT_ROOT}/$1.php" !-f -RewriteCond "%{DOCUMENT_ROOT}/$1.md" !-f +RewriteCond "$1.php" !-f +RewriteCond "$1.md" !-f RewriteRule "^(.+[^/])$" "$1/" [R,L] # # PHP rewriting # +# TODO: mdhost currently in a different path than help.keyman + # Rewrite file to file.md RewriteCond "%{DOCUMENT_ROOT}/$1.md" -f -RewriteRule "^(.+)$" "/_includes/md/mdhost.php?file=$1.md" +RewriteRule "^(.+)$" "/_includes/includes/md/mdhost.php?file=$1.md" RewriteCond "%{DOCUMENT_ROOT}/$1.md" -f -RewriteRule "^(.+)\.md$" "/_includes/md/mdhost.php?file=$1.md" +RewriteRule "^(.+)\.md$" "/_includes/includes/md/mdhost.php?file=$1.md" # Rewrite file to file.php RewriteCond "%{DOCUMENT_ROOT}/$1.php" -f RewriteCond "%{DOCUMENT_ROOT}/$1.md" !-f -RewriteRule "^(.+)$" "$1.php" # Rewrite folder/ to folder/index.md RewriteCond "%{DOCUMENT_ROOT}/$1/index.md" -f #RewriteCond "%{DOCUMENT_ROOT}/$1/index.php" !-f # not needed? -RewriteRule "^(.+)/$" "/_includes/md/mdhost.php?file=$1/index.md" +RewriteRule "^(.+)/$" "/_includes/includes/md/mdhost.php?file=$1/index.md" # Rewrite folder/ to folder/index.php - Infinite redirection? #RewriteCond "%{DOCUMENT_ROOT}/$1/index.php" -f From c703bcc15ed78a39a23f27c1a263b3092279019d Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Fri, 2 Sep 2022 08:22:58 +0700 Subject: [PATCH 05/73] chore: lowercase .png files --- .htaccess | 2 +- .../{keyman-settings.PNG => keyman-settings.png} | Bin .../{keyman-settings2.PNG => keyman-settings2.png} | Bin .../{keyman-settings3.PNG => keyman-settings3.png} | Bin .../{keyman-settings4.PNG => keyman-settings4.png} | Bin .../{keyman-settings5.PNG => keyman-settings5.png} | Bin .../{keyman-settings6.PNG => keyman-settings6.png} | Bin cdn/dev/img/app/{upgrade1.PNG => upgrade1.png} | Bin cdn/dev/img/app/{upgrade2.PNG => upgrade2.png} | Bin cdn/dev/img/app/{upgrade3.PNG => upgrade3.png} | Bin ...splashscreen-25.PNG => dev10splashscreen-25.png} | Bin ...{dev10splashscreen.PNG => dev10splashscreen.png} | Bin .../img/{devcharmap-25.PNG => devcharmap-25.png} | Bin .../{distribution-25.PNG => distribution-25.png} | Bin .../img/{fonthelper-pro.PNG => fonthelper-pro.png} | Bin ...ard-debugger-25.PNG => keyboard-debugger-25.png} | Bin .../{keyboard-kmw-25.PNG => keyboard-kmw-25.png} | Bin ...eyboard-source-25.PNG => keyboard-source-25.png} | Bin cdn/dev/img/{kmw-25.PNG => kmw-25.png} | Bin .../{languageswitcher.PNG => languageswitcher.png} | Bin cdn/dev/img/{osk_tibetan.PNG => osk_tibetan.png} | Bin .../img/{package-kmx-25.PNG => package-kmx-25.png} | Bin .../img/{usage-dynamic.PNG => usage-dynamic.png} | Bin 23 files changed, 1 insertion(+), 1 deletion(-) rename cdn/dev/img/app/{keyman-settings.PNG => keyman-settings.png} (100%) rename cdn/dev/img/app/{keyman-settings2.PNG => keyman-settings2.png} (100%) rename cdn/dev/img/app/{keyman-settings3.PNG => keyman-settings3.png} (100%) rename cdn/dev/img/app/{keyman-settings4.PNG => keyman-settings4.png} (100%) rename cdn/dev/img/app/{keyman-settings5.PNG => keyman-settings5.png} (100%) rename cdn/dev/img/app/{keyman-settings6.PNG => keyman-settings6.png} (100%) rename cdn/dev/img/app/{upgrade1.PNG => upgrade1.png} (100%) rename cdn/dev/img/app/{upgrade2.PNG => upgrade2.png} (100%) rename cdn/dev/img/app/{upgrade3.PNG => upgrade3.png} (100%) rename cdn/dev/img/{dev10splashscreen-25.PNG => dev10splashscreen-25.png} (100%) rename cdn/dev/img/{dev10splashscreen.PNG => dev10splashscreen.png} (100%) rename cdn/dev/img/{devcharmap-25.PNG => devcharmap-25.png} (100%) rename cdn/dev/img/{distribution-25.PNG => distribution-25.png} (100%) rename cdn/dev/img/{fonthelper-pro.PNG => fonthelper-pro.png} (100%) rename cdn/dev/img/{keyboard-debugger-25.PNG => keyboard-debugger-25.png} (100%) rename cdn/dev/img/{keyboard-kmw-25.PNG => keyboard-kmw-25.png} (100%) rename cdn/dev/img/{keyboard-source-25.PNG => keyboard-source-25.png} (100%) rename cdn/dev/img/{kmw-25.PNG => kmw-25.png} (100%) rename cdn/dev/img/{languageswitcher.PNG => languageswitcher.png} (100%) rename cdn/dev/img/{osk_tibetan.PNG => osk_tibetan.png} (100%) rename cdn/dev/img/{package-kmx-25.PNG => package-kmx-25.png} (100%) rename cdn/dev/img/{usage-dynamic.PNG => usage-dynamic.png} (100%) diff --git a/.htaccess b/.htaccess index 7c0dc388..438ab16b 100644 --- a/.htaccess +++ b/.htaccess @@ -31,7 +31,7 @@ RedirectMatch "(?i)/donate(\/.*)?" "https://donate.keyman.com" RedirectMatch "(?i)/privacy(\/.*)?" "https://software.sil.org/language-software-privacy-policy/" # desktop to windows -RedirectMatch "(?i)desktop(\/.*)?" "/windows$1" +RedirectMatch "(?i)/desktop(\/.*)?" "/windows$1" # diff --git a/cdn/dev/img/app/keyman-settings.PNG b/cdn/dev/img/app/keyman-settings.png similarity index 100% rename from cdn/dev/img/app/keyman-settings.PNG rename to cdn/dev/img/app/keyman-settings.png diff --git a/cdn/dev/img/app/keyman-settings2.PNG b/cdn/dev/img/app/keyman-settings2.png similarity index 100% rename from cdn/dev/img/app/keyman-settings2.PNG rename to cdn/dev/img/app/keyman-settings2.png diff --git a/cdn/dev/img/app/keyman-settings3.PNG b/cdn/dev/img/app/keyman-settings3.png similarity index 100% rename from cdn/dev/img/app/keyman-settings3.PNG rename to cdn/dev/img/app/keyman-settings3.png diff --git a/cdn/dev/img/app/keyman-settings4.PNG b/cdn/dev/img/app/keyman-settings4.png similarity index 100% rename from cdn/dev/img/app/keyman-settings4.PNG rename to cdn/dev/img/app/keyman-settings4.png diff --git a/cdn/dev/img/app/keyman-settings5.PNG b/cdn/dev/img/app/keyman-settings5.png similarity index 100% rename from cdn/dev/img/app/keyman-settings5.PNG rename to cdn/dev/img/app/keyman-settings5.png diff --git a/cdn/dev/img/app/keyman-settings6.PNG b/cdn/dev/img/app/keyman-settings6.png similarity index 100% rename from cdn/dev/img/app/keyman-settings6.PNG rename to cdn/dev/img/app/keyman-settings6.png diff --git a/cdn/dev/img/app/upgrade1.PNG b/cdn/dev/img/app/upgrade1.png similarity index 100% rename from cdn/dev/img/app/upgrade1.PNG rename to cdn/dev/img/app/upgrade1.png diff --git a/cdn/dev/img/app/upgrade2.PNG b/cdn/dev/img/app/upgrade2.png similarity index 100% rename from cdn/dev/img/app/upgrade2.PNG rename to cdn/dev/img/app/upgrade2.png diff --git a/cdn/dev/img/app/upgrade3.PNG b/cdn/dev/img/app/upgrade3.png similarity index 100% rename from cdn/dev/img/app/upgrade3.PNG rename to cdn/dev/img/app/upgrade3.png diff --git a/cdn/dev/img/dev10splashscreen-25.PNG b/cdn/dev/img/dev10splashscreen-25.png similarity index 100% rename from cdn/dev/img/dev10splashscreen-25.PNG rename to cdn/dev/img/dev10splashscreen-25.png diff --git a/cdn/dev/img/dev10splashscreen.PNG b/cdn/dev/img/dev10splashscreen.png similarity index 100% rename from cdn/dev/img/dev10splashscreen.PNG rename to cdn/dev/img/dev10splashscreen.png diff --git a/cdn/dev/img/devcharmap-25.PNG b/cdn/dev/img/devcharmap-25.png similarity index 100% rename from cdn/dev/img/devcharmap-25.PNG rename to cdn/dev/img/devcharmap-25.png diff --git a/cdn/dev/img/distribution-25.PNG b/cdn/dev/img/distribution-25.png similarity index 100% rename from cdn/dev/img/distribution-25.PNG rename to cdn/dev/img/distribution-25.png diff --git a/cdn/dev/img/fonthelper-pro.PNG b/cdn/dev/img/fonthelper-pro.png similarity index 100% rename from cdn/dev/img/fonthelper-pro.PNG rename to cdn/dev/img/fonthelper-pro.png diff --git a/cdn/dev/img/keyboard-debugger-25.PNG b/cdn/dev/img/keyboard-debugger-25.png similarity index 100% rename from cdn/dev/img/keyboard-debugger-25.PNG rename to cdn/dev/img/keyboard-debugger-25.png diff --git a/cdn/dev/img/keyboard-kmw-25.PNG b/cdn/dev/img/keyboard-kmw-25.png similarity index 100% rename from cdn/dev/img/keyboard-kmw-25.PNG rename to cdn/dev/img/keyboard-kmw-25.png diff --git a/cdn/dev/img/keyboard-source-25.PNG b/cdn/dev/img/keyboard-source-25.png similarity index 100% rename from cdn/dev/img/keyboard-source-25.PNG rename to cdn/dev/img/keyboard-source-25.png diff --git a/cdn/dev/img/kmw-25.PNG b/cdn/dev/img/kmw-25.png similarity index 100% rename from cdn/dev/img/kmw-25.PNG rename to cdn/dev/img/kmw-25.png diff --git a/cdn/dev/img/languageswitcher.PNG b/cdn/dev/img/languageswitcher.png similarity index 100% rename from cdn/dev/img/languageswitcher.PNG rename to cdn/dev/img/languageswitcher.png diff --git a/cdn/dev/img/osk_tibetan.PNG b/cdn/dev/img/osk_tibetan.png similarity index 100% rename from cdn/dev/img/osk_tibetan.PNG rename to cdn/dev/img/osk_tibetan.png diff --git a/cdn/dev/img/package-kmx-25.PNG b/cdn/dev/img/package-kmx-25.png similarity index 100% rename from cdn/dev/img/package-kmx-25.PNG rename to cdn/dev/img/package-kmx-25.png diff --git a/cdn/dev/img/usage-dynamic.PNG b/cdn/dev/img/usage-dynamic.png similarity index 100% rename from cdn/dev/img/usage-dynamic.PNG rename to cdn/dev/img/usage-dynamic.png From 4d479663880c12ec9e09d6ffd055a0122e279640 Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Mon, 5 Sep 2022 10:47:40 +0700 Subject: [PATCH 06/73] chore: Move events page to index.php --- events/iuc38/{default.htm => index.php} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename events/iuc38/{default.htm => index.php} (100%) diff --git a/events/iuc38/default.htm b/events/iuc38/index.php similarity index 100% rename from events/iuc38/default.htm rename to events/iuc38/index.php From 824b5fd8d35c5716b08d91f6758c934539dc1196 Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Mon, 5 Sep 2022 10:52:49 +0700 Subject: [PATCH 07/73] chore: Convert events page to php --- events/iuc38/index.php | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/events/iuc38/index.php b/events/iuc38/index.php index 132e329b..d00d9217 100644 --- a/events/iuc38/index.php +++ b/events/iuc38/index.php @@ -1,5 +1,13 @@ - - + 'Unicode Conference IUC38 - Keyboard Futures presentation and demos', + 'showMenu' => false + ]); +?> +

Unicode Conference IUC38 - Keyboard Futures presentation and demos

Keyboard Futures Presentation (PDF)

@@ -13,5 +21,3 @@ Thai Satellite (cut down)

9 November 2014

- - \ No newline at end of file From 064e9b7e83826d5c1d87f685b048f8024f532341 Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Wed, 11 Jan 2023 10:56:53 +0700 Subject: [PATCH 08/73] fix: Remove include_path --- .htaccess | 2 -- 1 file changed, 2 deletions(-) diff --git a/.htaccess b/.htaccess index 438ab16b..4bd3447f 100644 --- a/.htaccess +++ b/.htaccess @@ -1,8 +1,6 @@ # This file is used when running with Apache. Adapted from web.config. # NOTE: this is not very well tested... -php_value include_path "/var/www/html/_includes:." - RewriteEngine on # Redirect http://keyman.com to https://keyman.com, From 8f99a5fe0ebf59a1398fd352615575ff99277043 Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Wed, 11 Jan 2023 14:11:28 +0700 Subject: [PATCH 09/73] fix autoload path and redirects --- .htaccess | 32 ++++++++++++++------------------ _includes/autoload.php | 16 ++++++++++++++-- 2 files changed, 28 insertions(+), 20 deletions(-) diff --git a/.htaccess b/.htaccess index 4bd3447f..b4cf7bd3 100644 --- a/.htaccess +++ b/.htaccess @@ -157,20 +157,19 @@ RedirectMatch "/(amharic|burmese|cameroon|ethiopic|eurolatin|greek|ipa|sinhala|t # # Remove index or index.php and redirect (and stop processing) -RewriteCond "$1/index" -f [OR] -RewriteCond "$1/index.php" -f -RewriteRule "^((.+)/)?index(\.php)?$" "/$1" [R,L] +RewriteCond "$1" -d +RewriteRule "^((.+)/)?index(\.php)?$" "$1" [R,L] # Remove .php extension and redirect RewriteCond "$1.php" -f +RewriteCond "$1" !-d RewriteRule "^(.+)\.php$" "$1" [R,L] - # Redirect folder without / to include / -RewriteCond "$1" -d -RewriteCond "$1.php" !-f -RewriteCond "$1.md" !-f -RewriteRule "^(.+[^/])$" "$1/" [R,L] +RewriteCond "{DOCUMENT_ROOT}/$1" -d +RewriteCond "{DOCUMENT_ROOT}/$1.php" !-f +RewriteCond "{DOCUMENT_ROOT}/$1.md" !-f +RewriteRule "^(.+[^/])$" "$1/" [R,END] # # PHP rewriting @@ -180,21 +179,18 @@ RewriteRule "^(.+[^/])$" "$1/" [R,L] # Rewrite file to file.md RewriteCond "%{DOCUMENT_ROOT}/$1.md" -f -RewriteRule "^(.+)$" "/_includes/includes/md/mdhost.php?file=$1.md" - -RewriteCond "%{DOCUMENT_ROOT}/$1.md" -f -RewriteRule "^(.+)\.md$" "/_includes/includes/md/mdhost.php?file=$1.md" +RewriteRule "^(.+)$" "/_includes/includes/md/mdhost.php?file=$1.md" [END] # Rewrite file to file.php RewriteCond "%{DOCUMENT_ROOT}/$1.php" -f RewriteCond "%{DOCUMENT_ROOT}/$1.md" !-f +RewriteRule ="^(.+)$" "$1.php" [END] # Rewrite folder/ to folder/index.md RewriteCond "%{DOCUMENT_ROOT}/$1/index.md" -f -#RewriteCond "%{DOCUMENT_ROOT}/$1/index.php" !-f # not needed? -RewriteRule "^(.+)/$" "/_includes/includes/md/mdhost.php?file=$1/index.md" +RewriteRule "^(.+)/$" "/_includes/includes/md/mdhost.php?file=$1/index.md" [END] -# Rewrite folder/ to folder/index.php - Infinite redirection? -#RewriteCond "%{DOCUMENT_ROOT}/$1/index.php" -f -#RewriteCond "%{DOCUMENT_ROOT}/$1/index.md" !-f -#RewriteRule "^(.+)/$" "$1/index.php" +# Rewrite folder/ to folder/index.php +RewriteCond "%{DOCUMENT_ROOT}/$1/index.php" -f +RewriteCond "%{DOCUMENT_ROOT}/$1/index.md" !-f +RewriteRule "^(.+)/$" "$1/index.php" [END] diff --git a/_includes/autoload.php b/_includes/autoload.php index c6e7d65d..29c7493c 100644 --- a/_includes/autoload.php +++ b/_includes/autoload.php @@ -3,12 +3,24 @@ spl_autoload_register(function ($class_name) { if(preg_match('/^Keyman\\\\Site\\\\com\\\\keyman\\\\(.+)/', $class_name, $matches)) { - include(__DIR__ . "/2020/{$matches[1]}.php"); + // Fix namespace pathing for Linux + $filename = str_replace(array('\\', '/'), DIRECTORY_SEPARATOR, $matches[1]); + $success = include(__DIR__ . "/2020/{$filename}.php"); + if($success === FALSE) { + debug_print_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS); + die("Unable to find class $class_name"); + } } }); spl_autoload_register(function ($class_name) { if(preg_match('/^Keyman\\\\Site\\\\Common\\\\(.+)/', $class_name, $matches)) { - include(__DIR__ . "/../_common/{$matches[1]}.php"); + // Fix namespace pathing for Linux + $filename = str_replace(array('\\', '/'), DIRECTORY_SEPARATOR, $matches[1]); + $success = include(__DIR__ . "/../_common/{$filename}.php"); + if($success === FALSE) { + debug_print_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS); + die("Unable to find class $classname"); + } } }); From ff428374e3eec4013b1fde9d5631b0ae750386b2 Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Thu, 12 Jan 2023 11:35:49 +0700 Subject: [PATCH 10/73] fix: ios redirect for ios-dark.png --- .htaccess | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.htaccess b/.htaccess index b4cf7bd3..d90056d8 100644 --- a/.htaccess +++ b/.htaccess @@ -109,7 +109,7 @@ RewriteRule "^keyboards/countries/(.*)" "/keyboards/index.php?q=c:id:$1" [L] RedirectMatch "^/1([0-5])(\.0)\/?" "/1$1/" # ios -RedirectMatch "/(?!iphone-and-ipad)(ios|iphone|ipad)(\/.*)?" "/iphone-and-ipad$2" +RedirectMatch "^/(?!iphone-and-ipad)(ios|iphone|ipad)(\/.*)?" "/iphone-and-ipad$2" # Connect With Art landing page RedirectMatch "/connectwithart(\/|$)" "https://sites.google.com/sil.org/connectwithart/home" From 849c98a3ae87e6ca9a980a6ff501dd26505bdd03 Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Thu, 12 Jan 2023 14:36:27 +0700 Subject: [PATCH 11/73] fix: other root redirects --- .htaccess | 10 +++++----- archive/.htaccess | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.htaccess b/.htaccess index d90056d8..6d4b1f9e 100644 --- a/.htaccess +++ b/.htaccess @@ -17,19 +17,19 @@ RewriteEngine on # TODO: Add 301 permanent redirects, append query strings # macosx and macos to mac" (ignore case) -RedirectMatch "(?i)/(macosx|macos)\b(.*)$" "/mac$2" +RedirectMatch "(?i)^/(macosx|macos)\b(.*)$" "/mac$2" # Redirect deprecated Google Plus link -RedirectMatch "(?i)/plus.*" "/" +RedirectMatch "(?i)^/plus.*" "/" # /donate -> donate.keyman.com -RedirectMatch "(?i)/donate(\/.*)?" "https://donate.keyman.com" +RedirectMatch "(?i)^/donate(\/.*)?" "https://donate.keyman.com" # /privacy -> SIL Privacy policy -RedirectMatch "(?i)/privacy(\/.*)?" "https://software.sil.org/language-software-privacy-policy/" +RedirectMatch "(?i)^/privacy(\/.*)?" "https://software.sil.org/language-software-privacy-policy/" # desktop to windows -RedirectMatch "(?i)/desktop(\/.*)?" "/windows$1" +RedirectMatch "(?i)^/desktop(\/.*)?" "/windows$1" # diff --git a/archive/.htaccess b/archive/.htaccess index f616ce95..b465abd5 100644 --- a/archive/.htaccess +++ b/archive/.htaccess @@ -1,4 +1,4 @@ # Redirect /archive/downloads.php" # TODO: Permanent -RedirectMatch "/archive/downloads.php" "/downloads/archive/" \ No newline at end of file +RedirectMatch "/archive/downloads.php" "/downloads/archive/" From b7c8ed3fba764d7abbc1cb6daf39b970602dae7c Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Wed, 11 Jan 2023 13:39:19 +0700 Subject: [PATCH 12/73] fix: Add Docker --- .gitignore | 2 +- Dockerfile | 28 + build.sh | 120 ++++ resources/builder.inc.sh | 1252 ++++++++++++++++++++++++++++++++++++ resources/keyman-site.conf | 13 + 5 files changed, 1414 insertions(+), 1 deletion(-) create mode 100644 Dockerfile create mode 100755 build.sh create mode 100755 resources/builder.inc.sh create mode 100644 resources/keyman-site.conf diff --git a/.gitignore b/.gitignore index fd881e6d..887faf22 100644 --- a/.gitignore +++ b/.gitignore @@ -2,5 +2,5 @@ /.vscode cdn/deploy/ -/vendor/ +vendor* /node_modules/ diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..0f4d066d --- /dev/null +++ b/Dockerfile @@ -0,0 +1,28 @@ +# syntax=docker/dockerfile:1 +FROM php:7.4-apache AS composer-builder + +# Install Zip to use composer +RUN apt-get update && apt-get install -y \ + zlib1g-dev \ + libzip-dev \ + unzip +RUN docker-php-ext-install zip + +# Install and update composer +COPY --from=composer /usr/bin/composer /usr/bin/composer +RUN composer self-update + +USER www-data +WORKDIR /composer +COPY composer.* /composer/ +RUN composer install + +# Site +FROM php:7.4-apache +COPY resources/keyman-site.conf /etc/apache2/conf-available/ +RUN chown -R www-data:www-data /var/www/html/ + +COPY --from=composer-builder /composer/vendor /var/www/vendor +RUN a2enmod rewrite; a2enconf keyman-site + +# build.sh configure later needed to create link to vendor/ diff --git a/build.sh b/build.sh new file mode 100755 index 00000000..1415d5d1 --- /dev/null +++ b/build.sh @@ -0,0 +1,120 @@ +#!/usr/bin/env bash +# +# Setup keyman.com site to run via Docker. +# +set -eu + +## START STANDARD BUILD SCRIPT INCLUDE +# adjust relative paths as necessary +THIS_SCRIPT="$(greadlink -f "${BASH_SOURCE[0]}" 2>/dev/null || readlink -f "${BASH_SOURCE[0]}")" +. "$(dirname "$THIS_SCRIPT")/resources/builder.inc.sh" +## END STANDARD BUILD SCRIPT INCLUDE + +################################ Main script ################################ + +function _get_docker_image_id() { + echo "$(docker images -q keyman-website)" +} + +function _get_docker_container_id() { + echo "$(docker ps -a -q --filter ancestor=keyman-website)" +} + +function _stop_docker_container() { + KEYMAN_CONTAINER=$(_get_docker_container_id) + if [ ! -z "$KEYMAN_CONTAINER" ]; then + docker container stop $KEYMAN_CONTAINER + else + echo "No Docker container to stop" + fi +} + +builder_describe \ + "Setup keyman.com site to run via Docker." \ + configure \ + clean \ + build \ + start \ + stop \ + test \ + +builder_parse "$@" + +# This script runs from its own folder +cd "$REPO_ROOT" + +if builder_start_action configure; then + # Skip if link already exists + if [ -L vendor ]; then + echo "Skipping because vendor already exists" + else + # Create link to vendor/ folder + KEYMAN_CONTAINER=$(_get_docker_container_id) + if [ ! -z "$KEYMAN_CONTAINER" ]; then + docker exec -i $KEYMAN_CONTAINER sh -c "ln -s /var/www/vendor vendor && chown -R www-data:www-data vendor" + else + echo "No Docker container to configure" + fi + fi + builder_finish_action success configure +fi + +if builder_start_action clean; then + # Stop and cleanup Docker containers and images used for the site + _stop_docker_container + + KEYMAN_CONTAINER=$(_get_docker_container_id) + if [ ! -z "$KEYMAN_CONTAINER" ]; then + docker container rm $KEYMAN_CONTAINER + else + echo "No Docker container to clean" + fi + + KEYMAN_IMAGE=$(_get_docker_image_id) + if [ ! -z "$KEYMAN_IMAGE" ]; then + docker rmi keyman-website + else + echo "No Docker image to clean" + fi + + builder_finish_action success clean +fi + +if builder_start_action stop; then + # Stop the Docker container + _stop_docker_container + builder_finish_action success stop +fi + +if builder_start_action build; then + # Download docker image. --mount option requires BuildKit + DOCKER_BUILDKIT=1 docker build -t keyman-website . + + builder_finish_action success build +fi + +if builder_start_action start; then + # Start the Docker container + if [ ! -z $(_get_docker_image_id) ]; then + # TODO: What port to use? + if [[ $OSTYPE =~ msys|cygwin ]]; then + # Windows needs leading slashes for path + docker run -d -p 8053:80 -v //$(pwd):/var/www/html/ -e S_KEYMAN_COM=localhost:8054 keyman-website + else + docker run -d -p 8053:80 -v $(pwd):/var/www/html/ -e S_KEYMAN_COM=localhost:8054 keyman-website + fi + else + echo "${COLOR_RED}ERROR: Docker container doesn't exist. Run ./build.sh build first${COLOR_RESET}" + builder_finish_action fail start + fi + + builder_finish_action success start +fi + +if builder_start_action test; then + # TODO: lint tests + + composer check-docker-links + + builder_finish_action success test +fi diff --git a/resources/builder.inc.sh b/resources/builder.inc.sh new file mode 100755 index 00000000..4234df67 --- /dev/null +++ b/resources/builder.inc.sh @@ -0,0 +1,1252 @@ +#!/usr/bin/env bash +# +# This script contains utilities for builder_script calls +# +# * builder_ functions and variables are defined here. +# * REPO_ROOT defines the top level of this repository +# * THIS_SCRIPT_PATH defines the full path of the running script +# * THIS_SCRIPT_NAME defines the basename of the running script +# * THIS_SCRIPT_IDENTIFIER defines the repo-relative path of the running script +# * _builder_ functions and variables are internal use only for builder.inc.sh, and +# subject to change at any time. Do not use them in other scripts. +# * Note: the running script is the top-level script that includes either +# builder.inc.sh directly, or, just in the Keyman repo, via build-utils.sh. +# + +# _builder_init is called internally at the bottom of this file after we have +# all function declarations in place. +function _builder_init() { + _builder_findRepoRoot + _builder_setBuildScriptIdentifiers + + if [[ -n "$TERM" ]] && [[ "$TERM" != "dumb" ]] && [[ "$TERM" != "unknown" ]]; then + builder_use_color true + else + builder_use_color false + fi +} + +function _builder_findRepoRoot() { + # See https://stackoverflow.com/questions/59895/how-to-get-the-source-directory-of-a-bash-script-from-within-the-script-itself + # None of the answers are 100% correct for cross-platform + # On macOS, requires coreutils (`brew install coreutils`) + local SCRIPT=$(greadlink -f "${BASH_SOURCE[0]}" 2>/dev/null || readlink -f "${BASH_SOURCE[0]}") + REPO_ROOT=$(dirname $(dirname "$SCRIPT")) + readonly REPO_ROOT +} + +# Used to build script-related build variables useful for referencing the calling script +# and for prefixing `builder_finish_action` outputs in order to more clearly identify the calling +# script. +# +# Assumes that `THIS_SCRIPT` has been set, typically like this: +# +# ```bash +# ## START STANDARD BUILD SCRIPT INCLUDE +# # adjust relative paths as necessary +# THIS_SCRIPT="$(greadlink -f "${BASH_SOURCE[0]}" 2>/dev/null || readlink -f "${BASH_SOURCE[0]}")" +# . "$(dirname "$THIS_SCRIPT")/resources/builder.inc.sh" +# ## END STANDARD BUILD SCRIPT INCLUDE +# ``` +# +function _builder_setBuildScriptIdentifiers() { + if [ ! -z ${THIS_SCRIPT+x} ]; then + THIS_SCRIPT_PATH="$(dirname "$THIS_SCRIPT")" + readonly THIS_SCRIPT_PATH + THIS_SCRIPT_NAME="$(basename "$THIS_SCRIPT")" + readonly THIS_SCRIPT_NAME + # Leaves only the part of the path based upon REPO_ROOT. + THIS_SCRIPT_IDENTIFIER=${THIS_SCRIPT_PATH#"$REPO_ROOT/"} + readonly THIS_SCRIPT_IDENTIFIER + else + echo "Warning: THIS_SCRIPT not defined; builder.inc.sh has not been sourced with standard script include." + fi +} + +################################################################################ +# Standard build script functions for managing command line, actions and targets +################################################################################ + +# The following allows coloring of warning and error lines, but only works if there's a +# terminal attached, so not on the build machine. + +# Overrides default colorization of logging; can be used in command-line with +# --color or --no-color, or overridden as necessary on a per-script basis. +# +# Parameters +# 1: use_color true or false +builder_use_color() { + if $1; then + COLOR_RED=$(tput setaf 1) + COLOR_GREEN=$(tput setaf 2) + COLOR_YELLOW=$(tput setaf 3) + COLOR_BLUE=$(tput setaf 4) + COLOR_PURPLE=$(tput setaf 5) + COLOR_TEAL=$(tput setaf 6) + COLOR_WHITE=$(tput setaf 7) + COLOR_GREY=$(tput setaf 8) + COLOR_RESET=$(tput sgr0) + # e.g. VSCode https://code.visualstudio.com/updates/v1_69#_setmark-sequence-support + HEADING_SETMARK='\x1b]1337;SetMark\x07' + + # Used by `builder_display_usage` when marking special terms (actions, targets, options) + # in the plain-text description area. + BUILDER_TERM_START="$COLOR_BLUE" + BUILDER_TERM_END="$COLOR_RESET" + else + COLOR_RED= + COLOR_GREEN= + COLOR_YELLOW= + COLOR_BLUE= + COLOR_PURPLE= + COLOR_TEAL= + COLOR_WHITE= + COLOR_GREY= + COLOR_RESET= + HEADING_SETMARK= + BUILDER_TERM_START="<" + BUILDER_TERM_END=">" + fi +} + +function builder_die() { + echo + echo "${COLOR_RED}$*" + echo + exit 1 +} + +#################################################################################### +# +# builder_ functions for standard build script parameter and process management +# +#################################################################################### + +# +# builder_ names are reserved. +# _builder_ names are internal use and subject to change +# +_builder_debug=false + +# +# builder_extra_params: string containing all parameters after '--' +# +builder_extra_params=() + +# returns 0 if first parameter is in the array passed as second parameter +# +# Usage: +# if _builder_item_in_array "item" "${array[@]}"; then ...; fi +# Parameters: +# 1: item item to search for in array +# 2: array bash array, e.g. array=(one two three) +_builder_item_in_array() { + local e match="$1" + shift + [[ -z "$match" ]] && return 1 + for e; do [[ "$e" == $match ]] && return 0; done + return 1 +} + +# +# Returns `0` if first parameter is in the array passed as second parameter, +# where the array may contain globs. +# +# ### Parameters +# +# * 1: `item` item to search for in array +# * 2: `array` bash array, e.g. `array=(one two three)` +# +# ### Example +# +# ```bash +# array=(foo bar it*) +# if _builder_item_in_glob_array "item" "${array[@]}"; then ...; fi +# ``` +# +_builder_item_in_glob_array() { + local e match="$1" + shift + [[ -z "$match" ]] && return 1 + for e; do [[ "$match" == $e ]] && return 0; done + return 1 +} + + +_builder_item_is_target() { + local item="$1" + [[ $item =~ ^: ]] && return 1 + return 0 +} + +function _builder_warn_if_incomplete() { + if [ -n "${_builder_current_action}" ]; then + local scope="[$THIS_SCRIPT_IDENTIFIER] " + echo "${COLOR_YELLOW}## ${scope}Warning - $_builder_current_action never reported success or failure${COLOR_RESET}" + # exit 1 # If we wanted this scenario to result in a forced build-script fail. + fi + + # Since we've already warned about this once, we'll clear the variable to prevent repetitions. + _builder_current_action= +} + +# Used by a `trap` statement later to facilitate auto-reporting failures on error detection +# without obscuring failure exit/error codes. +_builder_failure_trap() { + local trappedExitCode=$? + local action target + + _builder_cleanup_deps + + # Since 'exit' is also trapped, we can also handle end-of-script incomplete actions. + if [[ $trappedExitCode == 0 ]]; then + # While there weren't errors, were there any actions that never reported success or failure? + _builder_warn_if_incomplete + return + fi + + # If we've reached this point, we're here because an error occurred. + + # Iterate across currently-active actions and report their failures. + if [ -n "${_builder_current_action}" ]; then + action="${_builder_current_action}" + if [[ $action =~ : ]]; then + IFS=: read -r action target <<< $action + target=:$target + else + target=:project + fi + + builder_finish_action failure $action$target + + # Make 100% sure that the exit code chains fully. + # Without this, nested scripts have failed to chain errors from npm calls past the script + # that directly executed the failed npm command. + exit $trappedExitCode + fi +} + +# +# Removes temporary `_builder_deps_built` file when top-level build script +# finishes. +# +_builder_cleanup_deps() { + if ! builder_is_dep_build && [[ ! -z ${_builder_deps_built+x} ]]; then + if $_builder_debug; then + echo "[DEBUG] Dependencies that were built:" + cat "$_builder_deps_built" + fi + rm -f "$_builder_deps_built" + _builder_deps_built= + fi +} + +# +# Builds the standardized `action:target` string for the specified action-target +# pairing and also returns 0 if the user has asked to perform it on the command +# line. Otherwise, returns 0 and sets an empty string in place of the matched +# pair. +# +# The string will be set as `_builder_matched_action`, which is for +# builder.inc.sh internal use, used by `builder_start_action`. +# +# ### Usage +# +# ```bash +# if build_has_action action[:target]; then ...; fi +# ```` +# +# Parameters: +# 1: action[:target] name of action:target +# Example: +# +# ```bash +# if builder_has_action build:app; then ... +# ``` +# +builder_has_action() { + local action="$1" target + + if [[ $action =~ : ]]; then + IFS=: read -r action target <<< $action + target=:$target + else + target=':*' + fi + + if _builder_item_in_array "$action$target" "${_builder_chosen_action_targets[@]}"; then + # To avoid WET re-processing of the $action$target string set + _builder_matched_action="$action$target" + if [[ $target == ':*' ]]; then + _builder_matched_action_name="$action" + else + _builder_matched_action_name="$action$target" + fi + return 0 + else + _builder_matched_action= + return 1 + fi +} + +# +# Returns `0` if the user has asked to perform action on target on the command +# line, and then starts the action. Should be paired with +# `builder_finish_action`. +# +# ### Usage +# +# ```bash +# if builder_start_action action[:target]; then ...; fi +# ``` +# +# ### Parameters +# +# * 1: `action[:target]` name of action, and optionally also target, if +# target excluded starts for all defined targets +# +# ### Example +# +# ```bash +# if builder_start_action build:app; then ... +# ``` +# +builder_start_action() { + local scope="[$THIS_SCRIPT_IDENTIFIER] " + + if builder_has_action $1; then + # In a dependency quick build (the default), determine whether we actually + # need to run this step. Uses data passed to builder_describe_outputs to + # verify whether a target output is present. + if builder_is_dep_build && + ! builder_is_full_dep_build && + [[ ! -z ${_builder_dep_path[$_builder_matched_action]+x} ]] && + [[ -e "$KEYMAN_ROOT/${_builder_dep_path[$_builder_matched_action]}" ]]; then + echo "$scope skipping $_builder_matched_action_name, up-to-date" + return 1 + fi + + echo "${COLOR_BLUE}## $scope$_builder_matched_action_name starting...${COLOR_RESET}" + if [ -n "${_builder_current_action}" ]; then + _builder_warn_if_incomplete + fi + _builder_current_action="$_builder_matched_action" + + # Build dependencies as required + _builder_do_build_deps "$_builder_matched_action" + return 0 + else + return 1 + fi +} + +# +# Returns 0 if the user has --option on the command line +# +# Usage: +# if build_has_option option; then ...; fi +# Parameters: +# 1: option name of option, i.e. --option +# Example: +# if build_has_option --debug; then +# +builder_has_option() { + local option="$1" + + if _builder_item_in_array "$option" "${_builder_chosen_options[@]}"; then + return 0 + fi + return 1 +} + +_builder_trim() { + local var="$*" + # remove leading whitespace characters + var="${var#"${var%%[![:space:]]*}"}" + # remove trailing whitespace characters + var="${var%"${var##*[![:space:]]}"}" + printf '%s' "$var" +} + +# +# Expands an in-repo-relative path to a repo-relative path. A path starting with +# `/` is expected to be relative to repo root, not filesystem root. Otherwise, +# it's relative to current script path, not current working directory. The +# returned path will not have a prefix `/`, and will be relative to +# `$KEYMAN_ROOT`. Assumes realpath is installed (brew coreutils on macOS). +# +_builder_expand_relative_path() { + local path="$1" + if [[ "$path" =~ ^/ ]]; then + echo "${path:1}" + else + realpath --canonicalize-missing --relative-to="$KEYMAN_ROOT" "$THIS_SCRIPT_PATH/$path" + fi +} + +# +# Expands an `[action][:target]` string, replacing missing values with `*`, +# for example: +# +# * `build` --> `build:*` +# * `build:app` --> `build:app` +# * `:app` --> `*:app` +# +# Supports multiple action:targets in the string +# +_builder_expand_action_target() { + local input="$1" target= action= + if [[ "$input" =~ : ]]; then + action=$(echo "$input" | cut -d: -f 1 -) + target=$(echo "$input" | cut -d: -f 2 -) + else + action=$input + fi + + if [[ -z "$action" ]]; then + action='*' + fi + if [[ -z "$target" ]]; then + target='*' + fi + + echo "$action:$target" +} + +_builder_expand_action_targets() { + local input=($1) e output=() + for e in "${input[@]}"; do + e=`_builder_expand_action_target "$e"` + output+=($e) + done + if [[ ${#output[@]} == 0 ]]; then + echo "*:*" + else + echo "${output[@]}" + fi +} + +# +# Describes a build script, defines available parameters and their meanings. Use +# together with `builder_parse` to process input parameters. +# +# ### Usage +# +# ```bash +# builder_describe description param_desc... +# ``` +# +# ### Parameters +# +# * `description` A short description of what the script does. +# * `param_desc` Space separated name and description of parameter, e.g. +# `"build Builds the target"` +# This parameter may be repeated to describe all parameters. +# +# There are four types of parameters that may be specified: +# +# * **Option:** `"--option[,-o][=var] [One line description]"` +# +# All options must have a longhand form with two prefix hyphens, +# e.g. `--option`. The `,-o` shorthand form is optional. When testing if +# the option is set with `builder_has_option`, always use the longhand +# form. +# +# if `=var` is specified, then the next parameter will be a variable stored in +# `$var` for that option. e.g. `--option=opt` means `$opt` will have the value +# `"foo"` when the script is called for `--option foo`. +# +# * **Action**: `"action [One line description]"` +# +# Actions must be a single word, lower case. To specify an action as the +# default, append a `+` to the action name, e.g. `"test+ Test the project"`. +# If there is no default specified, then it will be `build`. +# +# * **Target:** `":target [One line description]"` +# +# A target always starts with colon, e.g. `:project`. +# +# * **Dependency:** "@/path/to/dependency [action][:target] ..." +# +# A dependency always starts with `@`. The path to the dependency will be +# relative to the build script folder, or to the root of the repository, if +# the path starts with `/`, not to the root of the file system. It is an error +# to specify a dependency outside the repo root. +# +# Relative paths will be expanded to full paths, again, relative to the root +# of the repository. +# +# Dependencies may be limited to specific `action:target`. If not specified, +# dependencies will be built for all actions on all targets. Either `action` +# or `:target` may be omitted, and multiple actions and targets may be +# specified, space separated. +# +builder_describe() { + _builder_description="$1" + _builder_actions=() + _builder_targets=() + _builder_options=() + _builder_deps=() # array of all dependencies for this script + _builder_default_action=build + declare -A -g _builder_params + declare -A -g _builder_options_short + declare -A -g _builder_options_var + declare -A -g _builder_dep_path # array of output files for action:target pairs + declare -A -g _builder_dep_related_actions # array of action:targets associated with a given dependency + declare -A -g _builder_internal_dep # array of internal action:targets dependency relationships + shift + # describe each target, action, and option possibility + while [[ $# -gt 0 ]]; do + local key="$1" + local value="$(echo "$key" | cut -d" " -f 1 -)" + local description= + if [[ $key =~ [[:space:]] ]]; then + description="$(_builder_trim "$(echo "$key" | cut -d" " -f 2- -)")" + fi + + if [[ $value =~ ^: ]]; then + # Parameter is a target + _builder_targets+=($value) + elif [[ $value =~ ^@ ]]; then + # Parameter is a dependency + local dependency="${value:1}" + dependency="`_builder_expand_relative_path "$dependency"`" + _builder_deps+=($dependency) + _builder_dep_related_actions[$dependency]="`_builder_expand_action_targets "$description"`" + + # We don't want to add deps to params, so shift+continue + shift + continue + elif [[ $value =~ ^-- ]]; then + # Parameter is an option + # Look for a shorthand version of the option + local option_var= + if [[ $value =~ = ]]; then + option_var="$(echo "$value" | cut -d= -f 2 -)" + value="$(echo "$value" | cut -d= -f 1 -)" + fi + + if [[ $value =~ , ]]; then + local option_long="$(echo "$value" | cut -d, -f 1 -)" + local option_short="$(echo "$value" | cut -d, -f 2 -)" + _builder_options+=($option_long) + _builder_options_short[$option_short]="$option_long" + if [[ ! -z "$option_var" ]]; then + _builder_options_var[$option_long]="$option_var" + fi + value="$option_long, $option_short" + else + _builder_options+=($value) + if [[ ! -z "$option_var" ]]; then + _builder_options_var[$value]="$option_var" + fi + fi + + if [[ ! -z $option_var ]]; then + value="$value $option_var" + fi + else + # Parameter is an action + if [[ $value =~ \+$ ]]; then + # If the action name has a '+' suffix then it is the default action + value=${value//+} + _builder_default_action=$value + fi + _builder_actions+=($value) + fi + + if [[ -z "${description}" ]]; then + description=$(_builder_get_default_description "$value") + fi + _builder_params[${value}]="$description" + + shift + done + + # We'll always add a :project if no target is specified + if (( ! ${#_builder_targets[@]} )); then + _builder_targets+=(:project) + _builder_params[\:project]=$(_builder_get_default_description ":project") + fi +} + +# +# Defines an output file or folder expected to be present after successful +# completion of an action for a target. Used to skip actions for dependency +# builds. If `:target` is not provided, assumes `:project`. +# +# Relative paths are relative to script folder; absolute paths are relative +# to repository root, not filesystem root. +# +# ### Usage +# +# ```bash +# builder_describe_outputs action:target filename [...] +# ``` +# +# ### Parameters +# +# * 1: `action[:target]` action and/or target associated with file +# * 2: `filename` name of file or folder to check +# * 3+: ... repeat previous arguments for additional outputs +# +# ### Example +# +# ```bash +# builder_describe_outputs \ +# configure /node_modules \ +# build build/index.js +# ``` +# +function builder_describe_outputs() { + while [[ $# -gt 0 ]]; do + local key="$1" path="$2" action target + path="`_builder_expand_relative_path "$path"`" + + if [[ $key =~ : ]]; then + action="$(echo "$key" | cut -d: -f 1 -)" + target=":$(echo "$key" | cut -d: -f 2 -)" + else + # Add dependency expected output file for all targets, as well as a + # wildcard target match + action="$key" + for target in "${_builder_targets[@]}"; do + _builder_dep_path[$action$target]="$path" + done + target=':*' + fi + _builder_dep_path[$action$target]="$path" + shift 2 + done + + _builder_define_default_internal_dependencies +} + +_builder_get_default_description() { + local description= + local value="$1" + # default descriptions for common build actions, targets, and options + case "$value" in + clean) description="remove build/ folder and build artifacts" ;; + configure) description="install dependencies, e.g. npm" ;; + build) description="build target(s)" ;; + test) description="run automated tests" ;; + :project) description="this project" ;; + :app) description="main app" ;; + :engine) description="engine module" ;; + :module) description="this module" ;; + :tools) description="build tools for this project" ;; + --debug) description="debug build" ;; + esac + echo "$description" +} + +_builder_parameter_error() { + local program="$1" + local type="$2" + local param="$3" + echo "$COLOR_RED$program: invalid $type: $param$COLOR_RESET" + echo + builder_display_usage + exit 64 + +} + +# Pre-initializes the color setting based on the options specified to a +# a build.sh script, parsing the command line to do so. This is only +# needed if said script wishes to use this script's defined colors while +# respecting the options provided by the script's caller. +# +# Usage: +# builder_check_color "$@" +# Parameters +# 1: $@ all command-line arguments (as with builder_parse) +builder_check_color() { + # Process command-line arguments + while [[ $# -gt 0 ]] ; do + local key="$1" + + case "$key" in + --color) + builder_use_color true + ;; + --no-color) + builder_use_color false + ;; + esac + shift # past the processed argument + done +} + +# +# For every build action:target in _builder_chosen_action_targets, add +# its full internal dependency tree +# +_builder_add_chosen_action_target_dependencies() { + local action_target e i=0 new_actions=() + + # Iterate through every action specified on command line; we use this loop + # style so that any new actions added here will also be iteratively checked + while (( $i < ${#_builder_chosen_action_targets[@]} )); do + action_target=${_builder_chosen_action_targets[$i]} + + # If we have an internal dependency for the chosen action:target pair, add + # it to the list, but only if there is a defined output and that output is + # missing + if [[ ! -z ${_builder_internal_dep[$action_target]+x} ]]; then + local dep_output=${_builder_internal_dep[$action_target]} + if [[ ! -z ${_builder_dep_path[$dep_output]+x} ]] && + [[ ! -e "$KEYMAN_ROOT/${_builder_dep_path[$dep_output]}" ]]; then + if ! _builder_item_in_array "$dep_output" "${_builder_chosen_action_targets[@]}"; then + _builder_chosen_action_targets+=($dep_output) + new_actions+=($dep_output) + fi + fi + fi + i=$((i + 1)) + done + + if [[ ${#new_actions[@]} -gt 0 ]]; then + echo "Automatically running following required actions with missing outputs:" + for e in "${new_actions[@]}"; do + echo "* $e" + done + fi +} + +# +# If we have described outputs, then we will setup our +# default internal dependency chain: +# +# configure <- build <- (test,install,publish) +# +_builder_define_default_internal_dependencies() { + for target in "${_builder_targets[@]}"; do + _builder_define_default_internal_deps_for_target "$target" + done + + _builder_define_default_internal_deps_for_target ':*' +} + +_builder_define_default_internal_deps_for_target() { + local target=$1 + _builder_define_default_internal_dep "$target" configure build + _builder_define_default_internal_dep "$target" build test + _builder_define_default_internal_dep "$target" build install +} + +_builder_define_default_internal_dep() { + local target=$1 dep=$2 action=$3 + if _builder_item_in_array $dep "${_builder_actions[@]}" && + _builder_item_in_array $action "${_builder_actions[@]}"; then + _builder_internal_dep[$action$target]=$dep$target + fi +} + +# Initializes a build.sh script, parses command line. Will abort the script if +# invalid parameters are passed in. Use together with builder_describe which +# sets up the possible command line parameters +# +# Usage: +# builder_parse "$@" +# Parameters +# 1: $@ command-line arguments +builder_parse() { + _builder_build_deps=--deps + builder_verbose= + builder_debug= + builder_extra_params=() + _builder_chosen_action_targets=() + _builder_chosen_options=() + _builder_current_action= + + # Process command-line arguments + while [[ $# -gt 0 ]] ; do + local key="$1" + local action= + local target= + local e has_action has_target has_option longhand_option + + if [[ $key == "--" ]]; then + shift + builder_extra_params=("$@") + break + fi + + if [[ $key =~ : ]]; then + IFS=: read -r action target <<< $key + target=:$target + else + action="$key" + target= + fi + + _builder_item_in_array "$action" "${_builder_actions[@]}" && has_action=1 || has_action=0 + _builder_item_in_array "$target" "${_builder_targets[@]}" && has_target=1 || has_target=0 + + # Expand short -o to --option in options lookup + if [[ ! -z ${_builder_options_short[$key]+x} ]]; then + key=${_builder_options_short[$key]} + fi + _builder_item_in_array "$key" "${_builder_options[@]}" && has_option=1 || has_option=0 + + if (( has_action )) && (( has_target )); then + # apply the selected action and selected target + _builder_chosen_action_targets+=("$key") + elif (( has_action )); then + # apply the selected action to all targets + if [[ ! -z $target ]]; then + # A target was specified but is not valid + _builder_parameter_error "$0" target "$target" + fi + + for e in "${_builder_targets[@]}"; do + _builder_chosen_action_targets+=("$action$e") + done + elif (( has_target )); then + # apply the default action to the selected target + + if [[ ! -z $action ]]; then + # An action was specified but is not valid + _builder_parameter_error "$0" action "$action" + fi + + _builder_chosen_action_targets+=("$_builder_default_action$target") + elif (( has_option )); then + _builder_chosen_options+=("$key") + if [[ ! -z ${_builder_options_var[$key]+x} ]]; then + shift + if [[ $# -eq 0 ]]; then + _builder_parameter_error "$0" parameter "$key" + fi + # Set the variable associated with this option to the next parameter value + # A little bit of hoop jumping here to avoid issues with cygwin paths being + # corrupted too early in the game + local varname=${_builder_options_var[$key]} + declare -g $varname="$1" + fi + + else + case "$key" in + --help|-h) + builder_display_usage + exit 0 + ;; + --color) + builder_use_color true + ;; + --no-color) + builder_use_color false + ;; + --verbose|-v) + _builder_chosen_options+=(--verbose) + builder_verbose=--verbose + ;; + --debug|-d) + _builder_chosen_options+=(--debug) + builder_debug=--debug + ;; + --deps|--no-deps|--force-deps) + _builder_build_deps=$key + ;; + --builder-dep-parent) + # internal use parameter for dependency builds - identifier of parent script + shift + builder_dep_parent="$1" + ;; + --builder-deps-built) + # internal use parameter for dependency builds - path to dependency tracking file + shift + _builder_deps_built="$1" + ;; + --builder-report-dependencies) + # internal reporting function, ignores all other parameters + _builder_report_dependencies + ;; + *) + _builder_parameter_error "$0" parameter "$key" + esac + fi + shift # past the processed argument + done + + if (( ! ${#_builder_chosen_action_targets[@]} )); then + for e in "${_builder_targets[@]}"; do + _builder_chosen_action_targets+=("$_builder_default_action$e") + done + fi + + _builder_add_chosen_action_target_dependencies + + if $_builder_debug; then + echo "[DEBUG] Selected actions and targets:" + for e in "${_builder_chosen_action_targets[@]}"; do + echo "* $e" + done + echo + echo "[DEBUG] Selected options:" + for e in "${_builder_chosen_options[@]}"; do + echo "* $e" + done + fi + + if builder_is_dep_build; then + echo "[$THIS_SCRIPT_IDENTIFIER] dependency build, started by $builder_dep_parent" + if [[ -z ${_builder_deps_built+x} ]]; then + echo "FATAL ERROR: Expected --builder-deps-built parameter" + exit 1 + fi + else + # This is a top-level invocation, not a dependency build, so we want to + # track which dependencies have been built, so they don't get built multiple + # times. + _builder_deps_built=`mktemp` + fi + + # Now that we've successfully parsed options adhering to the _builder spec, we may activate our + # action_failure and action_hanging traps. (We don't want them active on scripts not yet using + # said script.) + # + # Note: if an error occurs within a script's function in a `set -e` script, it becomes an exit + # instead for the function's caller. So, we need both `err` and `exit` here. + # See https://medium.com/@dirk.avery/the-bash-trap-trap-ce6083f36700. + trap _builder_failure_trap err exit +} + +_builder_pad() { + local count=$1 + local text1=$2 + local text2=$3 + local fmt="%-${count}s%s\n" + printf $fmt "$text1" "$text2" +} + +builder_display_usage() { + local e program description + + # Minimum padding is 12 characters, increase this if necessary + # if you add other, longer, global options (like --verbose, --debug) + local width=12 + + for e in "${!_builder_params[@]}"; do + if (( ${#e} > $width )); then + width=${#e} + fi + done + + width=$((width + 6)) + + program="$(basename "$0")" + if [[ ! -z ${_builder_description+x} ]]; then + echo "Summary:" + echo " $_builder_description" + echo + fi + echo "Script Identifier:" + echo " $THIS_SCRIPT_IDENTIFIER" + echo + + echo "Usage:" + echo " $program [options...] [action][:target]..." + echo + echo "Actions: " + + for e in "${_builder_actions[@]}"; do + if [[ -v _builder_params[$e] ]]; then + description="${_builder_params[$e]}" + else + description=$(_builder_get_default_description "$e") + fi + _builder_pad $width " $e" "$description" + done + + echo + echo "Targets: " + + for e in "${_builder_targets[@]}"; do + if [[ -v _builder_params[$e] ]]; then + description="${_builder_params[$e]}" + else + description=$(_builder_get_default_description "$e") + fi + _builder_pad $width " $e" "$description" + done + + echo + echo "Options: " + + for e in "${!_builder_params[@]}"; do + if [[ $e =~ ^-- ]]; then + _builder_pad $width " $e" "${_builder_params[$e]}" + fi + done + + _builder_pad $width " --verbose, -v" "Verbose logging" + _builder_pad $width " --debug, -d" "Debug build" + _builder_pad $width " --color" "Force colorized output" + _builder_pad $width " --no-color" "Never use colorized output" + if builder_has_dependencies; then + _builder_pad $width " --deps" "Build dependencies if required (default)" + _builder_pad $width " --no-deps" "Skip build of dependencies" + _builder_pad $width " --force-deps" "Reconfigure and rebuild all dependencies" + fi + _builder_pad $width " --help, -h" "Show this help" + + echo + echo "Dependencies: " + + if builder_has_dependencies; then + for d in "${_builder_deps[@]}"; do + echo " $d" + done + else + echo " This module has no dependencies" + fi + + # Defined in `builder_use_color`; this assumes that said func has been called. + local c1=$BUILDER_TERM_START + local c0=$BUILDER_TERM_END + echo + echo "* Specify ${c1}action:target${c0} to run a specific ${c1}action${c0} against a specific ${c1}:target${c0}." + echo "* If ${c1}action${c0} is specified without a ${c1}target${c0} suffix, it will be applied to all ${c1}:target${c0}s." + echo "* If ${c1}:target${c0} is specified without an ${c1}action${c0} prefix, ${c1}$_builder_default_action:target${c0} will be inferred." + echo "* If no ${c1}action${c0}, ${c1}:target${c0}, or ${c1}action:target${c0} entries are specified, ${c1}$_builder_default_action${c0} will run on all ${c1}:target${c0}s." + echo +} + +builder_finish_action() { + local result="$1" + local action="$2" target action_name + + if [[ $action =~ : ]]; then + IFS=: read -r action target <<< $action + target=":$target" + else + target=':*' + fi + + if [[ "$target" == ":*" ]]; then + action_name="$action" + else + action_name="$action$target" + fi + + local scope="[$THIS_SCRIPT_IDENTIFIER] " + + if [[ "$action$target" == "${_builder_current_action}" ]]; then + if [[ $result == success ]]; then + echo "${COLOR_GREEN}## $scope$action_name completed successfully${COLOR_RESET}" + elif [[ $result == failure ]]; then + echo "${COLOR_RED}## $scope$action_name failed${COLOR_RESET}" + else + echo "${COLOR_RED}## $scope$action_name failed with message: $result${COLOR_RESET}" + fi + + # Remove $action$target from the array; it is no longer a current action + _builder_current_action= + else + echo "${COLOR_YELLOW}## Warning: reporting result of $action_name but the action was never started!${COLOR_RESET}" + fi +} + +# +# Returns `0` if the dependency should be built for the given action:target +# +_builder_should_build_dep() { + local action_target="$1" + local dep="$2" + local related_actions=(${_builder_dep_related_actions[$dep]}) + # echo "bdra: ${_builder_dep_related_actions[@]}" + # echo "target: $action_target" + # echo "dep: $2" + # echo "ra: ${related_actions[@]}" + if ! _builder_item_in_glob_array "$action_target" "${related_actions[@]}"; then + return 1 + fi + return 0 +} + +# +# Configure and build all dependencies +# Later, may restrict by either action or target +# +_builder_do_build_deps() { + local action_target="$1" + + if [[ $_builder_build_deps == --no-deps ]]; then + # we've been asked to skip dependencies + return 0 + fi + + for dep in "${_builder_deps[@]}"; do + # Don't attempt to build dependencies that don't match the current + # action:target (wildcards supported for matches here) + if ! _builder_should_build_dep "$action_target" "$dep"; then + echo "[$THIS_SCRIPT_IDENTIFIER] Skipping dependency build $dep for $_builder_matched_action_name" + continue + fi + + # Only configure and build the dependency once per invocation + if builder_has_module_been_built "$dep"; then + continue + fi + + # TODO: add --debug as a standard builder parameter + builder_set_module_has_been_built "$dep" + "$KEYMAN_ROOT/$dep/build.sh" configure build \ + $builder_verbose \ + $builder_debug \ + $_builder_build_deps \ + --builder-deps-built "$_builder_deps_built" \ + --builder-dep-parent "$THIS_SCRIPT_IDENTIFIER" + done +} + +# +# returns `0` if we are in a dependency doing a build. +# +builder_is_dep_build() { + if [[ ! -z ${builder_dep_parent+x} ]]; then + return 0 + fi + return 1 +} + +# +# returns `0` if we should attempt to do quick builds in a dependency build, for +# example skipping `tsc -b` where a parent may also do it; corresponds to the +# `--deps` parameter (which is the default). +# +builder_is_quick_dep_build() { + if builder_is_dep_build && [[ $_builder_build_deps == --deps ]]; then + return 0 + fi + return 1 +} + +# +# returns `0` if we should do a full configure and build in a dependency build; +# corresponds to the `--force-deps`` parameter. +# +builder_is_full_dep_build() { + if builder_is_dep_build && [[ $_builder_build_deps == --force-deps ]]; then + return 0 + fi + return 1 +} + +# +# returns `0` if the current build script has at least one dependency. +# +builder_has_dependencies() { + if [[ ${#_builder_deps[@]} -eq 0 ]]; then + return 1 + fi + return 0 +} + +# +# Tests if a dependency module has been built already in the current script +# invocation; if not running in a builder context, always returns `1` (i.e. +# "false"). +# +# ### Usage +# +# ```bash +# builder_has_module_been_built dependency-name +# ``` +# +# ### Parameters +# +# * 1: `dependency-name` the `$SCRIPT_IDENTIFIER` of the dependency +# (repo-relative path without leading `/`); or for +# external dependencies, a path-like starting with +# `/external/`. +# +# ### Examples +# +# ```bash +# if builder_has_module_been_built common/web/keyman-version; then ... +# if builder_has_module_been_built /external/npm-ci; then ... +# ``` +# +builder_has_module_been_built() { + local module="$1" + + if [[ -z ${_builder_deps_built+x} ]]; then + # not in a builder context, so we assume a build is needed + return 1 + fi + + if [[ -f $_builder_deps_built ]] && grep -qx "$module" $_builder_deps_built; then + # dependency history file contains the dependency module + return 0 + fi + return 1 +} + +# +# Updates the dependency module build state for the current script invocation; +# if not running in a builder context, a no-op. +# +# ### Usage +# +# ```bash +# builder_set_module_has_been_built dependency-name +# ``` +# +# ### Parameters +# +# * 1: `dependency-name` the `$SCRIPT_IDENTIFIER` of the dependency +# (repo-relative path without leading `/`); or for +# external dependencies, a path-like starting with +# `/external/`. +# +# ### Examples +# +# ```bash +# builder_set_module_has_been_built common/web/keyman-version +# builder_set_module_has_been_built /external/npm-ci +# ``` +# +builder_set_module_has_been_built() { + local module="$1" + + if [[ ! -z ${_builder_deps_built+x} ]]; then + echo "$module" >> $_builder_deps_built + fi +} + +# +# returns `0` if we should be verbose in output +# +builder_verbose() { + if [[ $builder_verbose == --verbose ]]; then + return 0 + fi + return 1 +} + +# +# returns `0` if we are doing a debug build +# +builder_debug() { + if [[ $builder_debug == --debug ]]; then + return 0 + fi + return 1 +} + +# +# Reports on all described dependencies, then exits +# used by builder-controls.sh +# +_builder_report_dependencies() { + echo "${_builder_deps[@]}" + exit 0 +} + +# +# Initialize builder once all functions are declared +# +_builder_init diff --git a/resources/keyman-site.conf b/resources/keyman-site.conf new file mode 100644 index 00000000..9f1c976a --- /dev/null +++ b/resources/keyman-site.conf @@ -0,0 +1,13 @@ + + SetHandler text/html + + +DirectoryIndex index.md index.php index.html + + + Options +Includes +FollowSymLinks -MultiViews + AllowOverride All + + +php_value include_path "/var/www/html/_includes:." + From 39624ef678d4857b8bd0aa09b42301210707bbd0 Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Fri, 20 Jan 2023 13:48:47 +0700 Subject: [PATCH 13/73] fix: Move configure step to start --- build.sh | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/build.sh b/build.sh index 1415d5d1..e26e3dae 100755 --- a/build.sh +++ b/build.sh @@ -44,18 +44,7 @@ builder_parse "$@" cd "$REPO_ROOT" if builder_start_action configure; then - # Skip if link already exists - if [ -L vendor ]; then - echo "Skipping because vendor already exists" - else - # Create link to vendor/ folder - KEYMAN_CONTAINER=$(_get_docker_container_id) - if [ ! -z "$KEYMAN_CONTAINER" ]; then - docker exec -i $KEYMAN_CONTAINER sh -c "ln -s /var/www/vendor vendor && chown -R www-data:www-data vendor" - else - echo "No Docker container to configure" - fi - fi + # Nothing to do builder_finish_action success configure fi @@ -96,7 +85,6 @@ fi if builder_start_action start; then # Start the Docker container if [ ! -z $(_get_docker_image_id) ]; then - # TODO: What port to use? if [[ $OSTYPE =~ msys|cygwin ]]; then # Windows needs leading slashes for path docker run -d -p 8053:80 -v //$(pwd):/var/www/html/ -e S_KEYMAN_COM=localhost:8054 keyman-website @@ -108,6 +96,19 @@ if builder_start_action start; then builder_finish_action fail start fi + # Skip if link already exists + if [ -L vendor ]; then + echo "Link to vendor/ already exists" + else + # Create link to vendor/ folder + KEYMAN_CONTAINER=$(_get_docker_container_id) + if [ ! -z "$KEYMAN_CONTAINER" ]; then + docker exec -i $KEYMAN_CONTAINER sh -c "ln -s /var/www/vendor vendor && chown -R www-data:www-data vendor" + else + echo "No Docker container running to create link to vendor/" + fi + fi + builder_finish_action success start fi From acbf2619ce269015e6a6933da3b048c00fa1362a Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Thu, 10 Aug 2023 07:07:37 +0700 Subject: [PATCH 14/73] chore: Update build.sh with latest builder.inc.sh --- build.sh | 16 +- resources/builder.inc.sh | 929 ++++++++++++++++++++++++++++++++------- 2 files changed, 791 insertions(+), 154 deletions(-) diff --git a/build.sh b/build.sh index e26e3dae..f51cea58 100755 --- a/build.sh +++ b/build.sh @@ -84,13 +84,23 @@ fi if builder_start_action start; then # Start the Docker container + + if [ -d vendor ]; then + builder_die "vendor folder is in the way. Please delete it" + fi + if [ ! -z $(_get_docker_image_id) ]; then if [[ $OSTYPE =~ msys|cygwin ]]; then # Windows needs leading slashes for path - docker run -d -p 8053:80 -v //$(pwd):/var/www/html/ -e S_KEYMAN_COM=localhost:8054 keyman-website + SITE_HTML="//$(pwd):/var/www/html/" else - docker run -d -p 8053:80 -v $(pwd):/var/www/html/ -e S_KEYMAN_COM=localhost:8054 keyman-website + SITE_HTML="$(pwd):/var/www/html/" fi + + docker run --rm -d -p 8053:80 -v ${SITE_HTML} \ + -e S_KEYMAN_COM=localhost:8054 \ + --name keyman-com-app \ + keyman-website else echo "${COLOR_RED}ERROR: Docker container doesn't exist. Run ./build.sh build first${COLOR_RESET}" builder_finish_action fail start @@ -98,7 +108,7 @@ if builder_start_action start; then # Skip if link already exists if [ -L vendor ]; then - echo "Link to vendor/ already exists" + builder_echo "\nLink to vendor/ already exists" else # Create link to vendor/ folder KEYMAN_CONTAINER=$(_get_docker_container_id) diff --git a/resources/builder.inc.sh b/resources/builder.inc.sh index 4234df67..6a47cbd5 100755 --- a/resources/builder.inc.sh +++ b/resources/builder.inc.sh @@ -1,4 +1,12 @@ #!/usr/bin/env bash + +# Note: these two lines can be uncommented for debugging and profiling build +# scripts: +# +# set -x +# PS4='+ $EPOCHREALTIME $0 $LINENO ' +# + # # This script contains utilities for builder_script calls # @@ -19,7 +27,7 @@ function _builder_init() { _builder_findRepoRoot _builder_setBuildScriptIdentifiers - if [[ -n "$TERM" ]] && [[ "$TERM" != "dumb" ]] && [[ "$TERM" != "unknown" ]]; then + if [[ -n "$TERM" ]] && [[ "$TERM" != "dumb" ]] && [[ "$TERM" != "unknown" ]] && [ -t 1 ]; then builder_use_color true else builder_use_color false @@ -27,11 +35,9 @@ function _builder_init() { } function _builder_findRepoRoot() { - # See https://stackoverflow.com/questions/59895/how-to-get-the-source-directory-of-a-bash-script-from-within-the-script-itself - # None of the answers are 100% correct for cross-platform - # On macOS, requires coreutils (`brew install coreutils`) - local SCRIPT=$(greadlink -f "${BASH_SOURCE[0]}" 2>/dev/null || readlink -f "${BASH_SOURCE[0]}") - REPO_ROOT=$(dirname $(dirname "$SCRIPT")) + # We don't need readlink here because our standard script prolog does a + # readlink -f already so we will have already escaped from any symlinks + REPO_ROOT="${BASH_SOURCE[0]%/*/*}" readonly REPO_ROOT } @@ -44,22 +50,22 @@ function _builder_findRepoRoot() { # ```bash # ## START STANDARD BUILD SCRIPT INCLUDE # # adjust relative paths as necessary -# THIS_SCRIPT="$(greadlink -f "${BASH_SOURCE[0]}" 2>/dev/null || readlink -f "${BASH_SOURCE[0]}")" -# . "$(dirname "$THIS_SCRIPT")/resources/builder.inc.sh" +# THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")" +# . "${THIS_SCRIPT%/*}/resources/builder.inc.sh" # ## END STANDARD BUILD SCRIPT INCLUDE # ``` # function _builder_setBuildScriptIdentifiers() { if [ ! -z ${THIS_SCRIPT+x} ]; then - THIS_SCRIPT_PATH="$(dirname "$THIS_SCRIPT")" + THIS_SCRIPT_PATH="${THIS_SCRIPT%/*}" readonly THIS_SCRIPT_PATH - THIS_SCRIPT_NAME="$(basename "$THIS_SCRIPT")" + THIS_SCRIPT_NAME="${THIS_SCRIPT##*/}" readonly THIS_SCRIPT_NAME # Leaves only the part of the path based upon REPO_ROOT. THIS_SCRIPT_IDENTIFIER=${THIS_SCRIPT_PATH#"$REPO_ROOT/"} readonly THIS_SCRIPT_IDENTIFIER else - echo "Warning: THIS_SCRIPT not defined; builder.inc.sh has not been sourced with standard script include." + builder_die "THIS_SCRIPT not defined; builder.inc.sh has not been sourced with standard script include." fi } @@ -77,18 +83,20 @@ function _builder_setBuildScriptIdentifiers() { # 1: use_color true or false builder_use_color() { if $1; then - COLOR_RED=$(tput setaf 1) - COLOR_GREEN=$(tput setaf 2) - COLOR_YELLOW=$(tput setaf 3) - COLOR_BLUE=$(tput setaf 4) - COLOR_PURPLE=$(tput setaf 5) - COLOR_TEAL=$(tput setaf 6) - COLOR_WHITE=$(tput setaf 7) - COLOR_GREY=$(tput setaf 8) - COLOR_RESET=$(tput sgr0) + # Using esc codes instead of tput for performance + COLOR_RED='\x1b[31m' # $(tput setaf 1) + COLOR_GREEN='\x1b[32m' # $(tput setaf 2) + COLOR_YELLOW='\x1b[33m' # $(tput setaf 3) + COLOR_BLUE='\x1b[34m' # $(tput setaf 4) + COLOR_PURPLE='\x1b[35m' # $(tput setaf 5) + COLOR_TEAL='\x1b[36m' # $(tput setaf 6) + COLOR_WHITE='\x1b[38;5;252m' # $(tput setaf 252) + COLOR_BRIGHT_WHITE='\x1b[38;5;255m' # $(tput setaf 255) + COLOR_GREY='\x1b[90m' # $(tput setaf 8) + COLOR_RESET='\x1b(B\x1b[m' # $(tput sgr0) # e.g. VSCode https://code.visualstudio.com/updates/v1_69#_setmark-sequence-support + BUILDER_BOLD='\x1b[1m' # $(tput bold) HEADING_SETMARK='\x1b]1337;SetMark\x07' - # Used by `builder_display_usage` when marking special terms (actions, targets, options) # in the plain-text description area. BUILDER_TERM_START="$COLOR_BLUE" @@ -101,32 +109,92 @@ builder_use_color() { COLOR_PURPLE= COLOR_TEAL= COLOR_WHITE= + COLOR_BRIGHT_WHITE= COLOR_GREY= COLOR_RESET= + BUILDER_BOLD= HEADING_SETMARK= BUILDER_TERM_START="<" BUILDER_TERM_END=">" fi } +# +# Wraps the input string in `builder_display_usage` with $BUILDER_TERM_START and +# $BUILDER_TERM_END +# +function builder_term() { + echo "${BUILDER_TERM_START}$*${BUILDER_TERM_END}" +} + function builder_die() { echo - echo "${COLOR_RED}$*" + if [[ $# -eq 0 ]]; then + builder_echo error "Unspecified error, aborting script" + else + builder_echo error "$*" + fi echo exit 1 } +function builder_warn() { + builder_echo warning "$*" +} + +function builder_heading() { + builder_echo heading "$*" +} + + #################################################################################### # # builder_ functions for standard build script parameter and process management # #################################################################################### + +builder_echo() { + local color=white message= mark= + if [[ $# -gt 1 && $1 =~ ^(white|grey|green|success|blue|heading|yellow|warning|red|error|purple|brightwhite|teal|debug|setmark)$ ]]; then + color="$1" + shift + fi + message="$*" + + if [[ ! -z ${COLOR_RED+x} ]]; then + case $color in + white) color="$COLOR_WHITE" ;; + grey) color="$COLOR_GREY" ;; + green|success) color="$COLOR_GREEN" ;; + blue|heading) color="$COLOR_BLUE" ;; + yellow|warning) color="$COLOR_YELLOW" ;; + red|error) color="$COLOR_RED" ;; + purple) color="$COLOR_PURPLE" ;; + brightwhite) color="$COLOR_BRIGHTWHITE" ;; + teal|debug) color="$COLOR_TEAL" ;; + setmark) mark="$HEADING_SETMARK" color="$COLOR_PURPLE" ;; + esac + + if builder_is_dep_build; then + echo -e "$mark$COLOR_GREY[$THIS_SCRIPT_IDENTIFIER]$COLOR_RESET $color$message$COLOR_RESET" + else + echo -e "$mark$BUILDER_BOLD$COLOR_BRIGHT_WHITE[$THIS_SCRIPT_IDENTIFIER]$COLOR_RESET $color$message$COLOR_RESET" + fi + else + # Cope with the case of pre-init message and just emit plain text + echo -e "$message" + fi +} + +builder_echo_debug() { + builder_echo debug "[DEBUG] $*" +} + # # builder_ names are reserved. # _builder_ names are internal use and subject to change # -_builder_debug=false # # builder_extra_params: string containing all parameters after '--' @@ -172,6 +240,67 @@ _builder_item_in_glob_array() { return 1 } +# +# Expands a shorthand item into a full match from an array of possibilities; +# reports an error if there are ambiguous options. Note that this function +# returns the number of matches, so 0 = no match, 1 = a precise match. +# +# ### Parameters +# +# * 1: `item` item to search for in array, e.g. "t" +# * 2: `array` bash array, e.g. `array=(one two three)` +# +# ### Description +# +# Does a substring search by regex for +# +# ### Example +# +# ```bash +# actions=(clean configure build test) +# +# action=`_builder_expand_shorthand $1 "${actions[@]}"` && +# builder_die "Unrecognized parameter $1" || +# case $? in +# 1) echo "Parameter $1 matches {$action}" +# ;; +# *) builder_die "Parameter $1 has $? matches, could mean any of {$action}" +# esac +# ``` +# +_builder_expand_shorthand() { + local item=$1 + shift + local count=0 + local result= + local string= + for e; do + if [[ $e == $item ]]; then + # Exact match trumps substring matches + echo $item + return 1 + fi + if [[ $e == "$item"* ]]; then + count=$((count+1)) + if [[ $count == 2 ]]; then + string="$result, $e" + result=$item + elif [[ $count -gt 2 ]]; then + string="$string, $e" + else + result=$e + fi + fi + done + + if [[ $count -lt 2 ]]; then + echo $result + else + echo $string + fi + return $count +} + _builder_item_is_target() { local item="$1" @@ -181,8 +310,7 @@ _builder_item_is_target() { function _builder_warn_if_incomplete() { if [ -n "${_builder_current_action}" ]; then - local scope="[$THIS_SCRIPT_IDENTIFIER] " - echo "${COLOR_YELLOW}## ${scope}Warning - $_builder_current_action never reported success or failure${COLOR_RESET}" + builder_echo warning "$_builder_current_action never reported success or failure" # exit 1 # If we wanted this scenario to result in a forced build-script fail. fi @@ -211,19 +339,19 @@ _builder_failure_trap() { if [ -n "${_builder_current_action}" ]; then action="${_builder_current_action}" if [[ $action =~ : ]]; then - IFS=: read -r action target <<< $action + IFS=: read -r action target <<< "$action" target=:$target else target=:project fi builder_finish_action failure $action$target - - # Make 100% sure that the exit code chains fully. - # Without this, nested scripts have failed to chain errors from npm calls past the script - # that directly executed the failed npm command. - exit $trappedExitCode fi + + # Make 100% sure that the exit code chains fully. + # Without this, nested scripts have failed to chain errors from npm calls past the script + # that directly executed the failed npm command. + exit $trappedExitCode } # @@ -231,9 +359,9 @@ _builder_failure_trap() { # finishes. # _builder_cleanup_deps() { - if ! builder_is_dep_build && [[ ! -z ${_builder_deps_built+x} ]]; then - if $_builder_debug; then - echo "[DEBUG] Dependencies that were built:" + if ! builder_is_dep_build && ! builder_is_child_build && [[ ! -z ${_builder_deps_built+x} ]]; then + if $_builder_debug_internal; then + builder_echo_debug "Dependencies that were built:" cat "$_builder_deps_built" fi rm -f "$_builder_deps_built" @@ -241,6 +369,110 @@ _builder_cleanup_deps() { fi } +#------------------------------------------------------------------------------------------ +# Child scripts +#------------------------------------------------------------------------------------------ + +_builder_execute_child() { + local action=$1 + local target=$2 + + local script="$THIS_SCRIPT_PATH/${_builder_target_paths[$target]}/build.sh" + + if $_builder_debug_internal; then + builder_echo heading "## $action$target starting..." + fi + + # Build array of specified inheritable options + local child_options=() + local opt + for opt in "${_builder_options_inheritable[@]}"; do + if builder_has_option $opt; then + child_options+=($opt) + fi + done + + "$script" $action \ + --builder-child \ + $_builder_build_deps \ + ${child_options[@]} \ + $builder_verbose \ + $builder_debug \ + && ( + if $_builder_debug_internal; then + builder_echo success "## $action$target completed successfully" + fi + ) || ( + result=$? + builder_echo error "## $action$target failed with exit code $result" + exit $result + ) || exit $? # Required due to above subshell masking exit +} + +_builder_run_child_action() { + local action="$1" target + + if [[ $action =~ : ]]; then + IFS=: read -r action target <<< "$action" + target=:$target + else + target=':*' + fi + + if builder_has_action $action$target; then + if [[ $target == ':*' ]]; then + # run all children in order specified in builder_describe + for target in "${_builder_targets[@]}"; do + # We have to re-test the action because the user may not + # have specified all targets in their invocation + if builder_has_action $action$target; then + if [[ ! -z ${_builder_target_paths[$target]+x} ]] && + [[ -f "$THIS_SCRIPT_PATH/${_builder_target_paths[$target]}/build.sh" ]]; then + _builder_execute_child $action $target + fi + fi + done + else + # If specified explicitly, we assume existence of a child build script. + _builder_execute_child $action $target + fi + fi +} + +# +# Executes the specified actions on all child targets, or on the specified +# targets. A child target is any target which has a sub-folder of the same name +# as the target. However, the actions will only be run if they have been +# specified by the user on the command-line. +# +# ### Usage +# +# ```bash +# builder_run_child_actions action1 [...] +# ``` +# +# ### Parameters +# +# 1...: action[:target] name of action:target to run +# +# ### Example +# +# ```bash +# builder_run_child_actions configure build test install +# ``` +# +builder_run_child_actions() { + while [[ $# -gt 0 ]]; do + local action="$1" + _builder_run_child_action "$action" + shift + done +} + +#------------------------------------------------------------------------------------------ +# Various API endpoints +#------------------------------------------------------------------------------------------ + # # Builds the standardized `action:target` string for the specified action-target # pairing and also returns 0 if the user has asked to perform it on the command @@ -256,9 +488,11 @@ _builder_cleanup_deps() { # if build_has_action action[:target]; then ...; fi # ```` # -# Parameters: +# ### Parameters +# # 1: action[:target] name of action:target -# Example: +# +# ### Example # # ```bash # if builder_has_action build:app; then ... @@ -268,7 +502,7 @@ builder_has_action() { local action="$1" target if [[ $action =~ : ]]; then - IFS=: read -r action target <<< $action + IFS=: read -r action target <<< "$action" target=:$target else target=':*' @@ -289,6 +523,48 @@ builder_has_action() { fi } +# +# Wraps builder_start_action and builder_finish action for single-command +# actions. Can be used together with a local function for multi-command actions. +# Do be aware that this pseudo-closure style cannot be mixed with operators such +# as `<`, `>`, `&&`, `;`, `()` and so on. +# +# ### Usage +# +# ```bash +# builder_run_action action[:target] command [command-params...] +# ``` +# +# ### Parameters +# +# * 1: `action[:target]` name of action, and optionally also target, if target +# excluded starts for all defined targets +# * 2: command command to run if action is started +# * 3...: command-params parameters for command +# +# ### Example +# +# ```bash +# function do_build() { +# mkdir -p build/cjs-src +# npm run build +# } +# +# builder_run_action clean rm -rf ./build/ ./tsconfig.tsbuildinfo +# builder_run_action configure verify_npm_setup +# builder_run_action build do_build +# ``` +# +function builder_run_action() { + local action=$1 + shift + if builder_start_action $action; then + ($@) + builder_finish_action success $action + fi + return 0 +} + # # Returns `0` if the user has asked to perform action on target on the command # line, and then starts the action. Should be paired with @@ -312,21 +588,18 @@ builder_has_action() { # ``` # builder_start_action() { - local scope="[$THIS_SCRIPT_IDENTIFIER] " - if builder_has_action $1; then # In a dependency quick build (the default), determine whether we actually # need to run this step. Uses data passed to builder_describe_outputs to # verify whether a target output is present. if builder_is_dep_build && ! builder_is_full_dep_build && - [[ ! -z ${_builder_dep_path[$_builder_matched_action]+x} ]] && - [[ -e "$KEYMAN_ROOT/${_builder_dep_path[$_builder_matched_action]}" ]]; then - echo "$scope skipping $_builder_matched_action_name, up-to-date" + _builder_dep_output_exists $_builder_matched_action; then + builder_echo "skipping $_builder_matched_action_name, up-to-date" return 1 fi - echo "${COLOR_BLUE}## $scope$_builder_matched_action_name starting...${COLOR_RESET}" + builder_echo blue "## $_builder_matched_action_name starting..." if [ -n "${_builder_current_action}" ]; then _builder_warn_if_incomplete fi @@ -359,7 +632,20 @@ builder_has_option() { return 1 } -_builder_trim() { +# +# Trims leading and following whitespace from the input parameters +# +# ### Usage +# +# ```bash +# my_string="$(builder_trim "$my_string")" +# ``` +# +# ### Parameters +# +# * `my_string` An input string +# +builder_trim() { local var="$*" # remove leading whitespace characters var="${var#"${var%%[![:space:]]*}"}" @@ -397,10 +683,9 @@ _builder_expand_relative_path() { _builder_expand_action_target() { local input="$1" target= action= if [[ "$input" =~ : ]]; then - action=$(echo "$input" | cut -d: -f 1 -) - target=$(echo "$input" | cut -d: -f 2 -) + IFS=":" read -r action target <<< "$input" else - action=$input + action="$input" fi if [[ -z "$action" ]]; then @@ -416,8 +701,8 @@ _builder_expand_action_target() { _builder_expand_action_targets() { local input=($1) e output=() for e in "${input[@]}"; do - e=`_builder_expand_action_target "$e"` - output+=($e) + e="$(_builder_expand_action_target "$e")" + output+=("$e") done if [[ ${#output[@]} == 0 ]]; then echo "*:*" @@ -426,6 +711,30 @@ _builder_expand_action_targets() { fi } +_builder_child_base= +# +# Describes the path from the build script's working directory to the common subfolder +# containing child scripts / projects without defined custom paths. +# +# This function must be called to set the child base path before builder_describe is +# called in order to work correctly. Furthermore, note that this setting will be +# ignored by targets with custom paths. +# +# ### Usage +# +# ```bash +# builder_set_child_base path +# ``` +# +# ### Parameters +# +# * `path` The relative path from the directory containing the calling script to +# the base folder to use for child-project detection and resolution +# +builder_set_child_base() { + _builder_child_base="$1/" +} + # # Describes a build script, defines available parameters and their meanings. Use # together with `builder_parse` to process input parameters. @@ -445,28 +754,40 @@ _builder_expand_action_targets() { # # There are four types of parameters that may be specified: # -# * **Option:** `"--option[,-o][=var] [One line description]"` +# * **Option:** `"--option[,-o][+][=var] [One line description]"` # # All options must have a longhand form with two prefix hyphens, # e.g. `--option`. The `,-o` shorthand form is optional. When testing if # the option is set with `builder_has_option`, always use the longhand # form. # -# if `=var` is specified, then the next parameter will be a variable stored in +# If `=var` is specified, then the next parameter will be a variable stored in # `$var` for that option. e.g. `--option=opt` means `$opt` will have the value # `"foo"` when the script is called for `--option foo`. # +# If `+` is specified, then the option will be passed to child scripts. All +# child scripts _must_ accept this option, or they will fail. It is acceptable +# for the child script to declare the option but ignore it. However, the option +# will _not_ be passed to dependencies. +# # * **Action**: `"action [One line description]"` # # Actions must be a single word, lower case. To specify an action as the # default, append a `+` to the action name, e.g. `"test+ Test the project"`. # If there is no default specified, then it will be `build`. # -# * **Target:** `":target [One line description]"` +# * **Target:** `":target[=path] [One line description]"` # -# A target always starts with colon, e.g. `:project`. +# A target always starts with colon, e.g. `:project`. If a folder exists with +# the same name as a target, then that automatically denotes the target as a +# "child project". This can simplify parent-child style scripts, using the +# [`builder_run_child_actions`] function. # -# * **Dependency:** "@/path/to/dependency [action][:target] ..." +# A child project with an alternate folder can also be specified by appending +# `=path` to the target definition, for example `:app=src/app`. Where +# possible, avoid differences in names of child projects and folders. +# +# * **Dependency:** `"@/path/to/dependency[:target] [action][:target] ..."`` # # A dependency always starts with `@`. The path to the dependency will be # relative to the build script folder, or to the root of the repository, if @@ -476,17 +797,24 @@ _builder_expand_action_targets() { # Relative paths will be expanded to full paths, again, relative to the root # of the repository. # -# Dependencies may be limited to specific `action:target`. If not specified, -# dependencies will be built for all actions on all targets. Either `action` -# or `:target` may be omitted, and multiple actions and targets may be -# specified, space separated. +# A dependency definition can include a target for that dependency, for +# example, `"@/core:arch"`. This would build only the ':arch' target for the +# core module. +# +# Dependencies may be limited to specific `action:target` pairs on the current +# script. If not specified, dependencies will be built for all actions on all +# targets. Either `action` or `:target` may be omitted, and multiple actions +# and targets may be specified, space separated. # builder_describe() { + _builder_record_function_call builder_describe + _builder_description="$1" _builder_actions=() _builder_targets=() _builder_options=() _builder_deps=() # array of all dependencies for this script + _builder_options_inheritable=() # array of all options that should be passed to child scripts _builder_default_action=build declare -A -g _builder_params declare -A -g _builder_options_short @@ -494,26 +822,56 @@ builder_describe() { declare -A -g _builder_dep_path # array of output files for action:target pairs declare -A -g _builder_dep_related_actions # array of action:targets associated with a given dependency declare -A -g _builder_internal_dep # array of internal action:targets dependency relationships + declare -A -g _builder_target_paths # array of target child project paths + declare -A -g _builder_dep_targets # array of :targets given for a specific dependency (comma separated if more than one) shift + local sub=() # describe each target, action, and option possibility while [[ $# -gt 0 ]]; do local key="$1" - local value="$(echo "$key" | cut -d" " -f 1 -)" + local value="$key" local description= if [[ $key =~ [[:space:]] ]]; then - description="$(_builder_trim "$(echo "$key" | cut -d" " -f 2- -)")" + IFS=" " read -r -a sub <<< "$key" + value="${sub[0]}" + description="$(builder_trim "${sub[@]:1}")" fi if [[ $value =~ ^: ]]; then # Parameter is a target + local target_path= + if [[ $value =~ = ]]; then + # The target has a custom child project path + IFS="=" read -r -a sub <<< "$value" + target_path="${sub[@]:1}" + value="${sub[0]}" + if [[ ! -d "$THIS_SCRIPT_PATH/$target_path" ]]; then + builder_die "Target path '$target_path' for $value does not exist." + fi + else + # If the target name matches a folder name, implicitly + # make it available as a child project + if [[ -d "$THIS_SCRIPT_PATH/$_builder_child_base${value:1}" ]]; then + target_path="$_builder_child_base${value:1}" + fi + fi _builder_targets+=($value) + if [[ ! -z "$target_path" ]]; then + _builder_target_paths[$value]="$target_path" + fi elif [[ $value =~ ^@ ]]; then # Parameter is a dependency local dependency="${value:1}" + local dependency_target= # all targets + if [[ $dependency =~ : ]]; then + IFS=":" read -r dependency dependency_target <<< "$dependency" + dependency_target=":$dependency_target" + fi + dependency="`_builder_expand_relative_path "$dependency"`" _builder_deps+=($dependency) - _builder_dep_related_actions[$dependency]="`_builder_expand_action_targets "$description"`" - + _builder_dep_related_actions[$dependency]="$(_builder_expand_action_targets "$description")" + _builder_dep_targets[$dependency]="$dependency_target" # We don't want to add deps to params, so shift+continue shift continue @@ -522,14 +880,27 @@ builder_describe() { # Look for a shorthand version of the option local option_var= if [[ $value =~ = ]]; then - option_var="$(echo "$value" | cut -d= -f 2 -)" - value="$(echo "$value" | cut -d= -f 1 -)" + IFS="=" read -r -a sub <<< "$value" + option_var="${sub[@]:1}" + value="${sub[0]}" + fi + + local is_inheritable=false + + if [[ $value =~ \+$ ]]; then + # final + indicates that option is inheritable + is_inheritable=true + value="${value:0:-1}" fi if [[ $value =~ , ]]; then - local option_long="$(echo "$value" | cut -d, -f 1 -)" - local option_short="$(echo "$value" | cut -d, -f 2 -)" + IFS="," read -r -a sub <<< "$value" + local option_long="${sub[0]}" + local option_short="${sub[@]:1}" _builder_options+=($option_long) + if $is_inheritable; then + _builder_options_inheritable+=($option_long) + fi _builder_options_short[$option_short]="$option_long" if [[ ! -z "$option_var" ]]; then _builder_options_var[$option_long]="$option_var" @@ -537,6 +908,9 @@ builder_describe() { value="$option_long, $option_short" else _builder_options+=($value) + if $is_inheritable; then + _builder_options_inheritable+=($value) + fi if [[ ! -z "$option_var" ]]; then _builder_options_var[$value]="$option_var" fi @@ -545,6 +919,7 @@ builder_describe() { if [[ ! -z $option_var ]]; then value="$value $option_var" fi + else # Parameter is an action if [[ $value =~ \+$ ]]; then @@ -594,18 +969,20 @@ builder_describe() { # # ```bash # builder_describe_outputs \ -# configure /node_modules \ -# build build/index.js +# configure /node_modules \ +# build build/index.js # ``` # function builder_describe_outputs() { + _builder_record_function_call builder_describe_outputs + while [[ $# -gt 0 ]]; do - local key="$1" path="$2" action target + local key="$1" path="$2" action= target= path="`_builder_expand_relative_path "$path"`" if [[ $key =~ : ]]; then - action="$(echo "$key" | cut -d: -f 1 -)" - target=":$(echo "$key" | cut -d: -f 2 -)" + IFS=":" read -r action target <<< "$key" + target=":$target" else # Add dependency expected output file for all targets, as well as a # wildcard target match @@ -620,6 +997,11 @@ function builder_describe_outputs() { done _builder_define_default_internal_dependencies + + # We only want to define internal dependencies after both builder_parse and builder_describe_outputs have been called + if _builder_has_function_been_called builder_parse; then + _builder_add_chosen_action_target_dependencies + fi } _builder_get_default_description() { @@ -645,23 +1027,20 @@ _builder_parameter_error() { local program="$1" local type="$2" local param="$3" - echo "$COLOR_RED$program: invalid $type: $param$COLOR_RESET" + builder_echo red "$program: invalid $type: $param" echo builder_display_usage exit 64 - } +# # Pre-initializes the color setting based on the options specified to a -# a build.sh script, parsing the command line to do so. This is only -# needed if said script wishes to use this script's defined colors while -# respecting the options provided by the script's caller. +# a build.sh script. This is called automatically during init. # -# Usage: -# builder_check_color "$@" # Parameters -# 1: $@ all command-line arguments (as with builder_parse) -builder_check_color() { +# 1: "$@" all command-line arguments +# +_builder_check_color() { # Process command-line arguments while [[ $# -gt 0 ]] ; do local key="$1" @@ -683,33 +1062,41 @@ builder_check_color() { # its full internal dependency tree # _builder_add_chosen_action_target_dependencies() { - local action_target e i=0 new_actions=() + local action_target i=0 new_actions=() # Iterate through every action specified on command line; we use this loop # style so that any new actions added here will also be iteratively checked while (( $i < ${#_builder_chosen_action_targets[@]} )); do action_target=${_builder_chosen_action_targets[$i]} - # If we have an internal dependency for the chosen action:target pair, add - # it to the list, but only if there is a defined output and that output is - # missing + # If we have an internal dependency for the chosen action:target pair if [[ ! -z ${_builder_internal_dep[$action_target]+x} ]]; then - local dep_output=${_builder_internal_dep[$action_target]} - if [[ ! -z ${_builder_dep_path[$dep_output]+x} ]] && - [[ ! -e "$KEYMAN_ROOT/${_builder_dep_path[$dep_output]}" ]]; then - if ! _builder_item_in_array "$dep_output" "${_builder_chosen_action_targets[@]}"; then - _builder_chosen_action_targets+=($dep_output) - new_actions+=($dep_output) + local dep_outputs=(${_builder_internal_dep[$action_target]}) dep_output + for dep_output in "${dep_outputs[@]}"; do + # If there is a defined output for this dependency + if [[ ! -z ${_builder_dep_path[$dep_output]+x} ]]; then + # If the output for the dependency is missing, or we have --force-deps + if [[ ! -e "$KEYMAN_ROOT/${_builder_dep_path[$dep_output]}" ]] || builder_is_full_dep_build; then + # Add the dependency to the chosen action:target list + if ! _builder_item_in_array "$dep_output" "${_builder_chosen_action_targets[@]}"; then + _builder_chosen_action_targets+=($dep_output) + new_actions+=($dep_output) + fi + fi fi - fi + done fi i=$((i + 1)) done if [[ ${#new_actions[@]} -gt 0 ]]; then - echo "Automatically running following required actions with missing outputs:" + if builder_is_full_dep_build; then + builder_echo "Automatically running all dependency actions due to --force-deps:" + else + builder_echo "Automatically running following required actions with missing outputs:" + fi for e in "${new_actions[@]}"; do - echo "* $e" + builder_echo "* $e" done fi } @@ -739,10 +1126,39 @@ _builder_define_default_internal_dep() { local target=$1 dep=$2 action=$3 if _builder_item_in_array $dep "${_builder_actions[@]}" && _builder_item_in_array $action "${_builder_actions[@]}"; then - _builder_internal_dep[$action$target]=$dep$target + [[ -z ${_builder_internal_dep[$action$target]+x} ]] && + _builder_internal_dep[$action$target]=$dep$target || + _builder_internal_dep[$action$target]="${_builder_internal_dep[$action$target]} $dep$target" fi } +# +# Define a local dependency between one action:target and +# another. +# +# Usage: +# builder_describe_internal_dependency action:target depaction:deptarget ... +# Parameters: +# 1: action:target The action and target that has a dependency +# 2: depaction:deptarget The dependency action and target +# Example: +# builder_describe_internal_dependency \ +# mac:build mac-x86_64:build \ +# mac:build mac-arm64:build +# +# Note: actions and targets must be fully specified, and this _must_ +# be called before either builder_describe_outputs or builder_parse in +# order for dependencies to be resolved. +builder_describe_internal_dependency() { + while [[ $# -gt 0 ]]; do + local action_target=$1 dep_action_target=$2 + [[ -z ${_builder_internal_dep[$action_target]+x} ]] && + _builder_internal_dep[$action_target]=$dep_action_target || + _builder_internal_dep[$action_target]="${_builder_internal_dep[$action_target]} $dep_action_target" + shift 2 + done +} + # Initializes a build.sh script, parses command line. Will abort the script if # invalid parameters are passed in. Use together with builder_describe which # sets up the possible command line parameters @@ -752,13 +1168,72 @@ _builder_define_default_internal_dep() { # Parameters # 1: $@ command-line arguments builder_parse() { + _builder_record_function_call builder_parse + + local exp=() + builder_extra_params=() + + while [[ $# -gt 0 ]] ; do + local action= target= + local key="$1" + if [[ $key == "--" ]]; then + shift + builder_extra_params=("$@") + break + fi + + if [[ $key =~ ^- ]]; then + exp+=($key) + else + # Expand comma separated values + if [[ $key =~ : ]]; then + IFS=: read -r action target <<< "$key" + else + action="$key" + target= + fi + + local actions targets + IFS=, read -r -a actions <<< "$action" + IFS=, read -r -a targets <<< "$target" + + if [[ "${#actions[@]}" -eq 0 ]]; then + # No actions, so must be at least one :target + for target in "${targets[@]}"; do + exp+=(:$target) + done + else + for action in "${actions[@]}"; do + if [[ "${#targets[@]}" -eq 0 ]]; then + # No :targets so just expand actions + exp+=($action) + else + # Actions:targets, expand them all + for target in "${targets[@]}"; do + exp+=($action:$target) + done + fi + done + fi + fi + + shift + done + + _builder_parse_expanded_parameters "${exp[@]}" +} + +_builder_parse_expanded_parameters() { _builder_build_deps=--deps builder_verbose= builder_debug= - builder_extra_params=() + local _params=($@) _builder_chosen_action_targets=() _builder_chosen_options=() _builder_current_action= + _builder_is_child=1 + + local n=0 # Process command-line arguments while [[ $# -gt 0 ]] ; do @@ -767,23 +1242,47 @@ builder_parse() { local target= local e has_action has_target has_option longhand_option - if [[ $key == "--" ]]; then - shift - builder_extra_params=("$@") - break - fi - if [[ $key =~ : ]]; then - IFS=: read -r action target <<< $key + IFS=: read -r action target <<< "$key" target=:$target else action="$key" target= fi + # Expand shorthand parameters + + new_action=$(_builder_expand_shorthand $action "${_builder_actions[@]}") || + case $? in + 1) + action=$new_action + ;; + *) + builder_warn "Parameter $action has $? matches, could mean any of {$new_action}" + exit 1 + ;; + esac + + new_target=$(_builder_expand_shorthand $target "${_builder_targets[@]}") || + case $? in + 1) + target=$new_target + ;; + *) + builder_warn "Parameter $target has $? matches, could mean any of {$new_target}" + exit 1 + ;; + esac + _builder_item_in_array "$action" "${_builder_actions[@]}" && has_action=1 || has_action=0 _builder_item_in_array "$target" "${_builder_targets[@]}" && has_target=1 || has_target=0 + if (( has_action )) || (( has_target )); then + # Document parameter expansion for end use + _params[$n]=$action$target + fi + n=$((n + 1)) + # Expand short -o to --option in options lookup if [[ ! -z ${_builder_options_short[$key]+x} ]]; then key=${_builder_options_short[$key]} @@ -792,7 +1291,7 @@ builder_parse() { if (( has_action )) && (( has_target )); then # apply the selected action and selected target - _builder_chosen_action_targets+=("$key") + _builder_chosen_action_targets+=("$action$target") elif (( has_action )); then # apply the selected action to all targets if [[ ! -z $target ]]; then @@ -854,16 +1353,15 @@ builder_parse() { shift builder_dep_parent="$1" ;; - --builder-deps-built) - # internal use parameter for dependency builds - path to dependency tracking file - shift - _builder_deps_built="$1" + --builder-child) + _builder_is_child=0 ;; --builder-report-dependencies) # internal reporting function, ignores all other parameters _builder_report_dependencies ;; *) + # script does not recognize anything of action or target form at this point. _builder_parameter_error "$0" parameter "$key" esac fi @@ -876,31 +1374,48 @@ builder_parse() { done fi - _builder_add_chosen_action_target_dependencies + # We only want to define internal dependencies after both builder_parse and builder_describe_outputs have been called + if _builder_has_function_been_called builder_describe_outputs; then + _builder_add_chosen_action_target_dependencies + fi - if $_builder_debug; then - echo "[DEBUG] Selected actions and targets:" + if $_builder_debug_internal; then + builder_echo_debug "Selected actions and targets:" for e in "${_builder_chosen_action_targets[@]}"; do - echo "* $e" + builder_echo_debug "* $e" done - echo - echo "[DEBUG] Selected options:" + builder_echo_debug + builder_echo_debug "Selected options:" for e in "${_builder_chosen_options[@]}"; do - echo "* $e" + builder_echo_debug "* $e" done fi if builder_is_dep_build; then - echo "[$THIS_SCRIPT_IDENTIFIER] dependency build, started by $builder_dep_parent" + builder_echo setmark "dependency build, started by $builder_dep_parent" + builder_echo grey "build.sh parameters: <${_params[@]}>" + if [[ -z ${_builder_deps_built+x} ]]; then + builder_die "FATAL ERROR: Expected '_builder_deps_built' variable to be set" + fi + elif builder_is_child_build; then + builder_echo setmark "child build, parameters: <${_params[@]}>" if [[ -z ${_builder_deps_built+x} ]]; then - echo "FATAL ERROR: Expected --builder-deps-built parameter" - exit 1 + builder_die "FATAL ERROR: Expected '_builder_deps_built' variable to be set" fi else - # This is a top-level invocation, not a dependency build, so we want to - # track which dependencies have been built, so they don't get built multiple - # times. - _builder_deps_built=`mktemp` + # This is a top-level invocation, so we want to track which dependencies + # have been built, so they don't get built multiple times. + builder_echo setmark "build.sh parameters: <${_params[@]}>" + if [[ ${#builder_extra_params[@]} -gt 0 ]]; then + builder_echo grey "build.sh extra parameters: <${builder_extra_params[@]}>" + fi + export _builder_deps_built=`mktemp` + fi + + if builder_is_debug_build; then + BUILDER_CONFIGURATION=debug + else + BUILDER_CONFIGURATION=release fi # Now that we've successfully parsed options adhering to the _builder spec, we may activate our @@ -952,7 +1467,7 @@ builder_display_usage() { echo "Actions: " for e in "${_builder_actions[@]}"; do - if [[ -v _builder_params[$e] ]]; then + if _builder_item_in_glob_array "$e" "${_builder_params[@]}"; then description="${_builder_params[$e]}" else description=$(_builder_get_default_description "$e") @@ -964,7 +1479,7 @@ builder_display_usage() { echo "Targets: " for e in "${_builder_targets[@]}"; do - if [[ -v _builder_params[$e] ]]; then + if _builder_item_in_glob_array "$e" "${_builder_params[@]}"; then description="${_builder_params[$e]}" else description=$(_builder_get_default_description "$e") @@ -1007,10 +1522,10 @@ builder_display_usage() { local c1=$BUILDER_TERM_START local c0=$BUILDER_TERM_END echo - echo "* Specify ${c1}action:target${c0} to run a specific ${c1}action${c0} against a specific ${c1}:target${c0}." - echo "* If ${c1}action${c0} is specified without a ${c1}target${c0} suffix, it will be applied to all ${c1}:target${c0}s." - echo "* If ${c1}:target${c0} is specified without an ${c1}action${c0} prefix, ${c1}$_builder_default_action:target${c0} will be inferred." - echo "* If no ${c1}action${c0}, ${c1}:target${c0}, or ${c1}action:target${c0} entries are specified, ${c1}$_builder_default_action${c0} will run on all ${c1}:target${c0}s." + echo -e "* Specify ${c1}action:target${c0} to run a specific ${c1}action${c0} against a specific ${c1}:target${c0}." + echo -e "* If ${c1}action${c0} is specified without a ${c1}target${c0} suffix, it will be applied to all ${c1}:target${c0}s." + echo -e "* If ${c1}:target${c0} is specified without an ${c1}action${c0} prefix, ${c1}$_builder_default_action:target${c0} will be inferred." + echo -e "* If no ${c1}action${c0}, ${c1}:target${c0}, or ${c1}action:target${c0} entries are specified, ${c1}$_builder_default_action${c0} will run on all ${c1}:target${c0}s." echo } @@ -1019,7 +1534,7 @@ builder_finish_action() { local action="$2" target action_name if [[ $action =~ : ]]; then - IFS=: read -r action target <<< $action + IFS=: read -r action target <<< "$action" target=":$target" else target=':*' @@ -1031,21 +1546,48 @@ builder_finish_action() { action_name="$action$target" fi - local scope="[$THIS_SCRIPT_IDENTIFIER] " + local matched_action="$action$target" - if [[ "$action$target" == "${_builder_current_action}" ]]; then + if [[ "$matched_action" == "${_builder_current_action}" ]]; then if [[ $result == success ]]; then - echo "${COLOR_GREEN}## $scope$action_name completed successfully${COLOR_RESET}" + # Sanity check: if there is a described output for this action, does the corresponding + # file or directory exist now? + if _builder_dep_output_defined $matched_action && ! _builder_dep_output_exists "$matched_action"; then + builder_echo warning "Expected output: '${_builder_dep_path[$matched_action]}'." + builder_echo warning "## $action_name completed successfully, but output does not exist" + else + builder_echo success "## $action_name completed successfully" + fi elif [[ $result == failure ]]; then - echo "${COLOR_RED}## $scope$action_name failed${COLOR_RESET}" + builder_echo error "## $action_name failed" else - echo "${COLOR_RED}## $scope$action_name failed with message: $result${COLOR_RESET}" + builder_echo error "## $action_name failed with message: $result" fi # Remove $action$target from the array; it is no longer a current action _builder_current_action= else - echo "${COLOR_YELLOW}## Warning: reporting result of $action_name but the action was never started!${COLOR_RESET}" + builder_echo warning "reporting result of $action_name but the action was never started!" + fi +} + +#------------------------------------------------------------------------------------------ +# Dependencies +#------------------------------------------------------------------------------------------ + +_builder_dep_output_defined() { + if [[ ! -z ${_builder_dep_path[$1]+x} ]]; then + return 0 + else + return 1 + fi +} + +_builder_dep_output_exists() { + if _builder_dep_output_defined $1 && [[ -e "$KEYMAN_ROOT/${_builder_dep_path[$1]}" ]]; then + return 0 + else + return 1 fi } @@ -1056,16 +1598,38 @@ _builder_should_build_dep() { local action_target="$1" local dep="$2" local related_actions=(${_builder_dep_related_actions[$dep]}) - # echo "bdra: ${_builder_dep_related_actions[@]}" - # echo "target: $action_target" - # echo "dep: $2" - # echo "ra: ${related_actions[@]}" + + if [[ $action_target =~ ^clean ]]; then + # don't attempt to build dependencies for a 'clean' action + return 1 + fi + if ! _builder_item_in_glob_array "$action_target" "${related_actions[@]}"; then return 1 fi return 0 } +# +# Removes a dependency from the list of available dependencies +# +# Parameters: +# $1 path to dependency +# +builder_remove_dep() { + local dependency="$1" i + dependency="`_builder_expand_relative_path "$dependency"`" + + for i in "${!_builder_deps[@]}"; do + if [[ ${_builder_deps[i]} = $dependency ]]; then + unset '_builder_deps[i]' + fi + done + + # rebuild the array to remove the empty item + _builder_deps=( "${_builder_deps[@]}" ) +} + # # Configure and build all dependencies # Later, may restrict by either action or target @@ -1082,7 +1646,7 @@ _builder_do_build_deps() { # Don't attempt to build dependencies that don't match the current # action:target (wildcards supported for matches here) if ! _builder_should_build_dep "$action_target" "$dep"; then - echo "[$THIS_SCRIPT_IDENTIFIER] Skipping dependency build $dep for $_builder_matched_action_name" + builder_echo "Skipping dependency $dep for $_builder_matched_action_name" continue fi @@ -1091,14 +1655,27 @@ _builder_do_build_deps() { continue fi - # TODO: add --debug as a standard builder parameter + dep_target= + if [[ ! -z ${_builder_dep_targets[$dep]+x} ]]; then + # TODO: in the future split _builder_dep_targets into comma-separated + # array for multiple targets for a dep? + dep_target=${_builder_dep_targets[$dep]} + fi + builder_set_module_has_been_built "$dep" - "$KEYMAN_ROOT/$dep/build.sh" configure build \ + "$KEYMAN_ROOT/$dep/build.sh" "configure$dep_target" "build$dep_target" \ $builder_verbose \ $builder_debug \ $_builder_build_deps \ - --builder-deps-built "$_builder_deps_built" \ - --builder-dep-parent "$THIS_SCRIPT_IDENTIFIER" + --builder-dep-parent "$THIS_SCRIPT_IDENTIFIER" && ( + if $_builder_debug_internal; then + builder_echo success "## Dependency $dep for $_builder_matched_action_name successfully" + fi + ) || ( + result=$? + builder_echo error "## Dependency failed with exit code $result" + exit $result + ) || exit $? # Required due to above subshell masking exit done } @@ -1112,13 +1689,20 @@ builder_is_dep_build() { return 1 } +# +# returns `0` if we are in a child script doing a build +# +builder_is_child_build() { + return $_builder_is_child +} + # # returns `0` if we should attempt to do quick builds in a dependency build, for # example skipping `tsc -b` where a parent may also do it; corresponds to the # `--deps` parameter (which is the default). # builder_is_quick_dep_build() { - if builder_is_dep_build && [[ $_builder_build_deps == --deps ]]; then + if [[ $_builder_build_deps == --deps ]]; then return 0 fi return 1 @@ -1129,7 +1713,7 @@ builder_is_quick_dep_build() { # corresponds to the `--force-deps`` parameter. # builder_is_full_dep_build() { - if builder_is_dep_build && [[ $_builder_build_deps == --force-deps ]]; then + if [[ $_builder_build_deps == --force-deps ]]; then return 0 fi return 1 @@ -1173,6 +1757,7 @@ builder_has_dependencies() { builder_has_module_been_built() { local module="$1" + if [[ -z ${_builder_deps_built+x} ]]; then # not in a builder context, so we assume a build is needed return 1 @@ -1217,6 +1802,19 @@ builder_set_module_has_been_built() { fi } +# +# Reports on all described dependencies, then exits +# used by builder-controls.sh +# +_builder_report_dependencies() { + echo "${_builder_deps[@]}" + exit 0 +} + +#------------------------------------------------------------------------------------------ +# Utility functions +#------------------------------------------------------------------------------------------ + # # returns `0` if we should be verbose in output # @@ -1230,7 +1828,7 @@ builder_verbose() { # # returns `0` if we are doing a debug build # -builder_debug() { +builder_is_debug_build() { if [[ $builder_debug == --debug ]]; then return 0 fi @@ -1238,15 +1836,44 @@ builder_debug() { } # -# Reports on all described dependencies, then exits -# used by builder-controls.sh +# Track whether functions have already been called; +# later we may use this to prevent multiple calls to, e.g. +# builder_describe # -_builder_report_dependencies() { - echo "${_builder_deps[@]}" - exit 0 + +_builder_function_calls=() + +_builder_record_function_call() { + local func=$1 + if _builder_has_function_been_called $1; then + # builder_die "ERROR: $func cannot be called more than once." + return 0 + fi + _builder_function_calls+=($1) +} + +_builder_has_function_been_called() { + local func=$1 + if _builder_item_in_array $1 "${_builder_function_calls[@]}"; then + return 0 + fi + return 1 } # # Initialize builder once all functions are declared # _builder_init +_builder_check_color "$@" + +# _builder_debug_internal flag can be used to emit verbose logs for builder itself, +# e.g.: +# _builder_debug_internal=true ./build.sh +# +if [ -z ${_builder_debug_internal+x} ]; then + _builder_debug_internal=false +fi + +if $_builder_debug_internal; then + builder_echo_debug "Command line: $0 $@" +fi From b3dd297e8173204e0c2e6adef93fe703fb0c9bd6 Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Thu, 10 Aug 2023 07:08:38 +0700 Subject: [PATCH 15/73] fix: slashes and pathing --- .htaccess | 20 ++++++++++++++------ Dockerfile | 3 ++- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/.htaccess b/.htaccess index 6d4b1f9e..3eb045d9 100644 --- a/.htaccess +++ b/.htaccess @@ -1,7 +1,14 @@ # This file is used when running with Apache. Adapted from web.config. # NOTE: this is not very well tested... +# We turn off automatic addition of slashes for directories because it +# interferes with the file extension removal for .php files. At the bottom of +# this file, we have a redirect rule to mimic the same behaviour, _after_ the +# relevant rewrite rules have been applied +DirectorySlash off + RewriteEngine on +RewriteBase / # Redirect http://keyman.com to https://keyman.com, # but only if on a live site (keyman.com) and not @@ -40,12 +47,8 @@ RedirectMatch "(?i)^/desktop(\/.*)?" "/windows$1" # TODO: Permanent redirects 301? - -# Stop processing dedicated keyboard landing pages -#RewriteRule "^keyboards/h/.*$" - [L] - # /keyboards/{install|download|share}/{id}/ to /keyboards/x/id -#RedirectMatch "^keyboards/(install|download|share)/([^/]+)/$" "/keyboards/$1/$2" +# RedirectMatch "^keyboards/(install|download|share)/([^/]+)/$" "/keyboards/$1/$2" RewriteRule "^keyboards/(install|download|share)/([^/]+)/$" "/keyboards/$1/$2" [R,L] # /keyboards/{id}/ to /keyboards/id @@ -184,7 +187,7 @@ RewriteRule "^(.+)$" "/_includes/includes/md/mdhost.php?file=$1.md" [END] # Rewrite file to file.php RewriteCond "%{DOCUMENT_ROOT}/$1.php" -f RewriteCond "%{DOCUMENT_ROOT}/$1.md" !-f -RewriteRule ="^(.+)$" "$1.php" [END] +RewriteRule "^(.+)$" "$1.php" [END] # Rewrite folder/ to folder/index.md RewriteCond "%{DOCUMENT_ROOT}/$1/index.md" -f @@ -194,3 +197,8 @@ RewriteRule "^(.+)/$" "/_includes/includes/md/mdhost.php?file=$1/index.md" [END] RewriteCond "%{DOCUMENT_ROOT}/$1/index.php" -f RewriteCond "%{DOCUMENT_ROOT}/$1/index.md" !-f RewriteRule "^(.+)/$" "$1/index.php" [END] + +# Finally, append the terminating slash for folders, given it is no longer +# done automatically because we put DirectorySlash off +RewriteCond %{REQUEST_FILENAME} -d +RewriteRule "^(.*)([^/])$" "$1$2/" [R] diff --git a/Dockerfile b/Dockerfile index 0f4d066d..0c27d13f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -20,9 +20,10 @@ RUN composer install # Site FROM php:7.4-apache COPY resources/keyman-site.conf /etc/apache2/conf-available/ +RUN cp /usr/local/etc/php/php.ini-production /usr/local/etc/php/php.ini RUN chown -R www-data:www-data /var/www/html/ COPY --from=composer-builder /composer/vendor /var/www/vendor -RUN a2enmod rewrite; a2enconf keyman-site +RUN a2enmod rewrite headers; a2enconf keyman-site # build.sh configure later needed to create link to vendor/ From 0c323a231f676c2ea965a5c8c6019830abd39156 Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Thu, 10 Aug 2023 07:09:45 +0700 Subject: [PATCH 16/73] fix: case insensitive parts of .htaccess --- .htaccess | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.htaccess b/.htaccess index 3eb045d9..5b0f3865 100644 --- a/.htaccess +++ b/.htaccess @@ -23,20 +23,20 @@ RewriteBase / # TODO: Add 301 permanent redirects, append query strings -# macosx and macos to mac" (ignore case) -RedirectMatch "(?i)^/(macosx|macos)\b(.*)$" "/mac$2" +# macosx and macos to mac (ignore case) +RedirectMatch "^(?i)/(macosx|macos)\b(.*)$" "/mac$2" # Redirect deprecated Google Plus link -RedirectMatch "(?i)^/plus.*" "/" +RedirectMatch "^(?i)/plus.*" "/" # /donate -> donate.keyman.com -RedirectMatch "(?i)^/donate(\/.*)?" "https://donate.keyman.com" +RedirectMatch "^(?i)/donate(\/.*)?" "https://donate.keyman.com" # /privacy -> SIL Privacy policy -RedirectMatch "(?i)^/privacy(\/.*)?" "https://software.sil.org/language-software-privacy-policy/" +RedirectMatch "^(?i)/privacy(\/.*)?" "https://software.sil.org/language-software-privacy-policy/" # desktop to windows -RedirectMatch "(?i)^/desktop(\/.*)?" "/windows$1" +RedirectMatch "^(?i)/desktop(\/.*)?" "/windows$1" # @@ -152,8 +152,8 @@ RedirectMatch "/yoruba(\/?)$" "/keyboards/sil_yoruba8" RedirectMatch "/ancient-greek(\/?)$" "/keyboards/h/greek" RedirectMatch "/(french|german|italian|spanish|swedish)(\/?)$" "/keyboards/h/eurolatin" -# dedicated-keyboard-landing pages -RedirectMatch "/(amharic|burmese|cameroon|ethiopic|eurolatin|greek|ipa|sinhala|tamil|tibetan|tigrigna|urdu)(\/.*)?$" "/keyboards/h/$1$2" +# dedicated-keyboard-landing pages TODO: [R=301] +RewriteRule "^(amharic|burmese|cameroon|ethiopic|eurolatin|greek|ipa|sinhala|tamil|tibetan|tigrigna|urdu)(/.*)?$" "/keyboards/h/$1$2" # # PHP and Markdown rewriting From fe94fe42531c7050199b2be41309ed73ddeac808 Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Thu, 10 Aug 2023 07:10:14 +0700 Subject: [PATCH 17/73] fix: Handle local api.keyman --- _common/KeymanHosts.php | 4 +++- cdn/dev/keyboard-search/search.js | 5 +++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/_common/KeymanHosts.php b/_common/KeymanHosts.php index abb28dbf..1fd4d753 100644 --- a/_common/KeymanHosts.php +++ b/_common/KeymanHosts.php @@ -119,7 +119,6 @@ function __construct() { // TODO: allow override of these with e.g. KEYMANHOSTS_API_KEYMAN_COM='https://api.keyman.com'; $this->s_keyman_com = "{$site_protocol}s.keyman.com{$site_suffix}"; $this->api_keyman_com = "{$site_protocol}api.keyman.com{$site_suffix}"; - // $this->api_keyman_com = "{$site_protocol}api.keyman.com"; //{$site_suffix}"; $this->help_keyman_com = "{$site_protocol}help.keyman.com{$site_suffix}"; $this->downloads_keyman_com = "{$site_protocol}downloads.keyman.com{$site_suffix}"; // $this->downloads_keyman_com = "{$site_protocol}downloads.keyman.com"; //{$site_suffix}"; @@ -127,6 +126,9 @@ function __construct() { $this->keymanweb_com = "{$site_protocol}keymanweb.com{$site_suffix}"; $this->r_keymanweb_com = "https://r.keymanweb.com"; /// local dev domain is usually not available } + // temp overrides + $this->api_keyman_com = "http://localhost:8098"; + $this->downloads_keyman_com = "https://downloads.keyman.com"; $this->blog_keyman_com_host = preg_replace('/^http(s)?:\/\/(.+)$/', '$2', $this->blog_keyman_com); $this->s_keyman_com_host = preg_replace('/^http(s)?:\/\/(.+)$/', '$2', $this->s_keyman_com); diff --git a/cdn/dev/keyboard-search/search.js b/cdn/dev/keyboard-search/search.js index d4180b5a..37a4adc7 100644 --- a/cdn/dev/keyboard-search/search.js +++ b/cdn/dev/keyboard-search/search.js @@ -85,8 +85,9 @@ function wrapSearch(localCounter, updateHistory) { return false; } - var base = location.protocol+'//api.'+location.host; // this works on test sites as well as live, assuming we use the host pattern "keyman.com[.local]" - + // this works on test sites as well as live, assuming we use the host pattern "keyman.com[.local]" + var base = (location.hostname != 'localhost') ? location.protocol+'//api.'+location.host : + 'http://localhost:8098'; var url = base+'/search/2.0?p='+page+'&q='+encodeURIComponent(stripCommonWords(q)); if(embed) { From e43eef54250b2eb3971def78dfaf63ed15131753 Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Thu, 10 Aug 2023 10:25:42 +0700 Subject: [PATCH 18/73] fix some keyboard searches --- .htaccess | 6 +++--- _common/KeymanHosts.php | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/.htaccess b/.htaccess index 5b0f3865..a4639b28 100644 --- a/.htaccess +++ b/.htaccess @@ -80,10 +80,10 @@ RewriteRule "^keyboards/download/([^/]+)$" "/keyboards/keyboard.php?id=$1" [L] RewriteRule "^keyboards/share/(^/]+)$" "/keyboards/share.php?id=$1" [L] # /keyboards/{id}.json to /keyboards/keyboard.json.php -RewriteRule "^keyboards/(.*)\.json$" "/keyboards/keyboard.json.php?id=$1" +RewriteRule "^keyboards/(?!keyboard.json)(.*)\.json$" "/keyboards/keyboard.json.php?id=$1" [L] # /keyboards/{id} to /keyboards/keyboard.php -RewriteRule "^keyboards/([^/]+)$" "/keyboards/keyboard.php?id=$1" [L] +RewriteRule "^keyboards/(?!install|keyboard|session|share)([^/]+)$" "/keyboards/keyboard.php?id=$1" [L,QSA] # @@ -91,7 +91,7 @@ RewriteRule "^keyboards/([^/]+)$" "/keyboards/keyboard.php?id=$1" [L] # # /keyboards?q=... to /keyboards/index.php -RewriteRule "^keyboards$" "/keyboards/index.php" [L] +# RewriteRule "^keyboards$" "/keyboards/index.php" [L] # /keyboards/languages to /keyboards/index.php RewriteRule "^keyboards/languages/(.*)" "/keyboards/index.php?q=l:id:$1" [L] diff --git a/_common/KeymanHosts.php b/_common/KeymanHosts.php index 1fd4d753..fe780f06 100644 --- a/_common/KeymanHosts.php +++ b/_common/KeymanHosts.php @@ -127,7 +127,8 @@ function __construct() { $this->r_keymanweb_com = "https://r.keymanweb.com"; /// local dev domain is usually not available } // temp overrides - $this->api_keyman_com = "http://localhost:8098"; + // https://docs.docker.com/desktop/networking/#use-cases-and-workarounds-for-all-platforms + $this->api_keyman_com = "http://host.docker.internal:8098"; $this->downloads_keyman_com = "https://downloads.keyman.com"; $this->blog_keyman_com_host = preg_replace('/^http(s)?:\/\/(.+)$/', '$2', $this->blog_keyman_com); From 3341164f48f38c90e11b3768c9fa6fd59bfa7f9a Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Thu, 10 Aug 2023 10:53:52 +0700 Subject: [PATCH 19/73] fix more keyboard links --- .htaccess | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.htaccess b/.htaccess index a4639b28..a8c365d1 100644 --- a/.htaccess +++ b/.htaccess @@ -83,7 +83,7 @@ RewriteRule "^keyboards/share/(^/]+)$" "/keyboards/share.php?id=$1" [L] RewriteRule "^keyboards/(?!keyboard.json)(.*)\.json$" "/keyboards/keyboard.json.php?id=$1" [L] # /keyboards/{id} to /keyboards/keyboard.php -RewriteRule "^keyboards/(?!install|keyboard|session|share)([^/]+)$" "/keyboards/keyboard.php?id=$1" [L,QSA] +RewriteRule "^keyboards/(?!index\.php|install|keyboard|session|share)([^/]+)$" "/keyboards/keyboard.php?id=$1" [L,QSA] # From e2cc050f6f588baf601752f1b4df9324a200eef5 Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Thu, 10 Aug 2023 16:12:00 +0700 Subject: [PATCH 20/73] fix: Redirects for Maltese and Rawang --- .htaccess | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.htaccess b/.htaccess index a8c365d1..494c0dbb 100644 --- a/.htaccess +++ b/.htaccess @@ -117,7 +117,7 @@ RedirectMatch "^/(?!iphone-and-ipad)(ios|iphone|ipad)(\/.*)?" "/iphone-and-ipad$ # Connect With Art landing page RedirectMatch "/connectwithart(\/|$)" "https://sites.google.com/sil.org/connectwithart/home" -# per-language landing pages +# per-language landing pages (maltese and rawang) RedirectMatch "/albanian(\/?)$" "/keyboards/basic_kbdal" RedirectMatch "/ancient-egyptian(\/?)$" "/keyboards/hieroglyphic" RedirectMatch "/ancient-hebrew(\/?)$" "/keyboards/galaxie_greek_hebrew_mnemonic" @@ -136,12 +136,12 @@ RedirectMatch "/igbo(\/?)$" "/keyboards/sil_nigeria_dot" RedirectMatch "/khmer(\/?)$" "/keyboards/khmer_angkor" RedirectMatch "/lao(\/?)$" "/keyboards/basic_kbdlao" RedirectMatch "/malayalam(\/?)$" "/keyboards/basic_kbdinmal" -RedirectMatch "/maltese(\/?)$" "/keyboards/maltese" +RedirectMatch "^/maltese(\/?)$" "/keyboards/maltese" RedirectMatch "/marathi(\/?)$" "/keyboards/basic_kbdinmar" RedirectMatch "/mongolian(\/?)$" "/keyboards/basic_kbdmon" RedirectMatch "/nepali(\/?)$" "/keyboards/basic_kbdnepr" RedirectMatch "/oriya(\/?)$" "/keyboards/basic_kbdinori" -RedirectMatch "/rawang(\/?)$" "/keyboards/rawang" +RedirectMatch "^/rawang(\/?)$" "/keyboards/rawang" RedirectMatch "/russian(\/?)$" "/keyboards/basic_kbdru" RedirectMatch "/serbian(\/?)$" "/keyboards/basic_kbdycc" RedirectMatch "/sindhi(\/?)$" "/keyboards/mbsindhi" From 4cc6d1cac0b61c6a3c37d8f862a7070fffadbff3 Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Fri, 11 Aug 2023 08:26:50 +0700 Subject: [PATCH 21/73] fix: cleanup go redirects --- go/.htaccess | 2 +- go/android/.htaccess | 4 ++-- go/developer/.htaccess | 2 +- go/ios/.htaccess | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go/.htaccess b/go/.htaccess index 271329fa..52438d69 100644 --- a/go/.htaccess +++ b/go/.htaccess @@ -13,7 +13,7 @@ RedirectMatch "/go/(([1-9][0-9])([.]?)([0-9]))/developer-help-(mobile|packages)( # download-model/keyboard package #RedirectMatch "/go/package/download/model/([^/]+)$" "https://keyman.com/go/package/download.php?type=model&id=$1" -RedirectMatch "/go/package/download/(model|keyboard)/([^\/]+)\/?$" "https://keyman2.com/go/package/download.php?type=$1&id=$2" +RedirectMatch "/go/package/download/(model|keyboard)/([^\/]+)\/?$" "https://keyman.com/go/package/download.php?type=$1&id=$2" # keyboard/id/share RedirectMatch "/go/keyboard/([^/?]+)/share$" "/keyboards/share/$1" diff --git a/go/android/.htaccess b/go/android/.htaccess index 16d5cec2..eb6c0f0f 100644 --- a/go/android/.htaccess +++ b/go/android/.htaccess @@ -2,7 +2,7 @@ # Links for Android 14.0 onward # /go/android/X.Y/download-keyboards/languages" -RedirectMatch "/go/android/([1-9][0-9]\.[0-9])/download-keyboards/languages/(.*)" "/keyboards/languages/$2?embed=android&embed_version=$1" +RedirectMatch "/go/android/([1-9][0-9]\.[0-9])/download-keyboards/languages/(.*)" "/keyboards/languages/$2?embed=android&embed_version=$1" # "/go/android/X.Y/download-keyboards" -RedirectMatch "/go/android/([1-9][0-9]\.[0-9])/download-keyboards" "/keyboards?embed=android&embed_version=$1" +RedirectMatch "/go/android/([1-9][0-9]\.[0-9])/download-keyboards" "/keyboards?embed=android&embed_version=$1" diff --git a/go/developer/.htaccess b/go/developer/.htaccess index a058071f..83b73028 100644 --- a/go/developer/.htaccess +++ b/go/developer/.htaccess @@ -45,7 +45,7 @@ RedirectMatch "/go/developer/([1-9][0-9]\.[0-9])/home" "/developer/" # "/go/developer/X.Y/ios-app" # see includes/appstore.php -RedirectMatch "/go/developer/([1-9][0-9]\.[0-9])/ios-app" "https://itunes.apple.com/us/app/keyman/id933676545?ls=1&mt=8" +RedirectMatch "/go/developer/([1-9][0-9]\.[0-9])/ios-app" "https://itunes.apple.com/us/app/keyman/id933676545?ls=1&mt=8" # "/go/developer/X.Y/android-app" diff --git a/go/ios/.htaccess b/go/ios/.htaccess index 53561877..7a1aaf0f 100644 --- a/go/ios/.htaccess +++ b/go/ios/.htaccess @@ -2,7 +2,7 @@ # Links for iOS 14.0 onward # "/go/ios/X.Y/download-keyboards/languages" -RedirectMatch "/go/ios/([1-9][0-9]\.[0-9])/download-keyboards/languages/(.*)" "/keyboards/languages/$2?embed=ios&embed_version=$1" +RedirectMatch "/go/ios/([1-9][0-9]\.[0-9])/download-keyboards/languages/(.*)" "/keyboards/languages/$2?embed=ios&embed_version=$1" # "/go/ios/X.Y/download-keyboards" -RedirectMatch "/go/ios/([1-9][0-9]\.[0-9])/download-keyboards" "/keyboards?embed=ios&embed_version=$1" +RedirectMatch "/go/ios/([1-9][0-9]\.[0-9])/download-keyboards" "/keyboards?embed=ios&embed_version=$1" From b71c494809b0b34957689da5bd0729b240a91bc4 Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Fri, 11 Aug 2023 10:41:19 +0700 Subject: [PATCH 22/73] chore: remove deprecated field data from keyboard_info usage Relates to keymanapp/keyman#9351. --- _includes/includes/ui/keyboard-details.php | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/_includes/includes/ui/keyboard-details.php b/_includes/includes/ui/keyboard-details.php index 455b4411..5d0e35b5 100644 --- a/_includes/includes/ui/keyboard-details.php +++ b/_includes/includes/ui/keyboard-details.php @@ -501,20 +501,6 @@ protected static function WriteKeyboardDetails() { - links) && sizeof(self::$keyboard->links) > 0) { ?> - - Links - - links as $link) { - $hurl = htmlentities($link->url); - $hname = htmlentities($link->name); - echo ""; - } - ?> - - - Supported Languages From b3cf144c44f7cf4fc54f1f225dd2fe9520a71242 Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Fri, 11 Aug 2023 12:33:18 +0700 Subject: [PATCH 23/73] fix: Move downloads/releases redirects --- .htaccess | 10 ++++++++++ downloads/releases/.htaccess | 10 ---------- 2 files changed, 10 insertions(+), 10 deletions(-) delete mode 100644 downloads/releases/.htaccess diff --git a/.htaccess b/.htaccess index 494c0dbb..0114f309 100644 --- a/.htaccess +++ b/.htaccess @@ -38,6 +38,16 @@ RedirectMatch "^(?i)/privacy(\/.*)?" "https://software.sil.org/language-software # desktop to windows RedirectMatch "^(?i)/desktop(\/.*)?" "/windows$1" +# releases-tier/download" +# note: the tier is currently ignored +RewriteRule "^downloads/releases/(alpha|beta|stable)/(.+)$" "/downloads/releases/_version_downloads.php?tier=$1&version=$2" [R,END] + +# "releases-download" +RewriteRule ^downloads/releases/(?!_version_downloads\b)(.+)$ /downloads/releases/_version_downloads.php?version=$1 [R,END] + +# index" +RedirectMatch "^downloads/releases/?$" "/downloads" + # # Keyboard landing pages (TODO) diff --git a/downloads/releases/.htaccess b/downloads/releases/.htaccess deleted file mode 100644 index 11d14944..00000000 --- a/downloads/releases/.htaccess +++ /dev/null @@ -1,10 +0,0 @@ - -# releases-tier/download" -# note: the tier is currently ignored -RedirectMatch "/downloads/releases/(alpha|beta|stable)/(.+)$" "/downloads/releases/_version_downloads.php?tier=$1&version=$2" - -# "releases-download" -RedirectMatch "/downloads/releases/(?!_version_downloads.php)(.+)$" "/downloads/releases/_version_downloads.php?version=$1" - -# index" -RedirectMatch "/downloads/releases$" "/downloads/" From 544334e1044a9eacf72200f89f4f0b86e3de9e12 Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Thu, 17 Aug 2023 10:52:09 +0700 Subject: [PATCH 24/73] fix: revert hosting changes --- _common/KeymanHosts.php | 9 ++------- cdn/dev/keyboard-search/search.js | 4 +--- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/_common/KeymanHosts.php b/_common/KeymanHosts.php index fe780f06..2b729b9c 100644 --- a/_common/KeymanHosts.php +++ b/_common/KeymanHosts.php @@ -88,7 +88,7 @@ function __construct() { break; case KeymanHosts::TIER_DEVELOPMENT: $site_suffix = '.local'; - $site_protocol = 'https://'; + $site_protocol = 'http://'; break; } @@ -120,16 +120,11 @@ function __construct() { $this->s_keyman_com = "{$site_protocol}s.keyman.com{$site_suffix}"; $this->api_keyman_com = "{$site_protocol}api.keyman.com{$site_suffix}"; $this->help_keyman_com = "{$site_protocol}help.keyman.com{$site_suffix}"; - $this->downloads_keyman_com = "{$site_protocol}downloads.keyman.com{$site_suffix}"; - // $this->downloads_keyman_com = "{$site_protocol}downloads.keyman.com"; //{$site_suffix}"; + $this->downloads_keyman_com = "https://downloads.keyman.com"; // local dev domain is usually not available $this->keyman_com = "{$site_protocol}keyman.com{$site_suffix}"; $this->keymanweb_com = "{$site_protocol}keymanweb.com{$site_suffix}"; $this->r_keymanweb_com = "https://r.keymanweb.com"; /// local dev domain is usually not available } - // temp overrides - // https://docs.docker.com/desktop/networking/#use-cases-and-workarounds-for-all-platforms - $this->api_keyman_com = "http://host.docker.internal:8098"; - $this->downloads_keyman_com = "https://downloads.keyman.com"; $this->blog_keyman_com_host = preg_replace('/^http(s)?:\/\/(.+)$/', '$2', $this->blog_keyman_com); $this->s_keyman_com_host = preg_replace('/^http(s)?:\/\/(.+)$/', '$2', $this->s_keyman_com); diff --git a/cdn/dev/keyboard-search/search.js b/cdn/dev/keyboard-search/search.js index 37a4adc7..b1db5262 100644 --- a/cdn/dev/keyboard-search/search.js +++ b/cdn/dev/keyboard-search/search.js @@ -85,9 +85,7 @@ function wrapSearch(localCounter, updateHistory) { return false; } - // this works on test sites as well as live, assuming we use the host pattern "keyman.com[.local]" - var base = (location.hostname != 'localhost') ? location.protocol+'//api.'+location.host : - 'http://localhost:8098'; + var base = location.protocol+'//api.'+location.host; // this works on test sites as well as live, assuming we use the host pattern "keyman.com[.local]" var url = base+'/search/2.0?p='+page+'&q='+encodeURIComponent(stripCommonWords(q)); if(embed) { From 3c9abe14fbb49d19bd3082081cfaf3ecf00cd82b Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Tue, 22 Aug 2023 08:23:33 +0700 Subject: [PATCH 25/73] fix: Use .localhost instead of .local --- _common/KeymanHosts.php | 4 ++-- _common/KeymanSentry.php | 4 ++-- _includes/2020/templates/Head.php | 2 +- cdn/dev/keyboard-search/search.js | 2 +- cdn/dev/legacy-keyboard-search/search.js | 2 +- composer.json | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/_common/KeymanHosts.php b/_common/KeymanHosts.php index 2b729b9c..a8361d9e 100644 --- a/_common/KeymanHosts.php +++ b/_common/KeymanHosts.php @@ -5,7 +5,7 @@ class KeymanHosts { // Four tiers. These use the following rough patterns: - // * development = [x.]keyman.com.local + // * development = [x.]keyman.com.localhost // * Staging = [x.]keyman-staging.com // * Production = [x.]keyman.com // * Test = GitHub actions, localhost:8888 (uses staging tier for other hosts) @@ -87,7 +87,7 @@ function __construct() { $site_protocol = 'http://'; break; case KeymanHosts::TIER_DEVELOPMENT: - $site_suffix = '.local'; + $site_suffix = '.localhost'; $site_protocol = 'http://'; break; } diff --git a/_common/KeymanSentry.php b/_common/KeymanSentry.php index 7358d323..b69efc5b 100644 --- a/_common/KeymanSentry.php +++ b/_common/KeymanSentry.php @@ -8,8 +8,8 @@ static function init($dsn) { if(isset($_SERVER['SERVER_NAME'])) { // running from web server $host = $_SERVER['SERVER_NAME']; - if(preg_match('/\.local$/', $host)) - // If the host name is, e.g. api.keyman.com.local, then we'll assume this is a development environment + if(preg_match('/\.localhost$/', $host)) + // If the host name is, e.g. api.keyman.com.localhost, then we'll assume this is a development environment $environment = 'development'; else if(preg_match('/(^|\.)keyman-staging\.com$/', $host)) $environment = 'staging'; diff --git a/_includes/2020/templates/Head.php b/_includes/2020/templates/Head.php index e81ea1cd..f9a4df0e 100644 --- a/_includes/2020/templates/Head.php +++ b/_includes/2020/templates/Head.php @@ -44,7 +44,7 @@ static function render($fields = []) { diff --git a/cdn/dev/keyboard-search/search.js b/cdn/dev/keyboard-search/search.js index b1db5262..3663ef00 100644 --- a/cdn/dev/keyboard-search/search.js +++ b/cdn/dev/keyboard-search/search.js @@ -85,7 +85,7 @@ function wrapSearch(localCounter, updateHistory) { return false; } - var base = location.protocol+'//api.'+location.host; // this works on test sites as well as live, assuming we use the host pattern "keyman.com[.local]" + var base = location.protocol+'//api.'+location.host; // this works on test sites as well as live, assuming we use the host pattern "keyman.com[.localhost]" var url = base+'/search/2.0?p='+page+'&q='+encodeURIComponent(stripCommonWords(q)); if(embed) { diff --git a/cdn/dev/legacy-keyboard-search/search.js b/cdn/dev/legacy-keyboard-search/search.js index abe16c1e..0de21f64 100644 --- a/cdn/dev/legacy-keyboard-search/search.js +++ b/cdn/dev/legacy-keyboard-search/search.js @@ -219,7 +219,7 @@ function wrapSearch(localCounter, updateHistory) { var base = location.host === 'staging-keyman-com.azurewebsites.net' ? location.protocol+'//staging-api-keyman-com.azurewebsites.net' : - location.protocol+'//api.'+location.host; // this works on test sites as well as live, assuming we use the host pattern "keyman.com[.local]" + location.protocol+'//api.'+location.host; // this works on test sites as well as live, assuming we use the host pattern "keyman.com[.localhost]" var url = base+'/search?q='+encodeURIComponent(q); diff --git a/composer.json b/composer.json index dee4ca9b..28f421e2 100644 --- a/composer.json +++ b/composer.json @@ -12,7 +12,7 @@ "test": "vendor\\bin\\phpunit --testdox", "check-links": [ "Composer\\Config::disableProcessTimeout", - "npx broken-link-checker http://keyman.com.local --ordered --recursive --host-requests 10 -e --filter-level 3" + "npx broken-link-checker http://keyman.com.localhost --ordered --recursive --host-requests 10 -e --filter-level 3" ], "lint": "find . -name '*.php' | grep -v '/vendor/' | xargs -n 1 -d '\\n' php -l" } From bc1e2f1075d73fc6baf477039cb90e54b20aa17f Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Tue, 22 Aug 2023 10:10:03 +0700 Subject: [PATCH 26/73] fix: Keep host.docker.internal for Dev sites --- .htaccess | 10 +++++----- _common/KeymanHosts.php | 9 +++++++++ 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/.htaccess b/.htaccess index 0114f309..dc8a2e01 100644 --- a/.htaccess +++ b/.htaccess @@ -38,14 +38,14 @@ RedirectMatch "^(?i)/privacy(\/.*)?" "https://software.sil.org/language-software # desktop to windows RedirectMatch "^(?i)/desktop(\/.*)?" "/windows$1" -# releases-tier/download" +# releases-tier/download # note: the tier is currently ignored RewriteRule "^downloads/releases/(alpha|beta|stable)/(.+)$" "/downloads/releases/_version_downloads.php?tier=$1&version=$2" [R,END] -# "releases-download" -RewriteRule ^downloads/releases/(?!_version_downloads\b)(.+)$ /downloads/releases/_version_downloads.php?version=$1 [R,END] +# releases-download +RewriteRule "^downloads/releases/(?!_version_downloads\b)(.+)$" "/downloads/releases/_version_downloads.php?version=$1" [R,END] -# index" +# index RedirectMatch "^downloads/releases/?$" "/downloads" @@ -71,7 +71,7 @@ RedirectMatch "^keyboards/$" "/keyboards" RedirectMatch "^keyboards/(?!install|download|share)/share(/?)$" "/keyboards/share/$1" # /keyboard/{content} to /keyboards/... -RedirectMatch "/keyboard(/.*)$" "/keyboards$1" +RewriteRule "^keyboard(/.*)$" "/keyboards$1" [L] # # Install | Download | Share | bare | .json --> diff --git a/_common/KeymanHosts.php b/_common/KeymanHosts.php index a8361d9e..6cbe2257 100644 --- a/_common/KeymanHosts.php +++ b/_common/KeymanHosts.php @@ -115,6 +115,15 @@ function __construct() { $this->keyman_com = "https://keyman.com"; $this->keymanweb_com = "https://keymanweb.com"; $this->r_keymanweb_com = "https://r.keymanweb.com"; + } else if($this->tier == KeymanHosts::TIER_DEVELOPMENT) { + // Locally running sites via Docker need to access "host.docker.internal:[port]" + $this->s_keyman_com = "{$site_protocol}s.keyman.com{$site_suffix}"; + $this->api_keyman_com = "http://host.docker.internal:8098"; + $this->help_keyman_com = "http://host.docker.internal:8055"; + $this->downloads_keyman_com = "https://downloads.keyman.com"; // local dev domain is usually not available + $this->keyman_com = "http://host.docker.internal:8053"; + $this->keymanweb_com = "http://host.docker.internal:8057"; + $this->r_keymanweb_com = "https://r.keymanweb.com"; /// local dev domain is usually not available } else { // TODO: allow override of these with e.g. KEYMANHOSTS_API_KEYMAN_COM='https://api.keyman.com'; $this->s_keyman_com = "{$site_protocol}s.keyman.com{$site_suffix}"; From c76ee81da1d34281dd0c82000d60910033ec27b3 Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Tue, 22 Aug 2023 10:42:12 +0700 Subject: [PATCH 27/73] chore: add msg about invalid tier --- _common/KeymanHosts.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/_common/KeymanHosts.php b/_common/KeymanHosts.php index 6cbe2257..2f44e11e 100644 --- a/_common/KeymanHosts.php +++ b/_common/KeymanHosts.php @@ -90,6 +90,8 @@ function __construct() { $site_suffix = '.localhost'; $site_protocol = 'http://'; break; + default: + die("tier is '$this->tier' which is invalid\n"); } $this->blog_keyman_com = "https://blog.keyman.com"; From 3562a1a327a55cf8583101f98280c9cd5a79de69 Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Mon, 18 Sep 2023 09:40:02 +0700 Subject: [PATCH 28/73] chore: Use port 8058 for api.keyman.com.localhost --- _common/KeymanHosts.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_common/KeymanHosts.php b/_common/KeymanHosts.php index 2f44e11e..aca31c24 100644 --- a/_common/KeymanHosts.php +++ b/_common/KeymanHosts.php @@ -120,7 +120,7 @@ function __construct() { } else if($this->tier == KeymanHosts::TIER_DEVELOPMENT) { // Locally running sites via Docker need to access "host.docker.internal:[port]" $this->s_keyman_com = "{$site_protocol}s.keyman.com{$site_suffix}"; - $this->api_keyman_com = "http://host.docker.internal:8098"; + $this->api_keyman_com = "http://host.docker.internal:8058"; $this->help_keyman_com = "http://host.docker.internal:8055"; $this->downloads_keyman_com = "https://downloads.keyman.com"; // local dev domain is usually not available $this->keyman_com = "http://host.docker.internal:8053"; From c64d5fb0a635909b88fd5563afc3206fcdb5bc84 Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Mon, 18 Sep 2023 09:55:40 +0700 Subject: [PATCH 29/73] chore: Standardize keyboard redirects --- .htaccess | 70 +++++++++++++++++++++++++++---------------------------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/.htaccess b/.htaccess index dc8a2e01..3c873826 100644 --- a/.htaccess +++ b/.htaccess @@ -127,43 +127,43 @@ RedirectMatch "^/(?!iphone-and-ipad)(ios|iphone|ipad)(\/.*)?" "/iphone-and-ipad$ # Connect With Art landing page RedirectMatch "/connectwithart(\/|$)" "https://sites.google.com/sil.org/connectwithart/home" -# per-language landing pages (maltese and rawang) -RedirectMatch "/albanian(\/?)$" "/keyboards/basic_kbdal" -RedirectMatch "/ancient-egyptian(\/?)$" "/keyboards/hieroglyphic" -RedirectMatch "/ancient-hebrew(\/?)$" "/keyboards/galaxie_greek_hebrew_mnemonic" -RedirectMatch "/arabic(\/?)$" "/keyboards/basic_kbda1" -RedirectMatch "/assamese(\/?)$" "/keyboards/isis_bangla" -RedirectMatch "/basic_kbdsn1(\/?)$" "/keyboards/basic_kbdsn1" -RedirectMatch "/bengali(\/?)$" "/keyboards/basic_kbdinbe2" -RedirectMatch "/cherokee(\/?)$" "/keyboards/cherokee6" -RedirectMatch "/cheyenne(\/?)$" "/keyboards/sil_cheyenne" -RedirectMatch "/dinka(\/?)$" "/keyboards/el_dinka" -RedirectMatch "/dutch(\/?)$" "/keyboards/basic_kbdne" -RedirectMatch "/farsi(\/?)$" "/keyboards/farsi_unicode" -RedirectMatch "/hebrew(\/?)$" "/keyboards/basic_kbdheb" -RedirectMatch "/hindi(\/?)$" "/keyboards/basic_kbdindev" -RedirectMatch "/igbo(\/?)$" "/keyboards/sil_nigeria_dot" -RedirectMatch "/khmer(\/?)$" "/keyboards/khmer_angkor" -RedirectMatch "/lao(\/?)$" "/keyboards/basic_kbdlao" -RedirectMatch "/malayalam(\/?)$" "/keyboards/basic_kbdinmal" -RedirectMatch "^/maltese(\/?)$" "/keyboards/maltese" -RedirectMatch "/marathi(\/?)$" "/keyboards/basic_kbdinmar" -RedirectMatch "/mongolian(\/?)$" "/keyboards/basic_kbdmon" -RedirectMatch "/nepali(\/?)$" "/keyboards/basic_kbdnepr" -RedirectMatch "/oriya(\/?)$" "/keyboards/basic_kbdinori" -RedirectMatch "^/rawang(\/?)$" "/keyboards/rawang" -RedirectMatch "/russian(\/?)$" "/keyboards/basic_kbdru" -RedirectMatch "/serbian(\/?)$" "/keyboards/basic_kbdycc" -RedirectMatch "/sindhi(\/?)$" "/keyboards/mbsindhi" -RedirectMatch "/thai(\/?)$" "/keyboards/thai-uni" -RedirectMatch "/yiddish(\/?)$" "/keyboards/yiddish_pasekh" -RedirectMatch "/yoruba(\/?)$" "/keyboards/sil_yoruba8" - -RedirectMatch "/ancient-greek(\/?)$" "/keyboards/h/greek" -RedirectMatch "/(french|german|italian|spanish|swedish)(\/?)$" "/keyboards/h/eurolatin" +# per-language landing pages +RedirectMatch "^/albanian(/?)$" "/keyboards/basic_kbdal" +RedirectMatch "^/ancient-egyptian(/?)$" "/keyboards/hieroglyphic" +RedirectMatch "^/ancient-hebrew(/?)$" "/keyboards/galaxie_greek_hebrew_mnemonic" +RedirectMatch "^/arabic(/?)$" "/keyboards/basic_kbda1" +RedirectMatch "^/assamese(/?)$" "/keyboards/isis_bangla" +RedirectMatch "^/basic_kbdsn1(/?)$" "/keyboards/basic_kbdsn1" +RedirectMatch "^/bengali(/?)$" "/keyboards/basic_kbdinbe2" +RedirectMatch "^/cherokee(/?)$" "/keyboards/cherokee6" +RedirectMatch "^/cheyenne(/?)$" "/keyboards/sil_cheyenne" +RedirectMatch "^/dinka(/?)$" "/keyboards/el_dinka" +RedirectMatch "^/dutch(/?)$" "/keyboards/basic_kbdne" +RedirectMatch "^/farsi(/?)$" "/keyboards/farsi_unicode" +RedirectMatch "^/hebrew(/?)$" "/keyboards/basic_kbdheb" +RedirectMatch "^/hindi(/?)$" "/keyboards/basic_kbdindev" +RedirectMatch "^/igbo(/?)$" "/keyboards/sil_nigeria_dot" +RedirectMatch "^/khmer(/?)$" "/keyboards/khmer_angkor" +RedirectMatch "^/lao(/?)$" "/keyboards/basic_kbdlao" +RedirectMatch "^/malayalam(/?)$" "/keyboards/basic_kbdinmal" +RedirectMatch "^/maltese(/?)$" "/keyboards/maltese" +RedirectMatch "^/marathi(/?)$" "/keyboards/basic_kbdinmar" +RedirectMatch "^/mongolian(/?)$" "/keyboards/basic_kbdmon" +RedirectMatch "^/nepali(/?)$" "/keyboards/basic_kbdnepr" +RedirectMatch "^/oriya(/?)$" "/keyboards/basic_kbdinori" +RedirectMatch "^/rawang(/?)$" "/keyboards/rawang" +RedirectMatch "^/russian(/?)$" "/keyboards/basic_kbdru" +RedirectMatch "^/serbian(/?)$" "/keyboards/basic_kbdycc" +RedirectMatch "^/sindhi(/?)$" "/keyboards/mbsindhi" +RedirectMatch "^/thai(/?)$" "/keyboards/thai-uni" +RedirectMatch "^/yiddish(/?)$" "/keyboards/yiddish_pasekh" +RedirectMatch "^/yoruba(/?)$" "/keyboards/sil_yoruba8" + +RedirectMatch "^/ancient-greek(/?)$" "/keyboards/h/greek" +RedirectMatch "^/(french|german|italian|spanish|swedish)(/?)$" "/keyboards/h/eurolatin" # dedicated-keyboard-landing pages TODO: [R=301] -RewriteRule "^(amharic|burmese|cameroon|ethiopic|eurolatin|greek|ipa|sinhala|tamil|tibetan|tigrigna|urdu)(/.*)?$" "/keyboards/h/$1$2" +RedirectMatch "^/(amharic|burmese|cameroon|ethiopic|eurolatin|greek|ipa|sinhala|tamil|tibetan|tigrigna|urdu)(/.*)?$" "/keyboards/h/$1$2" # # PHP and Markdown rewriting From 88f78a5c7c0f120045e0ce9ff14ad35e6c0224aa Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Fri, 22 Sep 2023 08:05:48 +0700 Subject: [PATCH 30/73] chore: Update site_suffix with KEYMAN_COM_PROXY_PORT --- _common/KeymanHosts.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/_common/KeymanHosts.php b/_common/KeymanHosts.php index aca31c24..82affc9f 100644 --- a/_common/KeymanHosts.php +++ b/_common/KeymanHosts.php @@ -94,6 +94,11 @@ function __construct() { die("tier is '$this->tier' which is invalid\n"); } + // Append reverse-proxy port + if (isset($_SERVER['KEYMAN_COM_PROXY_PORT'])) { + $site_suffix .= ':'.$_SERVER['KEYMAN_COM_PROXY_PORT']; + } + $this->blog_keyman_com = "https://blog.keyman.com"; $this->donate_keyman_com = "https://donate.keyman.com"; $this->translate_keyman_com = "https://translate.keyman.com"; From 6cfe1b16fd690e637be55519d1cc0e9665e9cbff Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Wed, 23 Aug 2023 13:11:10 +0700 Subject: [PATCH 31/73] fix: Update ci.yml to run with Docker --- .github/workflows/ci.yml | 119 ++++++++------------------------------- Dockerfile | 2 - _common/KeymanHosts.php | 2 +- build.sh | 14 ++--- 4 files changed, 33 insertions(+), 104 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index edaececb..4513355e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,92 +1,25 @@ name: CI -on: [pull_request] - +on: + [pull_request] jobs: build-test: - runs-on: windows-latest + runs-on: ubuntu-20.04 env: KEYMANHOSTS_TIER: TIER_TEST steps: - name: Checkout - uses: actions/checkout@v2 - - - name: Setup PHP 7.4 - uses: shivammathur/setup-php@6972aed899fa2dd4016a7e314c46e6902bcafb7b - with: - php-version: '7.4' - extensions: curl, intl, mbstring, openssl - coverage: none - env: - fail-fast: true - - # - # Configure IIS and setup site for running unit tests - # * Installs IIS, CGI extensions, URLRewrite and configures to connect to PHP - # * Sets up http://127.0.0.1:8888 as host for tests - # * Enables detailed error reporting - # - - name: Download and install IIS and setup a local website - shell: powershell - run: | - Enable-WindowsOptionalFeature -Online -FeatureName IIS-WebServerRole -NoRestart - Enable-WindowsOptionalFeature -Online -FeatureName IIS-WebServer -NoRestart - Enable-WindowsOptionalFeature -Online -FeatureName IIS-CGI -NoRestart - Enable-WindowsOptionalFeature -Online -FeatureName IIS-ISAPIExtensions -NoRestart - Enable-WindowsOptionalFeature -Online -FeatureName IIS-ISAPIFilter -NoRestart - Enable-WindowsOptionalFeature -Online -FeatureName IIS-StaticContent -NoRestart - Enable-WindowsOptionalFeature -Online -FeatureName IIS-DefaultDocument -NoRestart - Enable-WindowsOptionalFeature -Online -FeatureName IIS-CommonHttpFeatures -NoRestart - Enable-WindowsOptionalFeature -Online -FeatureName IIS-HttpRedirect -NoRestart - Enable-WindowsOptionalFeature -Online -FeatureName IIS-DirectoryBrowsing -NoRestart - Enable-WindowsOptionalFeature -Online -FeatureName IIS-HttpErrors -NoRestart - choco install --no-progress urlrewrite - Import-Module WebAdministration - New-WebAppPool -name "NewWebSiteAppPool" -force - New-WebSite -name "NewWebSite" -PhysicalPath "$ENV:GITHUB_WORKSPACE" -ApplicationPool "NewWebSiteAppPool" -port 8888 -force - Set-WebConfigurationproperty -filter "system.webServer/httpErrors" -pspath "MACHINE/WEBROOT/APPHOST" -name errorMode -value Detailed - Add-WebConfigurationProperty //defaultDocument/files "IIS:\sites\NewWebSite" -AtIndex 0 -Name collection -Value "index.php" - Add-WebConfigurationProperty //defaultDocument/files "IIS:\sites\NewWebSite" -AtIndex 0 -Name collection -Value "index.md" - - mkdir c:\tools\php\tmp - Add-Content -path c:\tools\php\php.ini -value '',"error_log = $ENV:GITHUB_WORKSPACE\php_errors.log","session.save_path = $ENV:GITHUB_WORKSPACE\.phpsessions","error_reporting = E_ALL","display_errors = On","display_startup_errors = On","html_errors = Off","sys_temp_dir = c:\tools\php\tmp","upload_tmp_dir = c:\tools\php\tmp" - mkdir $ENV:GITHUB_WORKSPACE\.phpsessions - - # - # This step configures FastCGI according to the documentation at https://www.php.net/manual/en/install.windows.manual.php - # This alternative doesn't work: New-WebHandler -name "PHP" -Path *.php -Modules FastCgiModule -ScriptProcessor "c:\tools\php\php-cgi.exe" -Verb 'GET,POST' -Force - # - - name: Setup FastCGI - shell: cmd - run: | - set phpdir=c:\tools - set phppath=php + uses: actions/checkout@v3.5.2 - REM Clear current PHP handlers - %windir%\system32\inetsrv\appcmd clear config /section:system.webServer/fastCGI - %windir%\system32\inetsrv\appcmd set config /section:system.webServer/handlers /-[name='PHP_via_FastCGI'] - - REM Set up the PHP handler - %windir%\system32\inetsrv\appcmd set config /section:system.webServer/fastCGI /+[fullPath='%phpdir%\%phppath%\php-cgi.exe'] - %windir%\system32\inetsrv\appcmd set config /section:system.webServer/handlers /+[name='PHP_via_FastCGI',path='*.php',verb='*',modules='FastCgiModule',scriptProcessor='%phpdir%\%phppath%\php-cgi.exe',resourceType='Unspecified'] - %windir%\system32\inetsrv\appcmd set config /section:system.webServer/handlers /accessPolicy:Read,Script - - REM Configure FastCGI Variables - %windir%\system32\inetsrv\appcmd set config -section:system.webServer/fastCgi /[fullPath='%phpdir%\%phppath%\php-cgi.exe'].instanceMaxRequests:10000 - %windir%\system32\inetsrv\appcmd.exe set config -section:system.webServer/fastCgi /+"[fullPath='%phpdir%\%phppath%\php-cgi.exe'].environmentVariables.[name='PHP_FCGI_MAX_REQUESTS',value='10000']" - %windir%\system32\inetsrv\appcmd.exe set config -section:system.webServer/fastCgi /+"[fullPath='%phpdir%\%phppath%\php-cgi.exe'].environmentVariables.[name='PHPRC',value='%phpdir%\%phppath%\php.ini']" - - # - # Install website PHP dependencies - # - - name: Install dependencies - shell: cmd + - name: Build the docker image for keyman.com app + shell: bash run: | - echo TIER_TEST > tier.txt - composer install --no-progress - npm install + echo "TIER_TEST" > tier.txt + ./build.sh build start + env: + fail-fast: true # # Finally, run the tests @@ -99,24 +32,22 @@ jobs: - name: Check broken links shell: bash run: | - ( set +e; set +o pipefail; npx broken-link-checker http://localhost:8888 --ordered --recursive --host-requests 50 -e --filter-level 3 | grep -E "BROKEN|Getting links from" | grep -B 1 "BROKEN"; exit ${PIPESTATUS[0]} ) + set +e; + set +o pipefail; + npx broken-link-checker http://localhost:8053 --ordered --recursive --host-requests 50 -e --filter-level 3 | \ + grep -E "BROKEN|Getting links from" | \ + grep -B 1 "BROKEN" + exit ${PIPESTATUS[0]} - name: Check PHP errors shell: bash run: | - ( set +e; set +o pipefail; [ -f php_errors.log ] && echo 'PHP reported errors or warnings; see log below' && exit 1 || ( echo 'No PHP errors found' && exit 0 ) ) - # - # If any of the tests fail, let's grab a bit more detail on the environment - # - - name: Report errors - if: ${{ failure() }} - shell: bash - run: | - echo "--- tier.txt ---" - cat tier.txt - echo "--- PHP Errors ---" - [ -f php_errors.log ] && cat php_errors.log - echo "--- Contents of /keyboards/khmer_angkor ---" - curl http://localhost:8888/keyboards/khmer_angkor - echo "--- PHPInfo ---" - php -r 'phpinfo();' + CONTAINER=`docker container ls -l -q` + if docker container logs $CONTAINER 2>&1 | grep -q 'php7'; then + echo 'PHP reported errors or warnings:' + docker container logs $CONTAINER 2>&1 | grep 'php7' + exit 1 + else + echo 'No PHP errors found' + exit 0 + fi diff --git a/Dockerfile b/Dockerfile index 0c27d13f..4a37f3c9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -25,5 +25,3 @@ RUN chown -R www-data:www-data /var/www/html/ COPY --from=composer-builder /composer/vendor /var/www/vendor RUN a2enmod rewrite headers; a2enconf keyman-site - -# build.sh configure later needed to create link to vendor/ diff --git a/_common/KeymanHosts.php b/_common/KeymanHosts.php index 82affc9f..b967eb4e 100644 --- a/_common/KeymanHosts.php +++ b/_common/KeymanHosts.php @@ -119,7 +119,7 @@ function __construct() { $this->api_keyman_com = "https://api.keyman.com"; $this->help_keyman_com = "https://help.keyman.com"; $this->downloads_keyman_com = "https://downloads.keyman.com"; - $this->keyman_com = "https://keyman.com"; + $this->keyman_com = "http://host.docker.internal:8053"; // Unique for keyman.com $this->keymanweb_com = "https://keymanweb.com"; $this->r_keymanweb_com = "https://r.keymanweb.com"; } else if($this->tier == KeymanHosts::TIER_DEVELOPMENT) { diff --git a/build.sh b/build.sh index f51cea58..6562ef38 100755 --- a/build.sh +++ b/build.sh @@ -69,11 +69,8 @@ if builder_start_action clean; then builder_finish_action success clean fi -if builder_start_action stop; then - # Stop the Docker container - _stop_docker_container - builder_finish_action success stop -fi +# Stop the Docker container +builder_run_action stop _stop_docker_container if builder_start_action build; then # Download docker image. --mount option requires BuildKit @@ -125,7 +122,10 @@ fi if builder_start_action test; then # TODO: lint tests - composer check-docker-links - + set +e; \ + set +o pipefail; \ + npx broken-link-checker http://localhost:8053 --ordered --recursive --host-requests 50 -e --filter-level 3 | \ + grep -E "BROKEN|Getting links from" | \ + grep -B 1 "BROKEN"; builder_finish_action success test fi From 8df6c4e83f8191805d2d670865ddcb2a4550fa19 Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Thu, 28 Sep 2023 09:42:58 +0700 Subject: [PATCH 32/73] chore: use build.sh test --- .github/workflows/ci.yml | 2 +- build.sh | 8 +- composer.json | 5 + composer.lock | 1141 +++++++++++++++++++++++--------------- 4 files changed, 690 insertions(+), 466 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4513355e..a5c7c65f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,7 +19,7 @@ jobs: echo "TIER_TEST" > tier.txt ./build.sh build start env: - fail-fast: true + fail-fast: true # # Finally, run the tests diff --git a/build.sh b/build.sh index 6562ef38..aaa7dafe 100755 --- a/build.sh +++ b/build.sh @@ -121,11 +121,13 @@ fi if builder_start_action test; then # TODO: lint tests - - set +e; \ - set +o pipefail; \ + set +e; + set +o pipefail; npx broken-link-checker http://localhost:8053 --ordered --recursive --host-requests 50 -e --filter-level 3 | \ grep -E "BROKEN|Getting links from" | \ grep -B 1 "BROKEN"; + + echo "Done checking links" + builder_finish_action success test fi diff --git a/composer.json b/composer.json index 28f421e2..774eb449 100644 --- a/composer.json +++ b/composer.json @@ -2,6 +2,7 @@ "name": "keymanapi/keyman.com", "require": { "sentry/sdk": "^2.1", + "php-http/curl-client": "^2.1", "erusev/parsedown-extra": "^0.8.1", "erusev/parsedown": "^1.7" }, @@ -14,6 +15,10 @@ "Composer\\Config::disableProcessTimeout", "npx broken-link-checker http://keyman.com.localhost --ordered --recursive --host-requests 10 -e --filter-level 3" ], + "check-docker-links": [ + "Composer\\Config::disableProcessTimeout", + "npx broken-link-checker http://localhost:8053 --ordered --recursive --host-requests 10 -e --filter-level 3" + ], "lint": "find . -name '*.php' | grep -v '/vendor/' | xargs -n 1 -d '\\n' php -l" } } diff --git a/composer.lock b/composer.lock index 8a226ec2..b0ceb20f 100644 --- a/composer.lock +++ b/composer.lock @@ -4,27 +4,27 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "1e663743215530e678f617f7eee54e34", + "content-hash": "3e06fbc1b0bb235733fbbcac295e8189", "packages": [ { "name": "clue/stream-filter", - "version": "v1.4.1", + "version": "v1.5.0", "source": { "type": "git", "url": "https://github.com/clue/stream-filter.git", - "reference": "5a58cc30a8bd6a4eb8f856adf61dd3e013f53f71" + "reference": "aeb7d8ea49c7963d3b581378955dbf5bc49aa320" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/clue/stream-filter/zipball/5a58cc30a8bd6a4eb8f856adf61dd3e013f53f71", - "reference": "5a58cc30a8bd6a4eb8f856adf61dd3e013f53f71", + "url": "https://api.github.com/repos/clue/stream-filter/zipball/aeb7d8ea49c7963d3b581378955dbf5bc49aa320", + "reference": "aeb7d8ea49c7963d3b581378955dbf5bc49aa320", "shasum": "" }, "require": { "php": ">=5.3" }, "require-dev": { - "phpunit/phpunit": "^5.0 || ^4.8" + "phpunit/phpunit": "^9.3 || ^5.7 || ^4.8.36" }, "type": "library", "autoload": { @@ -42,7 +42,7 @@ "authors": [ { "name": "Christian Lück", - "email": "christian@lueck.tv" + "email": "christian@clue.engineering" } ], "description": "A simple and modern approach to stream filtering in PHP", @@ -66,28 +66,28 @@ "type": "github" } ], - "time": "2019-04-09T12:31:48+00:00" + "time": "2020-10-02T12:38:20+00:00" }, { "name": "composer/package-versions-deprecated", - "version": "1.8.0", + "version": "1.11.99.1", "source": { "type": "git", "url": "https://github.com/composer/package-versions-deprecated.git", - "reference": "98df7f1b293c0550bd5b1ce6b60b59bdda23aa47" + "reference": "7413f0b55a051e89485c5cb9f765fe24bb02a7b6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/package-versions-deprecated/zipball/98df7f1b293c0550bd5b1ce6b60b59bdda23aa47", - "reference": "98df7f1b293c0550bd5b1ce6b60b59bdda23aa47", + "url": "https://api.github.com/repos/composer/package-versions-deprecated/zipball/7413f0b55a051e89485c5cb9f765fe24bb02a7b6", + "reference": "7413f0b55a051e89485c5cb9f765fe24bb02a7b6", "shasum": "" }, "require": { "composer-plugin-api": "^1.1.0 || ^2.0", - "php": "^7" + "php": "^7 || ^8" }, "replace": { - "ocramius/package-versions": "1.2 - 1.8.99" + "ocramius/package-versions": "1.11.99" }, "require-dev": { "composer/composer": "^1.9.3 || ^2.0@dev", @@ -126,12 +126,16 @@ "url": "https://packagist.com", "type": "custom" }, + { + "url": "https://github.com/composer", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/composer/composer", "type": "tidelift" } ], - "time": "2020-04-23T11:49:37+00:00" + "time": "2020-11-11T10:22:58+00:00" }, { "name": "erusev/parsedown", @@ -570,24 +574,24 @@ }, { "name": "jean85/pretty-package-versions", - "version": "1.3.0", + "version": "1.5.1", "source": { "type": "git", "url": "https://github.com/Jean85/pretty-package-versions.git", - "reference": "e3517fb11b67e798239354fe8213927d012ad8f9" + "reference": "a917488320c20057da87f67d0d40543dd9427f7a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Jean85/pretty-package-versions/zipball/e3517fb11b67e798239354fe8213927d012ad8f9", - "reference": "e3517fb11b67e798239354fe8213927d012ad8f9", + "url": "https://api.github.com/repos/Jean85/pretty-package-versions/zipball/a917488320c20057da87f67d0d40543dd9427f7a", + "reference": "a917488320c20057da87f67d0d40543dd9427f7a", "shasum": "" }, "require": { "composer/package-versions-deprecated": "^1.8.0", - "php": "^7.0" + "php": "^7.0|^8.0" }, "require-dev": { - "phpunit/phpunit": "^6.0" + "phpunit/phpunit": "^6.0|^8.5|^9.2" }, "type": "library", "extra": { @@ -617,97 +621,123 @@ "release", "versions" ], - "time": "2020-04-24T14:19:45+00:00" + "time": "2020-09-14T08:43:34+00:00" }, { - "name": "paragonie/random_compat", - "version": "v9.99.99", + "name": "php-http/client-common", + "version": "2.3.0", "source": { "type": "git", - "url": "https://github.com/paragonie/random_compat.git", - "reference": "84b4dfb120c6f9b4ff7b3685f9b8f1aa365a0c95" + "url": "https://github.com/php-http/client-common.git", + "reference": "e37e46c610c87519753135fb893111798c69076a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/paragonie/random_compat/zipball/84b4dfb120c6f9b4ff7b3685f9b8f1aa365a0c95", - "reference": "84b4dfb120c6f9b4ff7b3685f9b8f1aa365a0c95", + "url": "https://api.github.com/repos/php-http/client-common/zipball/e37e46c610c87519753135fb893111798c69076a", + "reference": "e37e46c610c87519753135fb893111798c69076a", "shasum": "" }, "require": { - "php": "^7" + "php": "^7.1 || ^8.0", + "php-http/httplug": "^2.0", + "php-http/message": "^1.6", + "php-http/message-factory": "^1.0", + "psr/http-client": "^1.0", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.0", + "symfony/options-resolver": "^2.6 || ^3.4.20 || ~4.0.15 || ~4.1.9 || ^4.2.1 || ^5.0", + "symfony/polyfill-php80": "^1.17" }, "require-dev": { - "phpunit/phpunit": "4.*|5.*", - "vimeo/psalm": "^1" + "doctrine/instantiator": "^1.1", + "guzzlehttp/psr7": "^1.4", + "nyholm/psr7": "^1.2", + "phpspec/phpspec": "^5.1 || ^6.0", + "phpspec/prophecy": "^1.10.2", + "phpunit/phpunit": "^7.5.15 || ^8.5 || ^9.3" }, "suggest": { - "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes." + "ext-json": "To detect JSON responses with the ContentTypePlugin", + "ext-libxml": "To detect XML responses with the ContentTypePlugin", + "php-http/cache-plugin": "PSR-6 Cache plugin", + "php-http/logger-plugin": "PSR-3 Logger plugin", + "php-http/stopwatch-plugin": "Symfony Stopwatch plugin" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Http\\Client\\Common\\": "src/" + } + }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { - "name": "Paragon Initiative Enterprises", - "email": "security@paragonie.com", - "homepage": "https://paragonie.com" + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com" } ], - "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7", + "description": "Common HTTP Client implementations and tools for HTTPlug", + "homepage": "http://httplug.io", "keywords": [ - "csprng", - "polyfill", - "pseudorandom", - "random" + "client", + "common", + "http", + "httplug" ], - "time": "2018-07-02T15:55:56+00:00" + "time": "2020-07-21T10:04:13+00:00" }, { - "name": "php-http/client-common", - "version": "2.1.0", + "name": "php-http/curl-client", + "version": "2.1.1", "source": { "type": "git", - "url": "https://github.com/php-http/client-common.git", - "reference": "a8b29678d61556f45d6236b1667db16d998ceec5" + "url": "https://github.com/php-http/curl-client.git", + "reference": "f0cb9802da5c56b6553dfbef4ce5e1ee333b01de" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-http/client-common/zipball/a8b29678d61556f45d6236b1667db16d998ceec5", - "reference": "a8b29678d61556f45d6236b1667db16d998ceec5", + "url": "https://api.github.com/repos/php-http/curl-client/zipball/f0cb9802da5c56b6553dfbef4ce5e1ee333b01de", + "reference": "f0cb9802da5c56b6553dfbef4ce5e1ee333b01de", "shasum": "" }, "require": { + "ext-curl": "*", "php": "^7.1", + "php-http/discovery": "^1.6", "php-http/httplug": "^2.0", - "php-http/message": "^1.6", - "php-http/message-factory": "^1.0", - "symfony/options-resolver": " ^3.4.20 || ~4.0.15 || ~4.1.9 || ^4.2.1 || ^5.0" + "php-http/message": "^1.2", + "psr/http-client": "^1.0", + "psr/http-factory": "^1.0", + "symfony/options-resolver": "^3.4 || ^4.0 || ^5.0" }, - "require-dev": { - "doctrine/instantiator": "^1.1", - "guzzlehttp/psr7": "^1.4", - "phpspec/phpspec": "^5.1", - "phpspec/prophecy": "^1.8", - "sebastian/comparator": "^3.0" + "provide": { + "php-http/async-client-implementation": "1.0", + "php-http/client-implementation": "1.0", + "psr/http-client-implementation": "1.0" }, - "suggest": { - "ext-json": "To detect JSON responses with the ContentTypePlugin", - "ext-libxml": "To detect XML responses with the ContentTypePlugin", - "php-http/cache-plugin": "PSR-6 Cache plugin", - "php-http/logger-plugin": "PSR-3 Logger plugin", - "php-http/stopwatch-plugin": "Symfony Stopwatch plugin" + "require-dev": { + "guzzlehttp/psr7": "^1.0", + "laminas/laminas-diactoros": "^2.0", + "php-http/client-integration-tests": "^2.0", + "phpunit/phpunit": "^7.5" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0.x-dev" + "dev-master": "2.x-dev" } }, "autoload": { "psr-4": { - "Http\\Client\\Common\\": "src/" + "Http\\Client\\Curl\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -716,45 +746,44 @@ ], "authors": [ { - "name": "Márk Sági-Kazár", - "email": "mark.sagikazar@gmail.com" + "name": "Михаил Красильников", + "email": "m.krasilnikov@yandex.ru" } ], - "description": "Common HTTP Client implementations and tools for HTTPlug", - "homepage": "http://httplug.io", + "description": "PSR-18 and HTTPlug Async client with cURL", + "homepage": "http://php-http.org", "keywords": [ - "client", - "common", + "curl", "http", - "httplug" + "psr-18" ], - "time": "2019-11-18T08:58:18+00:00" + "time": "2020-10-12T06:56:33+00:00" }, { "name": "php-http/discovery", - "version": "1.8.0", + "version": "1.12.0", "source": { "type": "git", "url": "https://github.com/php-http/discovery.git", - "reference": "10d9019f393773345aedc0dc79e7fd678da874ee" + "reference": "4366bf1bc39b663aa87459bd725501d2f1988b6c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-http/discovery/zipball/10d9019f393773345aedc0dc79e7fd678da874ee", - "reference": "10d9019f393773345aedc0dc79e7fd678da874ee", + "url": "https://api.github.com/repos/php-http/discovery/zipball/4366bf1bc39b663aa87459bd725501d2f1988b6c", + "reference": "4366bf1bc39b663aa87459bd725501d2f1988b6c", "shasum": "" }, "require": { - "php": "^7.1" + "php": "^7.1 || ^8.0" }, "conflict": { "nyholm/psr7": "<1.0" }, "require-dev": { - "akeneo/phpspec-skip-example-extension": "^4.0", + "graham-campbell/phpspec-skip-example-extension": "^5.0", "php-http/httplug": "^1.0 || ^2.0", "php-http/message-factory": "^1.0", - "phpspec/phpspec": "^5.1", + "phpspec/phpspec": "^5.1 || ^6.1", "puli/composer-plugin": "1.0.0-beta10" }, "suggest": { @@ -764,7 +793,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.7-dev" + "dev-master": "1.9-dev" } }, "autoload": { @@ -793,7 +822,7 @@ "message", "psr7" ], - "time": "2020-06-14T10:44:12+00:00" + "time": "2020-09-22T13:31:04+00:00" }, { "name": "php-http/guzzle6-adapter", @@ -860,27 +889,27 @@ }, { "name": "php-http/httplug", - "version": "2.1.0", + "version": "2.2.0", "source": { "type": "git", "url": "https://github.com/php-http/httplug.git", - "reference": "72d2b129a48f0490d55b7f89be0d6aa0597ffb06" + "reference": "191a0a1b41ed026b717421931f8d3bd2514ffbf9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-http/httplug/zipball/72d2b129a48f0490d55b7f89be0d6aa0597ffb06", - "reference": "72d2b129a48f0490d55b7f89be0d6aa0597ffb06", + "url": "https://api.github.com/repos/php-http/httplug/zipball/191a0a1b41ed026b717421931f8d3bd2514ffbf9", + "reference": "191a0a1b41ed026b717421931f8d3bd2514ffbf9", "shasum": "" }, "require": { - "php": "^7.0", - "php-http/promise": "^1.0", + "php": "^7.1 || ^8.0", + "php-http/promise": "^1.1", "psr/http-client": "^1.0", "psr/http-message": "^1.0" }, "require-dev": { "friends-of-phpspec/phpspec-code-coverage": "^4.1", - "phpspec/phpspec": "^4.3.4|^5.0|^6.0" + "phpspec/phpspec": "^5.1 || ^6.0" }, "type": "library", "extra": { @@ -904,7 +933,8 @@ }, { "name": "Márk Sági-Kazár", - "email": "mark.sagikazar@gmail.com" + "email": "mark.sagikazar@gmail.com", + "homepage": "https://sagikazarmark.hu" } ], "description": "HTTPlug, the HTTP client abstraction for PHP", @@ -913,25 +943,25 @@ "client", "http" ], - "time": "2019-12-27T10:07:11+00:00" + "time": "2020-07-13T15:43:23+00:00" }, { "name": "php-http/message", - "version": "1.8.0", + "version": "1.10.0", "source": { "type": "git", "url": "https://github.com/php-http/message.git", - "reference": "ce8f43ac1e294b54aabf5808515c3554a19c1e1c" + "reference": "39db36d5972e9e6d00ea852b650953f928d8f10d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-http/message/zipball/ce8f43ac1e294b54aabf5808515c3554a19c1e1c", - "reference": "ce8f43ac1e294b54aabf5808515c3554a19c1e1c", + "url": "https://api.github.com/repos/php-http/message/zipball/39db36d5972e9e6d00ea852b650953f928d8f10d", + "reference": "39db36d5972e9e6d00ea852b650953f928d8f10d", "shasum": "" }, "require": { - "clue/stream-filter": "^1.4", - "php": "^7.1", + "clue/stream-filter": "^1.5", + "php": "^7.1 || ^8.0", "php-http/message-factory": "^1.0.2", "psr/http-message": "^1.0" }, @@ -939,12 +969,10 @@ "php-http/message-factory-implementation": "1.0" }, "require-dev": { - "akeneo/phpspec-skip-example-extension": "^1.0", - "coduo/phpspec-data-provider-extension": "^1.0", + "ergebnis/composer-normalize": "^2.6", "ext-zlib": "*", "guzzlehttp/psr7": "^1.0", - "henrikbjorn/phpspec-code-coverage": "^1.0", - "phpspec/phpspec": "^2.4", + "phpspec/phpspec": "^5.1 || ^6.3", "slim/slim": "^3.0", "zendframework/zend-diactoros": "^1.0" }, @@ -957,7 +985,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.8-dev" + "dev-master": "1.10-dev" } }, "autoload": { @@ -985,7 +1013,7 @@ "message", "psr-7" ], - "time": "2019-08-05T06:55:08+00:00" + "time": "2020-11-11T10:19:56+00:00" }, { "name": "php-http/message-factory", @@ -1039,21 +1067,24 @@ }, { "name": "php-http/promise", - "version": "v1.0.0", + "version": "1.1.0", "source": { "type": "git", "url": "https://github.com/php-http/promise.git", - "reference": "dc494cdc9d7160b9a09bd5573272195242ce7980" + "reference": "4c4c1f9b7289a2ec57cde7f1e9762a5789506f88" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-http/promise/zipball/dc494cdc9d7160b9a09bd5573272195242ce7980", - "reference": "dc494cdc9d7160b9a09bd5573272195242ce7980", + "url": "https://api.github.com/repos/php-http/promise/zipball/4c4c1f9b7289a2ec57cde7f1e9762a5789506f88", + "reference": "4c4c1f9b7289a2ec57cde7f1e9762a5789506f88", "shasum": "" }, + "require": { + "php": "^7.1 || ^8.0" + }, "require-dev": { - "henrikbjorn/phpspec-code-coverage": "^1.0", - "phpspec/phpspec": "^2.4" + "friends-of-phpspec/phpspec-code-coverage": "^4.3.2", + "phpspec/phpspec": "^5.1.2 || ^6.2" }, "type": "library", "extra": { @@ -1071,13 +1102,13 @@ "MIT" ], "authors": [ - { - "name": "Márk Sági-Kazár", - "email": "mark.sagikazar@gmail.com" - }, { "name": "Joel Wurtz", "email": "joel.wurtz@gmail.com" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com" } ], "description": "Promise used for asynchronous HTTP requests", @@ -1085,24 +1116,24 @@ "keywords": [ "promise" ], - "time": "2016-01-26T13:27:02+00:00" + "time": "2020-07-07T09:29:14+00:00" }, { "name": "psr/http-client", - "version": "1.0.0", + "version": "1.0.1", "source": { "type": "git", "url": "https://github.com/php-fig/http-client.git", - "reference": "496a823ef742b632934724bf769560c2a5c7c44e" + "reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-client/zipball/496a823ef742b632934724bf769560c2a5c7c44e", - "reference": "496a823ef742b632934724bf769560c2a5c7c44e", + "url": "https://api.github.com/repos/php-fig/http-client/zipball/2dfb5f6c5eff0e91e20e913f8c5452ed95b86621", + "reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621", "shasum": "" }, "require": { - "php": "^7.0", + "php": "^7.0 || ^8.0", "psr/http-message": "^1.0" }, "type": "library", @@ -1134,7 +1165,7 @@ "psr", "psr-18" ], - "time": "2018-10-30T23:29:13+00:00" + "time": "2020-06-29T06:28:15+00:00" }, { "name": "psr/http-factory", @@ -1360,16 +1391,16 @@ }, { "name": "sentry/sentry", - "version": "2.4.0", + "version": "2.5.0", "source": { "type": "git", "url": "https://github.com/getsentry/sentry-php.git", - "reference": "e44561875e0d724bac3d9cdb705bf58847acd425" + "reference": "bab5b73dbaf5f0ff62317e1611d952764d5514a9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/getsentry/sentry-php/zipball/e44561875e0d724bac3d9cdb705bf58847acd425", - "reference": "e44561875e0d724bac3d9cdb705bf58847acd425", + "url": "https://api.github.com/repos/getsentry/sentry-php/zipball/bab5b73dbaf5f0ff62317e1611d952764d5514a9", + "reference": "bab5b73dbaf5f0ff62317e1611d952764d5514a9", "shasum": "" }, "require": { @@ -1411,7 +1442,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.4-dev" + "dev-master": "2.5.x-dev" } }, "autoload": { @@ -1453,20 +1484,20 @@ "type": "custom" } ], - "time": "2020-05-20T20:49:38+00:00" + "time": "2020-09-14T07:02:40+00:00" }, { "name": "symfony/deprecation-contracts", - "version": "v2.1.2", + "version": "v2.2.0", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "dd99cb3a0aff6cadd2a8d7d7ed72c2161e218337" + "reference": "5fa56b4074d1ae755beb55617ddafe6f5d78f665" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/dd99cb3a0aff6cadd2a8d7d7ed72c2161e218337", - "reference": "dd99cb3a0aff6cadd2a8d7d7ed72c2161e218337", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/5fa56b4074d1ae755beb55617ddafe6f5d78f665", + "reference": "5fa56b4074d1ae755beb55617ddafe6f5d78f665", "shasum": "" }, "require": { @@ -1475,7 +1506,11 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.1-dev" + "dev-master": "2.2-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" } }, "autoload": { @@ -1513,20 +1548,20 @@ "type": "tidelift" } ], - "time": "2020-05-27T08:34:37+00:00" + "time": "2020-09-07T11:33:47+00:00" }, { "name": "symfony/options-resolver", - "version": "v5.1.2", + "version": "v5.1.8", "source": { "type": "git", "url": "https://github.com/symfony/options-resolver.git", - "reference": "663f5dd5e14057d1954fe721f9709d35837f2447" + "reference": "c6a02905e4ffc7a1498e8ee019db2b477cd1cc02" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/663f5dd5e14057d1954fe721f9709d35837f2447", - "reference": "663f5dd5e14057d1954fe721f9709d35837f2447", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/c6a02905e4ffc7a1498e8ee019db2b477cd1cc02", + "reference": "c6a02905e4ffc7a1498e8ee019db2b477cd1cc02", "shasum": "" }, "require": { @@ -1535,11 +1570,6 @@ "symfony/polyfill-php80": "^1.15" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.1-dev" - } - }, "autoload": { "psr-4": { "Symfony\\Component\\OptionsResolver\\": "" @@ -1583,7 +1613,7 @@ "type": "tidelift" } ], - "time": "2020-05-23T13:08:13+00:00" + "time": "2020-10-24T12:01:57+00:00" }, { "name": "symfony/polyfill-intl-idn", @@ -1825,25 +1855,29 @@ }, { "name": "symfony/polyfill-php80", - "version": "v1.17.0", + "version": "v1.20.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "5e30b2799bc1ad68f7feb62b60a73743589438dd" + "reference": "e70aa8b064c5b72d3df2abd5ab1e90464ad009de" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/5e30b2799bc1ad68f7feb62b60a73743589438dd", - "reference": "5e30b2799bc1ad68f7feb62b60a73743589438dd", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/e70aa8b064c5b72d3df2abd5ab1e90464ad009de", + "reference": "e70aa8b064c5b72d3df2abd5ab1e90464ad009de", "shasum": "" }, "require": { - "php": ">=7.0.8" + "php": ">=7.1" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.17-dev" + "dev-main": "1.20-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" } }, "autoload": { @@ -1897,25 +1931,24 @@ "type": "tidelift" } ], - "time": "2020-05-12T16:47:27+00:00" + "time": "2020-10-23T14:02:19+00:00" }, { "name": "symfony/polyfill-uuid", - "version": "v1.17.0", + "version": "v1.20.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-uuid.git", - "reference": "6dbf0269e8aeab8253a5059c51c1760fb4034e87" + "reference": "7095799250ff244f3015dc492480175a249e7b55" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-uuid/zipball/6dbf0269e8aeab8253a5059c51c1760fb4034e87", - "reference": "6dbf0269e8aeab8253a5059c51c1760fb4034e87", + "url": "https://api.github.com/repos/symfony/polyfill-uuid/zipball/7095799250ff244f3015dc492480175a249e7b55", + "reference": "7095799250ff244f3015dc492480175a249e7b55", "shasum": "" }, "require": { - "paragonie/random_compat": "~1.0|~2.0|~9.99", - "php": ">=5.3.3" + "php": ">=7.1" }, "suggest": { "ext-uuid": "For best performance" @@ -1923,7 +1956,11 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.17-dev" + "dev-main": "1.20-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" } }, "autoload": { @@ -1970,42 +2007,37 @@ "type": "tidelift" } ], - "time": "2020-05-12T16:47:27+00:00" + "time": "2020-10-23T14:02:19+00:00" } ], "packages-dev": [ { "name": "doctrine/instantiator", - "version": "1.3.1", + "version": "1.4.0", "source": { "type": "git", "url": "https://github.com/doctrine/instantiator.git", - "reference": "f350df0268e904597e3bd9c4685c53e0e333feea" + "reference": "d56bf6102915de5702778fe20f2de3b2fe570b5b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/f350df0268e904597e3bd9c4685c53e0e333feea", - "reference": "f350df0268e904597e3bd9c4685c53e0e333feea", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/d56bf6102915de5702778fe20f2de3b2fe570b5b", + "reference": "d56bf6102915de5702778fe20f2de3b2fe570b5b", "shasum": "" }, "require": { "php": "^7.1 || ^8.0" }, "require-dev": { - "doctrine/coding-standard": "^6.0", + "doctrine/coding-standard": "^8.0", "ext-pdo": "*", "ext-phar": "*", - "phpbench/phpbench": "^0.13", - "phpstan/phpstan-phpunit": "^0.11", - "phpstan/phpstan-shim": "^0.11", - "phpunit/phpunit": "^7.0" + "phpbench/phpbench": "^0.13 || 1.0.0-alpha2", + "phpstan/phpstan": "^0.12", + "phpstan/phpstan-phpunit": "^0.12", + "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.2.x-dev" - } - }, "autoload": { "psr-4": { "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" @@ -2019,7 +2051,7 @@ { "name": "Marco Pivetta", "email": "ocramius@gmail.com", - "homepage": "http://ocramius.github.com/" + "homepage": "https://ocramius.github.io/" } ], "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", @@ -2042,24 +2074,24 @@ "type": "tidelift" } ], - "time": "2020-05-29T17:27:14+00:00" + "time": "2020-11-10T18:47:58+00:00" }, { "name": "myclabs/deep-copy", - "version": "1.9.5", + "version": "1.10.2", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "b2c28789e80a97badd14145fda39b545d83ca3ef" + "reference": "776f831124e9c62e1a2c601ecc52e776d8bb7220" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/b2c28789e80a97badd14145fda39b545d83ca3ef", - "reference": "b2c28789e80a97badd14145fda39b545d83ca3ef", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/776f831124e9c62e1a2c601ecc52e776d8bb7220", + "reference": "776f831124e9c62e1a2c601ecc52e776d8bb7220", "shasum": "" }, "require": { - "php": "^7.1" + "php": "^7.1 || ^8.0" }, "replace": { "myclabs/deep-copy": "self.version" @@ -2090,32 +2122,91 @@ "object", "object graph" ], - "time": "2020-01-17T21:11:47+00:00" + "funding": [ + { + "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", + "type": "tidelift" + } + ], + "time": "2020-11-13T09:40:50+00:00" + }, + { + "name": "nikic/php-parser", + "version": "v4.10.2", + "source": { + "type": "git", + "url": "https://github.com/nikic/PHP-Parser.git", + "reference": "658f1be311a230e0907f5dfe0213742aff0596de" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/658f1be311a230e0907f5dfe0213742aff0596de", + "reference": "658f1be311a230e0907f5dfe0213742aff0596de", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": ">=7.0" + }, + "require-dev": { + "ircmaxell/php-yacc": "^0.0.7", + "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0" + }, + "bin": [ + "bin/php-parse" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.9-dev" + } + }, + "autoload": { + "psr-4": { + "PhpParser\\": "lib/PhpParser" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Nikita Popov" + } + ], + "description": "A PHP parser written in PHP", + "keywords": [ + "parser", + "php" + ], + "time": "2020-09-26T10:30:38+00:00" }, { "name": "phar-io/manifest", - "version": "1.0.3", + "version": "2.0.1", "source": { "type": "git", "url": "https://github.com/phar-io/manifest.git", - "reference": "7761fcacf03b4d4f16e7ccb606d4879ca431fcf4" + "reference": "85265efd3af7ba3ca4b2a2c34dbfc5788dd29133" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phar-io/manifest/zipball/7761fcacf03b4d4f16e7ccb606d4879ca431fcf4", - "reference": "7761fcacf03b4d4f16e7ccb606d4879ca431fcf4", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/85265efd3af7ba3ca4b2a2c34dbfc5788dd29133", + "reference": "85265efd3af7ba3ca4b2a2c34dbfc5788dd29133", "shasum": "" }, "require": { "ext-dom": "*", "ext-phar": "*", - "phar-io/version": "^2.0", - "php": "^5.6 || ^7.0" + "ext-xmlwriter": "*", + "phar-io/version": "^3.0.1", + "php": "^7.2 || ^8.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "2.0.x-dev" } }, "autoload": { @@ -2145,24 +2236,24 @@ } ], "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", - "time": "2018-07-08T19:23:20+00:00" + "time": "2020-06-27T14:33:11+00:00" }, { "name": "phar-io/version", - "version": "2.0.1", + "version": "3.0.2", "source": { "type": "git", "url": "https://github.com/phar-io/version.git", - "reference": "45a2ec53a73c70ce41d55cedef9063630abaf1b6" + "reference": "c6bb6825def89e0a32220f88337f8ceaf1975fa0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phar-io/version/zipball/45a2ec53a73c70ce41d55cedef9063630abaf1b6", - "reference": "45a2ec53a73c70ce41d55cedef9063630abaf1b6", + "url": "https://api.github.com/repos/phar-io/version/zipball/c6bb6825def89e0a32220f88337f8ceaf1975fa0", + "reference": "c6bb6825def89e0a32220f88337f8ceaf1975fa0", "shasum": "" }, "require": { - "php": "^5.6 || ^7.0" + "php": "^7.2 || ^8.0" }, "type": "library", "autoload": { @@ -2192,29 +2283,29 @@ } ], "description": "Library for handling version information and constraints", - "time": "2018-07-08T19:19:57+00:00" + "time": "2020-06-27T14:39:04+00:00" }, { "name": "phpdocumentor/reflection-common", - "version": "2.1.0", + "version": "2.2.0", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionCommon.git", - "reference": "6568f4687e5b41b054365f9ae03fcb1ed5f2069b" + "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/6568f4687e5b41b054365f9ae03fcb1ed5f2069b", - "reference": "6568f4687e5b41b054365f9ae03fcb1ed5f2069b", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/1d01c49d4ed62f25aa84a747ad35d5a16924662b", + "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b", "shasum": "" }, "require": { - "php": ">=7.1" + "php": "^7.2 || ^8.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.x-dev" + "dev-2.x": "2.x-dev" } }, "autoload": { @@ -2241,32 +2332,31 @@ "reflection", "static analysis" ], - "time": "2020-04-27T09:25:28+00:00" + "time": "2020-06-27T09:03:43+00:00" }, { "name": "phpdocumentor/reflection-docblock", - "version": "5.1.0", + "version": "5.2.2", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "cd72d394ca794d3466a3b2fc09d5a6c1dc86b47e" + "reference": "069a785b2141f5bcf49f3e353548dc1cce6df556" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/cd72d394ca794d3466a3b2fc09d5a6c1dc86b47e", - "reference": "cd72d394ca794d3466a3b2fc09d5a6c1dc86b47e", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/069a785b2141f5bcf49f3e353548dc1cce6df556", + "reference": "069a785b2141f5bcf49f3e353548dc1cce6df556", "shasum": "" }, "require": { - "ext-filter": "^7.1", - "php": "^7.2", - "phpdocumentor/reflection-common": "^2.0", - "phpdocumentor/type-resolver": "^1.0", - "webmozart/assert": "^1" + "ext-filter": "*", + "php": "^7.2 || ^8.0", + "phpdocumentor/reflection-common": "^2.2", + "phpdocumentor/type-resolver": "^1.3", + "webmozart/assert": "^1.9.1" }, "require-dev": { - "doctrine/instantiator": "^1", - "mockery/mockery": "^1" + "mockery/mockery": "~1.3.2" }, "type": "library", "extra": { @@ -2294,34 +2384,33 @@ } ], "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", - "time": "2020-02-22T12:28:44+00:00" + "time": "2020-09-03T19:13:55+00:00" }, { "name": "phpdocumentor/type-resolver", - "version": "1.1.0", + "version": "1.4.0", "source": { "type": "git", "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "7462d5f123dfc080dfdf26897032a6513644fc95" + "reference": "6a467b8989322d92aa1c8bf2bebcc6e5c2ba55c0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/7462d5f123dfc080dfdf26897032a6513644fc95", - "reference": "7462d5f123dfc080dfdf26897032a6513644fc95", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/6a467b8989322d92aa1c8bf2bebcc6e5c2ba55c0", + "reference": "6a467b8989322d92aa1c8bf2bebcc6e5c2ba55c0", "shasum": "" }, "require": { - "php": "^7.2", + "php": "^7.2 || ^8.0", "phpdocumentor/reflection-common": "^2.0" }, "require-dev": { - "ext-tokenizer": "^7.2", - "mockery/mockery": "~1" + "ext-tokenizer": "*" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.x-dev" + "dev-1.x": "1.x-dev" } }, "autoload": { @@ -2340,37 +2429,37 @@ } ], "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", - "time": "2020-02-18T18:59:58+00:00" + "time": "2020-09-17T18:55:26+00:00" }, { "name": "phpspec/prophecy", - "version": "v1.10.3", + "version": "1.12.1", "source": { "type": "git", "url": "https://github.com/phpspec/prophecy.git", - "reference": "451c3cd1418cf640de218914901e51b064abb093" + "reference": "8ce87516be71aae9b956f81906aaf0338e0d8a2d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/451c3cd1418cf640de218914901e51b064abb093", - "reference": "451c3cd1418cf640de218914901e51b064abb093", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/8ce87516be71aae9b956f81906aaf0338e0d8a2d", + "reference": "8ce87516be71aae9b956f81906aaf0338e0d8a2d", "shasum": "" }, "require": { - "doctrine/instantiator": "^1.0.2", - "php": "^5.3|^7.0", - "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0|^5.0", - "sebastian/comparator": "^1.2.3|^2.0|^3.0|^4.0", - "sebastian/recursion-context": "^1.0|^2.0|^3.0|^4.0" + "doctrine/instantiator": "^1.2", + "php": "^7.2 || ~8.0, <8.1", + "phpdocumentor/reflection-docblock": "^5.2", + "sebastian/comparator": "^3.0 || ^4.0", + "sebastian/recursion-context": "^3.0 || ^4.0" }, "require-dev": { - "phpspec/phpspec": "^2.5 || ^3.2", - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5 || ^7.1" + "phpspec/phpspec": "^6.0", + "phpunit/phpunit": "^8.0 || ^9.0 <9.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.10.x-dev" + "dev-master": "1.11.x-dev" } }, "autoload": { @@ -2403,36 +2492,39 @@ "spy", "stub" ], - "time": "2020-03-05T15:02:03+00:00" + "time": "2020-09-29T09:10:42+00:00" }, { "name": "phpunit/php-code-coverage", - "version": "8.0.2", + "version": "9.2.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "ca6647ffddd2add025ab3f21644a441d7c146cdc" + "reference": "6b20e2055f7c29b56cb3870b3de7cc463d7add41" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/ca6647ffddd2add025ab3f21644a441d7c146cdc", - "reference": "ca6647ffddd2add025ab3f21644a441d7c146cdc", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/6b20e2055f7c29b56cb3870b3de7cc463d7add41", + "reference": "6b20e2055f7c29b56cb3870b3de7cc463d7add41", "shasum": "" }, "require": { "ext-dom": "*", + "ext-libxml": "*", "ext-xmlwriter": "*", - "php": "^7.3", - "phpunit/php-file-iterator": "^3.0", - "phpunit/php-text-template": "^2.0", - "phpunit/php-token-stream": "^4.0", - "sebastian/code-unit-reverse-lookup": "^2.0", - "sebastian/environment": "^5.0", - "sebastian/version": "^3.0", - "theseer/tokenizer": "^1.1.3" + "nikic/php-parser": "^4.10.2", + "php": ">=7.3", + "phpunit/php-file-iterator": "^3.0.3", + "phpunit/php-text-template": "^2.0.2", + "sebastian/code-unit-reverse-lookup": "^2.0.2", + "sebastian/complexity": "^2.0", + "sebastian/environment": "^5.1.2", + "sebastian/lines-of-code": "^1.0", + "sebastian/version": "^3.0.1", + "theseer/tokenizer": "^1.2.0" }, "require-dev": { - "phpunit/phpunit": "^9.0" + "phpunit/phpunit": "^9.3" }, "suggest": { "ext-pcov": "*", @@ -2441,7 +2533,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "8.0-dev" + "dev-master": "9.2-dev" } }, "autoload": { @@ -2473,27 +2565,27 @@ "type": "github" } ], - "time": "2020-05-23T08:02:54+00:00" + "time": "2020-10-30T10:46:41+00:00" }, { "name": "phpunit/php-file-iterator", - "version": "3.0.2", + "version": "3.0.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "eba15e538f2bb3fe018b7bbb47d2fe32d404bfd2" + "reference": "aa4be8575f26070b100fccb67faabb28f21f66f8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/eba15e538f2bb3fe018b7bbb47d2fe32d404bfd2", - "reference": "eba15e538f2bb3fe018b7bbb47d2fe32d404bfd2", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/aa4be8575f26070b100fccb67faabb28f21f66f8", + "reference": "aa4be8575f26070b100fccb67faabb28f21f66f8", "shasum": "" }, "require": { - "php": "^7.3" + "php": ">=7.3" }, "require-dev": { - "phpunit/phpunit": "^9.0" + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { @@ -2529,28 +2621,28 @@ "type": "github" } ], - "time": "2020-06-15T12:54:35+00:00" + "time": "2020-09-28T05:57:25+00:00" }, { "name": "phpunit/php-invoker", - "version": "3.0.1", + "version": "3.1.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-invoker.git", - "reference": "62f696ad0d140e0e513e69eaafdebb674d622b4c" + "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/62f696ad0d140e0e513e69eaafdebb674d622b4c", - "reference": "62f696ad0d140e0e513e69eaafdebb674d622b4c", + "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/5a10147d0aaf65b58940a0b72f71c9ac0423cc67", + "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67", "shasum": "" }, "require": { - "php": "^7.3" + "php": ">=7.3" }, "require-dev": { "ext-pcntl": "*", - "phpunit/phpunit": "^9.0" + "phpunit/phpunit": "^9.3" }, "suggest": { "ext-pcntl": "*" @@ -2558,7 +2650,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-master": "3.1-dev" } }, "autoload": { @@ -2588,27 +2680,27 @@ "type": "github" } ], - "time": "2020-06-15T13:10:07+00:00" + "time": "2020-09-28T05:58:55+00:00" }, { "name": "phpunit/php-text-template", - "version": "2.0.1", + "version": "2.0.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "0c69cbf965d5317ba33f24a352539f354a25db09" + "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/0c69cbf965d5317ba33f24a352539f354a25db09", - "reference": "0c69cbf965d5317ba33f24a352539f354a25db09", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", + "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", "shasum": "" }, "require": { - "php": "^7.3" + "php": ">=7.3" }, "require-dev": { - "phpunit/phpunit": "^9.0" + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { @@ -2643,27 +2735,27 @@ "type": "github" } ], - "time": "2020-06-15T12:52:43+00:00" + "time": "2020-10-26T05:33:50+00:00" }, { "name": "phpunit/php-timer", - "version": "5.0.0", + "version": "5.0.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "b0d089de001ba60ffa3be36b23e1b8150d072238" + "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/b0d089de001ba60ffa3be36b23e1b8150d072238", - "reference": "b0d089de001ba60ffa3be36b23e1b8150d072238", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", + "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", "shasum": "" }, "require": { - "php": "^7.3" + "php": ">=7.3" }, "require-dev": { - "phpunit/phpunit": "^9.2" + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { @@ -2698,36 +2790,73 @@ "type": "github" } ], - "time": "2020-06-07T12:05:53+00:00" + "time": "2020-10-26T13:16:10+00:00" }, { - "name": "phpunit/php-token-stream", - "version": "4.0.2", + "name": "phpunit/phpunit", + "version": "9.4.3", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "e61c593e9734b47ef462340c24fca8d6a57da14e" + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "9fa359ff5ddaa5eb2be2bedb08a6a5787a5807ab" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/e61c593e9734b47ef462340c24fca8d6a57da14e", - "reference": "e61c593e9734b47ef462340c24fca8d6a57da14e", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/9fa359ff5ddaa5eb2be2bedb08a6a5787a5807ab", + "reference": "9fa359ff5ddaa5eb2be2bedb08a6a5787a5807ab", "shasum": "" }, "require": { - "ext-tokenizer": "*", - "php": "^7.3" + "doctrine/instantiator": "^1.3.1", + "ext-dom": "*", + "ext-json": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-xml": "*", + "ext-xmlwriter": "*", + "myclabs/deep-copy": "^1.10.1", + "phar-io/manifest": "^2.0.1", + "phar-io/version": "^3.0.2", + "php": ">=7.3", + "phpspec/prophecy": "^1.12.1", + "phpunit/php-code-coverage": "^9.2", + "phpunit/php-file-iterator": "^3.0.5", + "phpunit/php-invoker": "^3.1.1", + "phpunit/php-text-template": "^2.0.3", + "phpunit/php-timer": "^5.0.2", + "sebastian/cli-parser": "^1.0.1", + "sebastian/code-unit": "^1.0.6", + "sebastian/comparator": "^4.0.5", + "sebastian/diff": "^4.0.3", + "sebastian/environment": "^5.1.3", + "sebastian/exporter": "^4.0.3", + "sebastian/global-state": "^5.0.1", + "sebastian/object-enumerator": "^4.0.3", + "sebastian/resource-operations": "^3.0.3", + "sebastian/type": "^2.3", + "sebastian/version": "^3.0.2" }, "require-dev": { - "phpunit/phpunit": "^9.0" + "ext-pdo": "*", + "phpspec/prophecy-phpunit": "^2.0.1" + }, + "suggest": { + "ext-soap": "*", + "ext-xdebug": "*" }, + "bin": [ + "phpunit" + ], "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-master": "9.4-dev" } }, "autoload": { + "files": [ + "src/Framework/Assert/Functions.php" + ], "classmap": [ "src/" ] @@ -2739,87 +2868,56 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" + "email": "sebastian@phpunit.de", + "role": "lead" } ], - "description": "Wrapper around PHP's tokenizer extension.", - "homepage": "https://github.com/sebastianbergmann/php-token-stream/", + "description": "The PHP Unit Testing framework.", + "homepage": "https://phpunit.de/", "keywords": [ - "tokenizer" + "phpunit", + "testing", + "xunit" ], "funding": [ + { + "url": "https://phpunit.de/donate.html", + "type": "custom" + }, { "url": "https://github.com/sebastianbergmann", "type": "github" } ], - "abandoned": true, - "time": "2020-06-16T07:00:44+00:00" + "time": "2020-11-10T12:53:30+00:00" }, { - "name": "phpunit/phpunit", - "version": "9.2.3", + "name": "sebastian/cli-parser", + "version": "1.0.1", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "c1b1d62095ef78427f112a7a1c1502d4607e3c00" + "url": "https://github.com/sebastianbergmann/cli-parser.git", + "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/c1b1d62095ef78427f112a7a1c1502d4607e3c00", - "reference": "c1b1d62095ef78427f112a7a1c1502d4607e3c00", + "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/442e7c7e687e42adc03470c7b668bc4b2402c0b2", + "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2", "shasum": "" }, "require": { - "doctrine/instantiator": "^1.2.0", - "ext-dom": "*", - "ext-json": "*", - "ext-libxml": "*", - "ext-mbstring": "*", - "ext-xml": "*", - "ext-xmlwriter": "*", - "myclabs/deep-copy": "^1.9.1", - "phar-io/manifest": "^1.0.3", - "phar-io/version": "^2.0.1", - "php": "^7.3", - "phpspec/prophecy": "^1.8.1", - "phpunit/php-code-coverage": "^8.0.1", - "phpunit/php-file-iterator": "^3.0", - "phpunit/php-invoker": "^3.0", - "phpunit/php-text-template": "^2.0", - "phpunit/php-timer": "^5.0", - "sebastian/code-unit": "^1.0.2", - "sebastian/comparator": "^4.0", - "sebastian/diff": "^4.0", - "sebastian/environment": "^5.0.1", - "sebastian/exporter": "^4.0", - "sebastian/global-state": "^4.0", - "sebastian/object-enumerator": "^4.0", - "sebastian/resource-operations": "^3.0", - "sebastian/type": "^2.1", - "sebastian/version": "^3.0" + "php": ">=7.3" }, "require-dev": { - "ext-pdo": "*", - "phpspec/prophecy-phpunit": "^2.0" + "phpunit/phpunit": "^9.3" }, - "suggest": { - "ext-soap": "*", - "ext-xdebug": "*" - }, - "bin": [ - "phpunit" - ], "type": "library", "extra": { "branch-alias": { - "dev-master": "9.2-dev" + "dev-master": "1.0-dev" } }, "autoload": { - "files": [ - "src/Framework/Assert/Functions.php" - ], "classmap": [ "src/" ] @@ -2835,44 +2933,35 @@ "role": "lead" } ], - "description": "The PHP Unit Testing framework.", - "homepage": "https://phpunit.de/", - "keywords": [ - "phpunit", - "testing", - "xunit" - ], + "description": "Library for parsing CLI options", + "homepage": "https://github.com/sebastianbergmann/cli-parser", "funding": [ - { - "url": "https://phpunit.de/donate.html", - "type": "custom" - }, { "url": "https://github.com/sebastianbergmann", "type": "github" } ], - "time": "2020-06-15T10:51:34+00:00" + "time": "2020-09-28T06:08:49+00:00" }, { "name": "sebastian/code-unit", - "version": "1.0.3", + "version": "1.0.8", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/code-unit.git", - "reference": "d650ef9b1fece15ed4d6eaed6e6b469b7b81183a" + "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/d650ef9b1fece15ed4d6eaed6e6b469b7b81183a", - "reference": "d650ef9b1fece15ed4d6eaed6e6b469b7b81183a", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/1fc9f64c0927627ef78ba436c9b17d967e68e120", + "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120", "shasum": "" }, "require": { - "php": "^7.3" + "php": ">=7.3" }, "require-dev": { - "phpunit/phpunit": "^9.0" + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { @@ -2904,27 +2993,27 @@ "type": "github" } ], - "time": "2020-06-15T13:11:26+00:00" + "time": "2020-10-26T13:08:54+00:00" }, { "name": "sebastian/code-unit-reverse-lookup", - "version": "2.0.1", + "version": "2.0.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", - "reference": "c771130f0e8669104a4320b7101a81c2cc2963ef" + "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/c771130f0e8669104a4320b7101a81c2cc2963ef", - "reference": "c771130f0e8669104a4320b7101a81c2cc2963ef", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", + "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", "shasum": "" }, "require": { - "php": "^7.3" + "php": ">=7.3" }, "require-dev": { - "phpunit/phpunit": "^9.0" + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { @@ -2955,29 +3044,29 @@ "type": "github" } ], - "time": "2020-06-15T12:56:39+00:00" + "time": "2020-09-28T05:30:19+00:00" }, { "name": "sebastian/comparator", - "version": "4.0.2", + "version": "4.0.6", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "266d85ef789da8c41f06af4093c43e9798af2784" + "reference": "55f4261989e546dc112258c7a75935a81a7ce382" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/266d85ef789da8c41f06af4093c43e9798af2784", - "reference": "266d85ef789da8c41f06af4093c43e9798af2784", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/55f4261989e546dc112258c7a75935a81a7ce382", + "reference": "55f4261989e546dc112258c7a75935a81a7ce382", "shasum": "" }, "require": { - "php": "^7.3", + "php": ">=7.3", "sebastian/diff": "^4.0", "sebastian/exporter": "^4.0" }, "require-dev": { - "phpunit/phpunit": "^9.0" + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { @@ -3025,27 +3114,80 @@ "type": "github" } ], - "time": "2020-06-15T15:04:48+00:00" + "time": "2020-10-26T15:49:45+00:00" + }, + { + "name": "sebastian/complexity", + "version": "2.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/complexity.git", + "reference": "739b35e53379900cc9ac327b2147867b8b6efd88" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/739b35e53379900cc9ac327b2147867b8b6efd88", + "reference": "739b35e53379900cc9ac327b2147867b8b6efd88", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^4.7", + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for calculating the complexity of PHP code units", + "homepage": "https://github.com/sebastianbergmann/complexity", + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T15:52:27+00:00" }, { "name": "sebastian/diff", - "version": "4.0.1", + "version": "4.0.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "3e523c576f29dacecff309f35e4cc5a5c168e78a" + "reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/3e523c576f29dacecff309f35e4cc5a5c168e78a", - "reference": "3e523c576f29dacecff309f35e4cc5a5c168e78a", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/3461e3fccc7cfdfc2720be910d3bd73c69be590d", + "reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d", "shasum": "" }, "require": { - "php": "^7.3" + "php": ">=7.3" }, "require-dev": { - "phpunit/phpunit": "^9.0", + "phpunit/phpunit": "^9.3", "symfony/process": "^4.2 || ^5" }, "type": "library", @@ -3087,27 +3229,27 @@ "type": "github" } ], - "time": "2020-05-08T05:01:12+00:00" + "time": "2020-10-26T13:10:38+00:00" }, { "name": "sebastian/environment", - "version": "5.1.1", + "version": "5.1.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "16eb0fa43e29c33d7f2117ed23072e26fc5ab34e" + "reference": "388b6ced16caa751030f6a69e588299fa09200ac" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/16eb0fa43e29c33d7f2117ed23072e26fc5ab34e", - "reference": "16eb0fa43e29c33d7f2117ed23072e26fc5ab34e", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/388b6ced16caa751030f6a69e588299fa09200ac", + "reference": "388b6ced16caa751030f6a69e588299fa09200ac", "shasum": "" }, "require": { - "php": "^7.3" + "php": ">=7.3" }, "require-dev": { - "phpunit/phpunit": "^9.0" + "phpunit/phpunit": "^9.3" }, "suggest": { "ext-posix": "*" @@ -3115,7 +3257,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "5.0-dev" + "dev-master": "5.1-dev" } }, "autoload": { @@ -3146,29 +3288,29 @@ "type": "github" } ], - "time": "2020-06-15T13:00:01+00:00" + "time": "2020-09-28T05:52:38+00:00" }, { "name": "sebastian/exporter", - "version": "4.0.1", + "version": "4.0.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "d12fbca85da932d01d941b59e4b71a0d559db091" + "reference": "d89cc98761b8cb5a1a235a6b703ae50d34080e65" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/d12fbca85da932d01d941b59e4b71a0d559db091", - "reference": "d12fbca85da932d01d941b59e4b71a0d559db091", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/d89cc98761b8cb5a1a235a6b703ae50d34080e65", + "reference": "d89cc98761b8cb5a1a235a6b703ae50d34080e65", "shasum": "" }, "require": { - "php": "^7.3", + "php": ">=7.3", "sebastian/recursion-context": "^4.0" }, "require-dev": { "ext-mbstring": "*", - "phpunit/phpunit": "^9.0" + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { @@ -3219,30 +3361,30 @@ "type": "github" } ], - "time": "2020-06-15T13:12:44+00:00" + "time": "2020-09-28T05:24:23+00:00" }, { "name": "sebastian/global-state", - "version": "4.0.0", + "version": "5.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "bdb1e7c79e592b8c82cb1699be3c8743119b8a72" + "reference": "a90ccbddffa067b51f574dea6eb25d5680839455" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bdb1e7c79e592b8c82cb1699be3c8743119b8a72", - "reference": "bdb1e7c79e592b8c82cb1699be3c8743119b8a72", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/a90ccbddffa067b51f574dea6eb25d5680839455", + "reference": "a90ccbddffa067b51f574dea6eb25d5680839455", "shasum": "" }, "require": { - "php": "^7.3", + "php": ">=7.3", "sebastian/object-reflector": "^2.0", "sebastian/recursion-context": "^4.0" }, "require-dev": { "ext-dom": "*", - "phpunit/phpunit": "^9.0" + "phpunit/phpunit": "^9.3" }, "suggest": { "ext-uopz": "*" @@ -3250,7 +3392,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-master": "5.0-dev" } }, "autoload": { @@ -3273,29 +3415,88 @@ "keywords": [ "global state" ], - "time": "2020-02-07T06:11:37+00:00" + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T15:55:19+00:00" + }, + { + "name": "sebastian/lines-of-code", + "version": "1.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/lines-of-code.git", + "reference": "acf76492a65401babcf5283296fa510782783a7a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/acf76492a65401babcf5283296fa510782783a7a", + "reference": "acf76492a65401babcf5283296fa510782783a7a", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^4.6", + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for counting the lines of code in PHP source code", + "homepage": "https://github.com/sebastianbergmann/lines-of-code", + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T17:03:56+00:00" }, { "name": "sebastian/object-enumerator", - "version": "4.0.1", + "version": "4.0.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "15f319d67c49fc55ebcdbffb3377433125588455" + "reference": "5c9eeac41b290a3712d88851518825ad78f45c71" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/15f319d67c49fc55ebcdbffb3377433125588455", - "reference": "15f319d67c49fc55ebcdbffb3377433125588455", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/5c9eeac41b290a3712d88851518825ad78f45c71", + "reference": "5c9eeac41b290a3712d88851518825ad78f45c71", "shasum": "" }, "require": { - "php": "^7.3", + "php": ">=7.3", "sebastian/object-reflector": "^2.0", "sebastian/recursion-context": "^4.0" }, "require-dev": { - "phpunit/phpunit": "^9.0" + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { @@ -3326,27 +3527,27 @@ "type": "github" } ], - "time": "2020-06-15T13:15:25+00:00" + "time": "2020-10-26T13:12:34+00:00" }, { "name": "sebastian/object-reflector", - "version": "2.0.1", + "version": "2.0.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/object-reflector.git", - "reference": "14e04b3c25b821cc0702d4837803fe497680b062" + "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/14e04b3c25b821cc0702d4837803fe497680b062", - "reference": "14e04b3c25b821cc0702d4837803fe497680b062", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", + "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", "shasum": "" }, "require": { - "php": "^7.3" + "php": ">=7.3" }, "require-dev": { - "phpunit/phpunit": "^9.0" + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { @@ -3377,27 +3578,27 @@ "type": "github" } ], - "time": "2020-06-15T13:08:02+00:00" + "time": "2020-10-26T13:14:26+00:00" }, { "name": "sebastian/recursion-context", - "version": "4.0.1", + "version": "4.0.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "a32789e5f0157c10cf216ce6c5136db12a12b847" + "reference": "cd9d8cf3c5804de4341c283ed787f099f5506172" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/a32789e5f0157c10cf216ce6c5136db12a12b847", - "reference": "a32789e5f0157c10cf216ce6c5136db12a12b847", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/cd9d8cf3c5804de4341c283ed787f099f5506172", + "reference": "cd9d8cf3c5804de4341c283ed787f099f5506172", "shasum": "" }, "require": { - "php": "^7.3" + "php": ">=7.3" }, "require-dev": { - "phpunit/phpunit": "^9.0" + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { @@ -3436,24 +3637,24 @@ "type": "github" } ], - "time": "2020-06-15T13:06:44+00:00" + "time": "2020-10-26T13:17:30+00:00" }, { "name": "sebastian/resource-operations", - "version": "3.0.1", + "version": "3.0.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/resource-operations.git", - "reference": "71421c1745788de4facae1b79af923650bd3ec15" + "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/71421c1745788de4facae1b79af923650bd3ec15", - "reference": "71421c1745788de4facae1b79af923650bd3ec15", + "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", + "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", "shasum": "" }, "require": { - "php": "^7.3" + "php": ">=7.3" }, "require-dev": { "phpunit/phpunit": "^9.0" @@ -3487,32 +3688,32 @@ "type": "github" } ], - "time": "2020-06-15T13:17:14+00:00" + "time": "2020-09-28T06:45:17+00:00" }, { "name": "sebastian/type", - "version": "2.1.0", + "version": "2.3.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/type.git", - "reference": "bad49207c6f854e7a25cef0ea948ac8ebe3ef9d8" + "reference": "81cd61ab7bbf2de744aba0ea61fae32f721df3d2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/bad49207c6f854e7a25cef0ea948ac8ebe3ef9d8", - "reference": "bad49207c6f854e7a25cef0ea948ac8ebe3ef9d8", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/81cd61ab7bbf2de744aba0ea61fae32f721df3d2", + "reference": "81cd61ab7bbf2de744aba0ea61fae32f721df3d2", "shasum": "" }, "require": { - "php": "^7.3" + "php": ">=7.3" }, "require-dev": { - "phpunit/phpunit": "^9.2" + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.1-dev" + "dev-master": "2.3-dev" } }, "autoload": { @@ -3539,24 +3740,24 @@ "type": "github" } ], - "time": "2020-06-01T12:21:09+00:00" + "time": "2020-10-26T13:18:59+00:00" }, { "name": "sebastian/version", - "version": "3.0.0", + "version": "3.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/version.git", - "reference": "0411bde656dce64202b39c2f4473993a9081d39e" + "reference": "c6c1022351a901512170118436c764e473f6de8c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/0411bde656dce64202b39c2f4473993a9081d39e", - "reference": "0411bde656dce64202b39c2f4473993a9081d39e", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c6c1022351a901512170118436c764e473f6de8c", + "reference": "c6c1022351a901512170118436c764e473f6de8c", "shasum": "" }, "require": { - "php": "^7.3" + "php": ">=7.3" }, "type": "library", "extra": { @@ -3582,24 +3783,30 @@ ], "description": "Library that helps with managing the version number of Git-hosted PHP projects", "homepage": "https://github.com/sebastianbergmann/version", - "time": "2020-01-21T06:36:37+00:00" + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T06:39:44+00:00" }, { "name": "symfony/polyfill-ctype", - "version": "v1.17.0", + "version": "v1.20.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "e94c8b1bbe2bc77507a1056cdb06451c75b427f9" + "reference": "f4ba089a5b6366e453971d3aad5fe8e897b37f41" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/e94c8b1bbe2bc77507a1056cdb06451c75b427f9", - "reference": "e94c8b1bbe2bc77507a1056cdb06451c75b427f9", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/f4ba089a5b6366e453971d3aad5fe8e897b37f41", + "reference": "f4ba089a5b6366e453971d3aad5fe8e897b37f41", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=7.1" }, "suggest": { "ext-ctype": "For best performance" @@ -3607,7 +3814,11 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.17-dev" + "dev-main": "1.20-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" } }, "autoload": { @@ -3654,27 +3865,27 @@ "type": "tidelift" } ], - "time": "2020-05-12T16:14:59+00:00" + "time": "2020-10-23T14:02:19+00:00" }, { "name": "theseer/tokenizer", - "version": "1.1.3", + "version": "1.2.0", "source": { "type": "git", "url": "https://github.com/theseer/tokenizer.git", - "reference": "11336f6f84e16a720dae9d8e6ed5019efa85a0f9" + "reference": "75a63c33a8577608444246075ea0af0d052e452a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/theseer/tokenizer/zipball/11336f6f84e16a720dae9d8e6ed5019efa85a0f9", - "reference": "11336f6f84e16a720dae9d8e6ed5019efa85a0f9", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/75a63c33a8577608444246075ea0af0d052e452a", + "reference": "75a63c33a8577608444246075ea0af0d052e452a", "shasum": "" }, "require": { "ext-dom": "*", "ext-tokenizer": "*", "ext-xmlwriter": "*", - "php": "^7.0" + "php": "^7.2 || ^8.0" }, "type": "library", "autoload": { @@ -3694,24 +3905,30 @@ } ], "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", - "time": "2019-06-13T22:48:21+00:00" + "funding": [ + { + "url": "https://github.com/theseer", + "type": "github" + } + ], + "time": "2020-07-12T23:59:07+00:00" }, { "name": "webmozart/assert", - "version": "1.9.0", + "version": "1.9.1", "source": { "type": "git", "url": "https://github.com/webmozarts/assert.git", - "reference": "9dc4f203e36f2b486149058bade43c851dd97451" + "reference": "bafc69caeb4d49c39fd0779086c03a3738cbb389" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/webmozarts/assert/zipball/9dc4f203e36f2b486149058bade43c851dd97451", - "reference": "9dc4f203e36f2b486149058bade43c851dd97451", + "url": "https://api.github.com/repos/webmozarts/assert/zipball/bafc69caeb4d49c39fd0779086c03a3738cbb389", + "reference": "bafc69caeb4d49c39fd0779086c03a3738cbb389", "shasum": "" }, "require": { - "php": "^5.3.3 || ^7.0", + "php": "^5.3.3 || ^7.0 || ^8.0", "symfony/polyfill-ctype": "^1.8" }, "conflict": { @@ -3743,7 +3960,7 @@ "check", "validate" ], - "time": "2020-06-16T10:16:42+00:00" + "time": "2020-07-08T17:02:28+00:00" } ], "aliases": [], From f9b3094b12bd04b876f06c7dd8a9dcebedf1ba31 Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Thu, 5 Oct 2023 10:33:26 +0700 Subject: [PATCH 33/73] fix: Add 301 permanent redirects --- .htaccess | 26 ++++++++++++-------------- _legacy/.htaccess | 2 +- archive/.htaccess | 3 +-- go/desktop/.htaccess | 2 +- go/developer/.htaccess | 2 +- 5 files changed, 16 insertions(+), 19 deletions(-) diff --git a/.htaccess b/.htaccess index 3c873826..0c054fa6 100644 --- a/.htaccess +++ b/.htaccess @@ -14,29 +14,29 @@ RewriteBase / # but only if on a live site (keyman.com) and not # matching `/.well-known/(.*)$` (for Let's Encrypt) - Redirect "/" "https://keyman.com" + Redirect 301 "/" "https://keyman.com" # Custom error messages # ErrorDocument 404 /_includes/errors/404.php -# TODO: Add 301 permanent redirects, append query strings +# TODO: Append query strings 12x [QSA] # macosx and macos to mac (ignore case) -RedirectMatch "^(?i)/(macosx|macos)\b(.*)$" "/mac$2" +RedirectMatch 301 "^(?i)/(macosx|macos)\b(.*)$" "/mac$2" # Redirect deprecated Google Plus link -RedirectMatch "^(?i)/plus.*" "/" +RedirectMatch 301 "^(?i)/plus.*" "/" # /donate -> donate.keyman.com -RedirectMatch "^(?i)/donate(\/.*)?" "https://donate.keyman.com" +RedirectMatch 301 "^(?i)/donate(\/.*)?" "https://donate.keyman.com" # /privacy -> SIL Privacy policy -RedirectMatch "^(?i)/privacy(\/.*)?" "https://software.sil.org/language-software-privacy-policy/" +RedirectMatch 301 "^(?i)/privacy(\/.*)?" "https://software.sil.org/language-software-privacy-policy/" # desktop to windows -RedirectMatch "^(?i)/desktop(\/.*)?" "/windows$1" +RedirectMatch 301 "^(?i)/desktop(\/.*)?" "/windows$1" # releases-tier/download # note: the tier is currently ignored @@ -55,17 +55,15 @@ RedirectMatch "^downloads/releases/?$" "/downloads" # Cleanup various URLS with permanent redirects -# TODO: Permanent redirects 301? - # /keyboards/{install|download|share}/{id}/ to /keyboards/x/id # RedirectMatch "^keyboards/(install|download|share)/([^/]+)/$" "/keyboards/$1/$2" -RewriteRule "^keyboards/(install|download|share)/([^/]+)/$" "/keyboards/$1/$2" [R,L] +RewriteRule "^keyboards/(install|download|share)/([^/]+)/$" "/keyboards/$1/$2" [R=301,L] # /keyboards/{id}/ to /keyboards/id -RedirectMatch "^keyboards/([^/]+)/$" "/keyboards/$1" +RedirectMatch 301 "^keyboards/([^/]+)/$" "/keyboards/$1" # /keyboards/ to /keyboards -RedirectMatch "^keyboards/$" "/keyboards" +RedirectMatch 301 "^keyboards/$" "/keyboards" # Old share url /keyboards/{id}/share[/] to /keyboards/share/id RedirectMatch "^keyboards/(?!install|download|share)/share(/?)$" "/keyboards/share/$1" @@ -162,8 +160,8 @@ RedirectMatch "^/yoruba(/?)$" "/keyboards/sil_yoruba8" RedirectMatch "^/ancient-greek(/?)$" "/keyboards/h/greek" RedirectMatch "^/(french|german|italian|spanish|swedish)(/?)$" "/keyboards/h/eurolatin" -# dedicated-keyboard-landing pages TODO: [R=301] -RedirectMatch "^/(amharic|burmese|cameroon|ethiopic|eurolatin|greek|ipa|sinhala|tamil|tibetan|tigrigna|urdu)(/.*)?$" "/keyboards/h/$1$2" +# dedicated-keyboard-landing pages +RedirectMatch 301 "^/(amharic|burmese|cameroon|ethiopic|eurolatin|greek|ipa|sinhala|tamil|tibetan|tigrigna|urdu)(/.*)?$" "/keyboards/h/$1$2" # # PHP and Markdown rewriting diff --git a/_legacy/.htaccess b/_legacy/.htaccess index ac4b07bc..b03e4101 100644 --- a/_legacy/.htaccess +++ b/_legacy/.htaccess @@ -4,7 +4,7 @@ RedirectMatch "/_legacy/keyboards" "/keyboards/index.php" # legacy /keyboards/ to /keyboards -RedirectMatch "/_legacy/keyboards/" "/keyboards" +RedirectMatch 301 "/_legacy/keyboards/" "/keyboards" # legacy /keyboards/languages to /keyboards/index.php RedirectMatch "/_legacy/keyboards/languages/(.*)" "/keyboards/index.php?q=l:id:$1" diff --git a/archive/.htaccess b/archive/.htaccess index b465abd5..0599591b 100644 --- a/archive/.htaccess +++ b/archive/.htaccess @@ -1,4 +1,3 @@ # Redirect /archive/downloads.php" -# TODO: Permanent -RedirectMatch "/archive/downloads.php" "/downloads/archive/" +RedirectMatch 301 "/archive/downloads.php" "/downloads/archive/" diff --git a/go/desktop/.htaccess b/go/desktop/.htaccess index 81c358b8..c3893f6c 100644 --- a/go/desktop/.htaccess +++ b/go/desktop/.htaccess @@ -31,7 +31,7 @@ RedirectMatch "/go/desktop/([1-9][0-9]\.[0-9])/create-locale" "https://secure.ta # /go/desktop/X.Y/view-exception/ to /contact/exception" # This endpoint is not used in 14.0 or later -RedirectMatch "/go/desktop/1[0123]\.0/view-exception(/)?$" "/contact/exception.php" +RedirectMatch 301 "/go/desktop/1[0123]\.0/view-exception(/)?$" "/contact/exception.php" # /go/desktop/X.Y/view-exception?id=" diff --git a/go/developer/.htaccess b/go/developer/.htaccess index 83b73028..4f0053e1 100644 --- a/go/developer/.htaccess +++ b/go/developer/.htaccess @@ -21,7 +21,7 @@ RedirectMatch "/go/developer/([1-9][0-9]\.[0-9])/language-lookup" "https://www.e # "/go/developer/X.Y/view-exception/ to /contact/exception" -RedirectMatch "/go/developer/([1-9][0-9]\.[0-9])/view-exception(/)?$" "/contact/exception.php" +RedirectMatch 301 "/go/developer/([1-9][0-9]\.[0-9])/view-exception(/)?$" "/contact/exception.php" # "/go/developer/X.Y/view-exception?id=" From 10c79e5ab0d43e694f185729c997d839f6056311 Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Mon, 16 Oct 2023 08:48:23 +0700 Subject: [PATCH 34/73] chore: Remove shared sites files --- .gitignore | 5 + _common/JsonApiFailure.php | 23 - _common/KeymanHosts.php | 157 --- _common/KeymanSentry.php | 32 - _common/MarkdownHost.php | 83 -- _common/README.md | 16 - resources/builder.inc.sh | 1879 ------------------------------------ 7 files changed, 5 insertions(+), 2190 deletions(-) delete mode 100644 _common/JsonApiFailure.php delete mode 100644 _common/KeymanHosts.php delete mode 100644 _common/KeymanSentry.php delete mode 100644 _common/MarkdownHost.php delete mode 100644 _common/README.md delete mode 100755 resources/builder.inc.sh diff --git a/.gitignore b/.gitignore index 887faf22..43329935 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,8 @@ cdn/deploy/ vendor* /node_modules/ + +# Shared files are bootstrapped: +resources/bootstrap.inc.sh +resources/.bootstrap-version +_common/ diff --git a/_common/JsonApiFailure.php b/_common/JsonApiFailure.php deleted file mode 100644 index cbf1270f..00000000 --- a/_common/JsonApiFailure.php +++ /dev/null @@ -1,23 +0,0 @@ - $errorcode, 'message' => $message]; - echo json_encode($data, JSON_UNESCAPED_SLASHES); - exit; - } - - static function InvalidParameters($expected) { - self::Failure(400, JsonApiFailure::ERROR_InvalidParameters, "Invalid parameters passed to function (expected: $expected)"); - } - } \ No newline at end of file diff --git a/_common/KeymanHosts.php b/_common/KeymanHosts.php deleted file mode 100644 index b967eb4e..00000000 --- a/_common/KeymanHosts.php +++ /dev/null @@ -1,157 +0,0 @@ -tier; - } - - public static function Rebuild() { - self::$instance = new KeymanHosts(); - } - - /** - * Returns $contents after regex'ing the Keyman live hosts for Markdown files - * @param $contents - * @return $contents - */ - public function fixupHostReferences($contents) { - // Regex Keyman hosts - $contents = str_replace("https://s.keyman.com", $this->s_keyman_com, $contents); - $contents = str_replace("https://api.keyman.com", $this->api_keyman_com, $contents); - $contents = str_replace("https://help.keyman.com", $this->help_keyman_com, $contents); - $contents = str_replace("https://downloads.keyman.com", $this->downloads_keyman_com, $contents); - $contents = str_replace("https://keyman.com", $this->keyman_com, $contents); - $contents = str_replace("https://keymanweb.com", $this->keymanweb_com, $contents); - $contents = str_replace("https://r.keymanweb.com", $this->r_keymanweb_com, $contents); - $contents = str_replace("https://blog.keyman.com", $this->blog_keyman_com, $contents); - $contents = str_replace("https://donate.keyman.com", $this->donate_keyman_com, $contents); - $contents = str_replace("https://translate.keyman.com", $this->translate_keyman_com, $contents); - $contents = str_replace("https://sentry.keyman.com", $this->sentry_keyman_com, $contents); - - return $contents; - } - - function __construct() { - if(isset($_SERVER['KEYMANHOSTS_TIER']) && in_array($_SERVER['KEYMANHOSTS_TIER'], - [KeymanHosts::TIER_DEVELOPMENT, KeymanHosts::TIER_STAGING, - KeymanHosts::TIER_PRODUCTION, KeymanHosts::TIER_TEST])) { - $this->tier = $_SERVER['KEYMANHOSTS_TIER']; - } else if(file_exists(__DIR__ . '/../tier.txt')) { - $this->tier = trim(file_get_contents(__DIR__ . '/../tier.txt')); - } else { - $this->tier = KeymanHosts::TIER_DEVELOPMENT; - } - - switch($this->tier) { - // Not all these are currently used but helps to cleanup confusion - case KeymanHosts::TIER_PRODUCTION: - case KeymanHosts::TIER_STAGING: - $site_suffix = ''; - $site_protocol = 'https://'; - break; - case KeymanHosts::TIER_TEST: - $site_suffix = ''; - $site_protocol = 'http://'; - break; - case KeymanHosts::TIER_DEVELOPMENT: - $site_suffix = '.localhost'; - $site_protocol = 'http://'; - break; - default: - die("tier is '$this->tier' which is invalid\n"); - } - - // Append reverse-proxy port - if (isset($_SERVER['KEYMAN_COM_PROXY_PORT'])) { - $site_suffix .= ':'.$_SERVER['KEYMAN_COM_PROXY_PORT']; - } - - $this->blog_keyman_com = "https://blog.keyman.com"; - $this->donate_keyman_com = "https://donate.keyman.com"; - $this->translate_keyman_com = "https://translate.keyman.com"; - $this->sentry_keyman_com = "https://sentry.keyman.com"; - - if($this->tier == KeymanHosts::TIER_STAGING) { - // As we build more staging areas, change these over as well. Assumption that we'll stage across multiple sites is a - // little presumptuous but we can live with it. - $this->s_keyman_com = "https://s.keyman.com"; - $this->api_keyman_com = "https://api.keyman-staging.com"; - $this->help_keyman_com = "https://help.keyman-staging.com"; - $this->downloads_keyman_com = "https://downloads.keyman.com"; - $this->keyman_com = "https://keyman-staging.com"; - $this->keymanweb_com = "https://keymanweb.com"; - $this->r_keymanweb_com = "https://r.keymanweb.com"; - } else if($this->tier == KeymanHosts::TIER_TEST) { - $this->s_keyman_com = "https://s.keyman.com"; - $this->api_keyman_com = "https://api.keyman.com"; - $this->help_keyman_com = "https://help.keyman.com"; - $this->downloads_keyman_com = "https://downloads.keyman.com"; - $this->keyman_com = "http://host.docker.internal:8053"; // Unique for keyman.com - $this->keymanweb_com = "https://keymanweb.com"; - $this->r_keymanweb_com = "https://r.keymanweb.com"; - } else if($this->tier == KeymanHosts::TIER_DEVELOPMENT) { - // Locally running sites via Docker need to access "host.docker.internal:[port]" - $this->s_keyman_com = "{$site_protocol}s.keyman.com{$site_suffix}"; - $this->api_keyman_com = "http://host.docker.internal:8058"; - $this->help_keyman_com = "http://host.docker.internal:8055"; - $this->downloads_keyman_com = "https://downloads.keyman.com"; // local dev domain is usually not available - $this->keyman_com = "http://host.docker.internal:8053"; - $this->keymanweb_com = "http://host.docker.internal:8057"; - $this->r_keymanweb_com = "https://r.keymanweb.com"; /// local dev domain is usually not available - } else { - // TODO: allow override of these with e.g. KEYMANHOSTS_API_KEYMAN_COM='https://api.keyman.com'; - $this->s_keyman_com = "{$site_protocol}s.keyman.com{$site_suffix}"; - $this->api_keyman_com = "{$site_protocol}api.keyman.com{$site_suffix}"; - $this->help_keyman_com = "{$site_protocol}help.keyman.com{$site_suffix}"; - $this->downloads_keyman_com = "https://downloads.keyman.com"; // local dev domain is usually not available - $this->keyman_com = "{$site_protocol}keyman.com{$site_suffix}"; - $this->keymanweb_com = "{$site_protocol}keymanweb.com{$site_suffix}"; - $this->r_keymanweb_com = "https://r.keymanweb.com"; /// local dev domain is usually not available - } - - $this->blog_keyman_com_host = preg_replace('/^http(s)?:\/\/(.+)$/', '$2', $this->blog_keyman_com); - $this->s_keyman_com_host = preg_replace('/^http(s)?:\/\/(.+)$/', '$2', $this->s_keyman_com); - $this->api_keyman_com_host = preg_replace('/^http(s)?:\/\/(.+)$/', '$2', $this->api_keyman_com); - $this->help_keyman_com_host = preg_replace('/^http(s)?:\/\/(.+)$/', '$2', $this->help_keyman_com); - $this->downloads_keyman_com_host = preg_replace('/^http(s)?:\/\/(.+)$/', '$2', $this->downloads_keyman_com); - $this->keyman_com_host = preg_replace('/^http(s)?:\/\/(.+)$/', '$2', $this->keyman_com); - $this->keymanweb_com_host = preg_replace('/^http(s)?:\/\/(.+)$/', '$2', $this->keymanweb_com); - $this->r_keymanweb_com_host = preg_replace('/^http(s)?:\/\/(.+)$/', '$2', $this->r_keymanweb_com); - $this->donate_keyman_com_host = preg_replace('/^http(s)?:\/\/(.+)$/', '$2', $this->donate_keyman_com); - $this->translate_keyman_com_host = preg_replace('/^http(s)?:\/\/(.+)$/', '$2', $this->translate_keyman_com); - $this->sentry_keyman_com_host = preg_replace('/^http(s)?:\/\/(.+)$/', '$2', $this->sentry_keyman_com); - } - } diff --git a/_common/KeymanSentry.php b/_common/KeymanSentry.php deleted file mode 100644 index b69efc5b..00000000 --- a/_common/KeymanSentry.php +++ /dev/null @@ -1,32 +0,0 @@ - $dsn, - 'environment' => $environment - ]); - } - } \ No newline at end of file diff --git a/_common/MarkdownHost.php b/_common/MarkdownHost.php deleted file mode 100644 index 517c52fa..00000000 --- a/_common/MarkdownHost.php +++ /dev/null @@ -1,83 +0,0 @@ -pagetitle; - } - - function Content() { - return $this->content; - } - - function __construct($file) { - $this->pagetitle = 'TODO'; // If page title is not set, this hints to the developer to fix it - - $file = realpath(__DIR__ . '/../') . DIRECTORY_SEPARATOR . $file; - $contents = trim(file_get_contents($file)); - $contents = str_replace("\r\n", "\n", $contents); - - $contents = KeymanHosts::Instance()->fixupHostReferences($contents); - - // This header specification comes from YAML originally and is not common across - // markdown implementations. While Parsedown does not currently parse this out, - // it seems a sensible approach to use. The header section is delineated by `---` - // and `---` must be the first three characters of the file (no BOM!); note that - // the full spec supports metadata sections anywhere but we only support top-of-file. - // - // Currently we support only the 'title' and 'redirect' keywords. - // - // title: must be a plain text title - // redirect: must be a relative or absolute url - // - // --- - // keyword: content - // keyword: content - // --- - // - // source: https://yaml.org/spec/1.2/spec.html#id2760395 - // source: https://pandoc.org/MANUAL.html#extension-yaml_metadata_block - // - - $lines = explode("\n", $contents); - - $found = count($lines) > 3 && rtrim($lines[0]) == '---'; - $headers = []; - for($i = 1; $i < count($lines); $i++) { - if($lines[$i] == '---') break; - if(!preg_match('/^([a-z0-9_-]+):(.+)$/', $lines[$i], $match)) { - $found = false; - break; - } else { - $headers[$match[1]] = trim($match[2]); - } - } - $found = $found && $i < count($lines); - - if($found) $contents = implode("\n", array_slice($lines, $i)); - - if(isset($headers['redirect'])) { - header("Location: {$headers['redirect']}"); - exit; - } - - $this->pagetitle = isset($headers['title']) ? $headers['title'] : 'Untitled'; - - // Performs the parsing + prettification of Markdown for display through PHP. - $Parsedown = new \ParsedownExtra(); - - // Does the magic. - $this->content = - "

" . htmlentities($this->pagetitle) . "

\n" . - "
" . - $Parsedown->text($contents) . - "
"; - } - } - diff --git a/_common/README.md b/_common/README.md deleted file mode 100644 index 64139980..00000000 --- a/_common/README.md +++ /dev/null @@ -1,16 +0,0 @@ -# Common Files - -These files are common to keyman.com sites. They must be kept identical to each other. - -## Namespace - -The root namespace for all PHP modules is `Keyman\Site\Common`. - -## Validation - -`composer test` on api.keyman.com will compare the contents of the `_common` folder across -keyman.com, api.keyman.com and help.keyman.com (and in future, other sites), if the -corresponding folders can be found. Currently, this test assumes that each site is in -a sibling folder with corresponding name (e.g. `~/keyman/sites/keyman.com`, -`~/keyman/sites/api.keyman.com`, etc), so the test will be skipped in CI at this time -(especially as the development cycle may be out of sync for the sites). diff --git a/resources/builder.inc.sh b/resources/builder.inc.sh deleted file mode 100755 index 6a47cbd5..00000000 --- a/resources/builder.inc.sh +++ /dev/null @@ -1,1879 +0,0 @@ -#!/usr/bin/env bash - -# Note: these two lines can be uncommented for debugging and profiling build -# scripts: -# -# set -x -# PS4='+ $EPOCHREALTIME $0 $LINENO ' -# - -# -# This script contains utilities for builder_script calls -# -# * builder_ functions and variables are defined here. -# * REPO_ROOT defines the top level of this repository -# * THIS_SCRIPT_PATH defines the full path of the running script -# * THIS_SCRIPT_NAME defines the basename of the running script -# * THIS_SCRIPT_IDENTIFIER defines the repo-relative path of the running script -# * _builder_ functions and variables are internal use only for builder.inc.sh, and -# subject to change at any time. Do not use them in other scripts. -# * Note: the running script is the top-level script that includes either -# builder.inc.sh directly, or, just in the Keyman repo, via build-utils.sh. -# - -# _builder_init is called internally at the bottom of this file after we have -# all function declarations in place. -function _builder_init() { - _builder_findRepoRoot - _builder_setBuildScriptIdentifiers - - if [[ -n "$TERM" ]] && [[ "$TERM" != "dumb" ]] && [[ "$TERM" != "unknown" ]] && [ -t 1 ]; then - builder_use_color true - else - builder_use_color false - fi -} - -function _builder_findRepoRoot() { - # We don't need readlink here because our standard script prolog does a - # readlink -f already so we will have already escaped from any symlinks - REPO_ROOT="${BASH_SOURCE[0]%/*/*}" - readonly REPO_ROOT -} - -# Used to build script-related build variables useful for referencing the calling script -# and for prefixing `builder_finish_action` outputs in order to more clearly identify the calling -# script. -# -# Assumes that `THIS_SCRIPT` has been set, typically like this: -# -# ```bash -# ## START STANDARD BUILD SCRIPT INCLUDE -# # adjust relative paths as necessary -# THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")" -# . "${THIS_SCRIPT%/*}/resources/builder.inc.sh" -# ## END STANDARD BUILD SCRIPT INCLUDE -# ``` -# -function _builder_setBuildScriptIdentifiers() { - if [ ! -z ${THIS_SCRIPT+x} ]; then - THIS_SCRIPT_PATH="${THIS_SCRIPT%/*}" - readonly THIS_SCRIPT_PATH - THIS_SCRIPT_NAME="${THIS_SCRIPT##*/}" - readonly THIS_SCRIPT_NAME - # Leaves only the part of the path based upon REPO_ROOT. - THIS_SCRIPT_IDENTIFIER=${THIS_SCRIPT_PATH#"$REPO_ROOT/"} - readonly THIS_SCRIPT_IDENTIFIER - else - builder_die "THIS_SCRIPT not defined; builder.inc.sh has not been sourced with standard script include." - fi -} - -################################################################################ -# Standard build script functions for managing command line, actions and targets -################################################################################ - -# The following allows coloring of warning and error lines, but only works if there's a -# terminal attached, so not on the build machine. - -# Overrides default colorization of logging; can be used in command-line with -# --color or --no-color, or overridden as necessary on a per-script basis. -# -# Parameters -# 1: use_color true or false -builder_use_color() { - if $1; then - # Using esc codes instead of tput for performance - COLOR_RED='\x1b[31m' # $(tput setaf 1) - COLOR_GREEN='\x1b[32m' # $(tput setaf 2) - COLOR_YELLOW='\x1b[33m' # $(tput setaf 3) - COLOR_BLUE='\x1b[34m' # $(tput setaf 4) - COLOR_PURPLE='\x1b[35m' # $(tput setaf 5) - COLOR_TEAL='\x1b[36m' # $(tput setaf 6) - COLOR_WHITE='\x1b[38;5;252m' # $(tput setaf 252) - COLOR_BRIGHT_WHITE='\x1b[38;5;255m' # $(tput setaf 255) - COLOR_GREY='\x1b[90m' # $(tput setaf 8) - COLOR_RESET='\x1b(B\x1b[m' # $(tput sgr0) - # e.g. VSCode https://code.visualstudio.com/updates/v1_69#_setmark-sequence-support - BUILDER_BOLD='\x1b[1m' # $(tput bold) - HEADING_SETMARK='\x1b]1337;SetMark\x07' - # Used by `builder_display_usage` when marking special terms (actions, targets, options) - # in the plain-text description area. - BUILDER_TERM_START="$COLOR_BLUE" - BUILDER_TERM_END="$COLOR_RESET" - else - COLOR_RED= - COLOR_GREEN= - COLOR_YELLOW= - COLOR_BLUE= - COLOR_PURPLE= - COLOR_TEAL= - COLOR_WHITE= - COLOR_BRIGHT_WHITE= - COLOR_GREY= - COLOR_RESET= - BUILDER_BOLD= - HEADING_SETMARK= - BUILDER_TERM_START="<" - BUILDER_TERM_END=">" - fi -} - -# -# Wraps the input string in `builder_display_usage` with $BUILDER_TERM_START and -# $BUILDER_TERM_END -# -function builder_term() { - echo "${BUILDER_TERM_START}$*${BUILDER_TERM_END}" -} - -function builder_die() { - echo - if [[ $# -eq 0 ]]; then - builder_echo error "Unspecified error, aborting script" - else - builder_echo error "$*" - fi - echo - exit 1 -} - -function builder_warn() { - builder_echo warning "$*" -} - -function builder_heading() { - builder_echo heading "$*" -} - - -#################################################################################### -# -# builder_ functions for standard build script parameter and process management -# -#################################################################################### - - -builder_echo() { - local color=white message= mark= - if [[ $# -gt 1 && $1 =~ ^(white|grey|green|success|blue|heading|yellow|warning|red|error|purple|brightwhite|teal|debug|setmark)$ ]]; then - color="$1" - shift - fi - message="$*" - - if [[ ! -z ${COLOR_RED+x} ]]; then - case $color in - white) color="$COLOR_WHITE" ;; - grey) color="$COLOR_GREY" ;; - green|success) color="$COLOR_GREEN" ;; - blue|heading) color="$COLOR_BLUE" ;; - yellow|warning) color="$COLOR_YELLOW" ;; - red|error) color="$COLOR_RED" ;; - purple) color="$COLOR_PURPLE" ;; - brightwhite) color="$COLOR_BRIGHTWHITE" ;; - teal|debug) color="$COLOR_TEAL" ;; - setmark) mark="$HEADING_SETMARK" color="$COLOR_PURPLE" ;; - esac - - if builder_is_dep_build; then - echo -e "$mark$COLOR_GREY[$THIS_SCRIPT_IDENTIFIER]$COLOR_RESET $color$message$COLOR_RESET" - else - echo -e "$mark$BUILDER_BOLD$COLOR_BRIGHT_WHITE[$THIS_SCRIPT_IDENTIFIER]$COLOR_RESET $color$message$COLOR_RESET" - fi - else - # Cope with the case of pre-init message and just emit plain text - echo -e "$message" - fi -} - -builder_echo_debug() { - builder_echo debug "[DEBUG] $*" -} - -# -# builder_ names are reserved. -# _builder_ names are internal use and subject to change -# - -# -# builder_extra_params: string containing all parameters after '--' -# -builder_extra_params=() - -# returns 0 if first parameter is in the array passed as second parameter -# -# Usage: -# if _builder_item_in_array "item" "${array[@]}"; then ...; fi -# Parameters: -# 1: item item to search for in array -# 2: array bash array, e.g. array=(one two three) -_builder_item_in_array() { - local e match="$1" - shift - [[ -z "$match" ]] && return 1 - for e; do [[ "$e" == $match ]] && return 0; done - return 1 -} - -# -# Returns `0` if first parameter is in the array passed as second parameter, -# where the array may contain globs. -# -# ### Parameters -# -# * 1: `item` item to search for in array -# * 2: `array` bash array, e.g. `array=(one two three)` -# -# ### Example -# -# ```bash -# array=(foo bar it*) -# if _builder_item_in_glob_array "item" "${array[@]}"; then ...; fi -# ``` -# -_builder_item_in_glob_array() { - local e match="$1" - shift - [[ -z "$match" ]] && return 1 - for e; do [[ "$match" == $e ]] && return 0; done - return 1 -} - -# -# Expands a shorthand item into a full match from an array of possibilities; -# reports an error if there are ambiguous options. Note that this function -# returns the number of matches, so 0 = no match, 1 = a precise match. -# -# ### Parameters -# -# * 1: `item` item to search for in array, e.g. "t" -# * 2: `array` bash array, e.g. `array=(one two three)` -# -# ### Description -# -# Does a substring search by regex for -# -# ### Example -# -# ```bash -# actions=(clean configure build test) -# -# action=`_builder_expand_shorthand $1 "${actions[@]}"` && -# builder_die "Unrecognized parameter $1" || -# case $? in -# 1) echo "Parameter $1 matches {$action}" -# ;; -# *) builder_die "Parameter $1 has $? matches, could mean any of {$action}" -# esac -# ``` -# -_builder_expand_shorthand() { - local item=$1 - shift - local count=0 - local result= - local string= - for e; do - if [[ $e == $item ]]; then - # Exact match trumps substring matches - echo $item - return 1 - fi - if [[ $e == "$item"* ]]; then - count=$((count+1)) - if [[ $count == 2 ]]; then - string="$result, $e" - result=$item - elif [[ $count -gt 2 ]]; then - string="$string, $e" - else - result=$e - fi - fi - done - - if [[ $count -lt 2 ]]; then - echo $result - else - echo $string - fi - return $count -} - - -_builder_item_is_target() { - local item="$1" - [[ $item =~ ^: ]] && return 1 - return 0 -} - -function _builder_warn_if_incomplete() { - if [ -n "${_builder_current_action}" ]; then - builder_echo warning "$_builder_current_action never reported success or failure" - # exit 1 # If we wanted this scenario to result in a forced build-script fail. - fi - - # Since we've already warned about this once, we'll clear the variable to prevent repetitions. - _builder_current_action= -} - -# Used by a `trap` statement later to facilitate auto-reporting failures on error detection -# without obscuring failure exit/error codes. -_builder_failure_trap() { - local trappedExitCode=$? - local action target - - _builder_cleanup_deps - - # Since 'exit' is also trapped, we can also handle end-of-script incomplete actions. - if [[ $trappedExitCode == 0 ]]; then - # While there weren't errors, were there any actions that never reported success or failure? - _builder_warn_if_incomplete - return - fi - - # If we've reached this point, we're here because an error occurred. - - # Iterate across currently-active actions and report their failures. - if [ -n "${_builder_current_action}" ]; then - action="${_builder_current_action}" - if [[ $action =~ : ]]; then - IFS=: read -r action target <<< "$action" - target=:$target - else - target=:project - fi - - builder_finish_action failure $action$target - fi - - # Make 100% sure that the exit code chains fully. - # Without this, nested scripts have failed to chain errors from npm calls past the script - # that directly executed the failed npm command. - exit $trappedExitCode -} - -# -# Removes temporary `_builder_deps_built` file when top-level build script -# finishes. -# -_builder_cleanup_deps() { - if ! builder_is_dep_build && ! builder_is_child_build && [[ ! -z ${_builder_deps_built+x} ]]; then - if $_builder_debug_internal; then - builder_echo_debug "Dependencies that were built:" - cat "$_builder_deps_built" - fi - rm -f "$_builder_deps_built" - _builder_deps_built= - fi -} - -#------------------------------------------------------------------------------------------ -# Child scripts -#------------------------------------------------------------------------------------------ - -_builder_execute_child() { - local action=$1 - local target=$2 - - local script="$THIS_SCRIPT_PATH/${_builder_target_paths[$target]}/build.sh" - - if $_builder_debug_internal; then - builder_echo heading "## $action$target starting..." - fi - - # Build array of specified inheritable options - local child_options=() - local opt - for opt in "${_builder_options_inheritable[@]}"; do - if builder_has_option $opt; then - child_options+=($opt) - fi - done - - "$script" $action \ - --builder-child \ - $_builder_build_deps \ - ${child_options[@]} \ - $builder_verbose \ - $builder_debug \ - && ( - if $_builder_debug_internal; then - builder_echo success "## $action$target completed successfully" - fi - ) || ( - result=$? - builder_echo error "## $action$target failed with exit code $result" - exit $result - ) || exit $? # Required due to above subshell masking exit -} - -_builder_run_child_action() { - local action="$1" target - - if [[ $action =~ : ]]; then - IFS=: read -r action target <<< "$action" - target=:$target - else - target=':*' - fi - - if builder_has_action $action$target; then - if [[ $target == ':*' ]]; then - # run all children in order specified in builder_describe - for target in "${_builder_targets[@]}"; do - # We have to re-test the action because the user may not - # have specified all targets in their invocation - if builder_has_action $action$target; then - if [[ ! -z ${_builder_target_paths[$target]+x} ]] && - [[ -f "$THIS_SCRIPT_PATH/${_builder_target_paths[$target]}/build.sh" ]]; then - _builder_execute_child $action $target - fi - fi - done - else - # If specified explicitly, we assume existence of a child build script. - _builder_execute_child $action $target - fi - fi -} - -# -# Executes the specified actions on all child targets, or on the specified -# targets. A child target is any target which has a sub-folder of the same name -# as the target. However, the actions will only be run if they have been -# specified by the user on the command-line. -# -# ### Usage -# -# ```bash -# builder_run_child_actions action1 [...] -# ``` -# -# ### Parameters -# -# 1...: action[:target] name of action:target to run -# -# ### Example -# -# ```bash -# builder_run_child_actions configure build test install -# ``` -# -builder_run_child_actions() { - while [[ $# -gt 0 ]]; do - local action="$1" - _builder_run_child_action "$action" - shift - done -} - -#------------------------------------------------------------------------------------------ -# Various API endpoints -#------------------------------------------------------------------------------------------ - -# -# Builds the standardized `action:target` string for the specified action-target -# pairing and also returns 0 if the user has asked to perform it on the command -# line. Otherwise, returns 0 and sets an empty string in place of the matched -# pair. -# -# The string will be set as `_builder_matched_action`, which is for -# builder.inc.sh internal use, used by `builder_start_action`. -# -# ### Usage -# -# ```bash -# if build_has_action action[:target]; then ...; fi -# ```` -# -# ### Parameters -# -# 1: action[:target] name of action:target -# -# ### Example -# -# ```bash -# if builder_has_action build:app; then ... -# ``` -# -builder_has_action() { - local action="$1" target - - if [[ $action =~ : ]]; then - IFS=: read -r action target <<< "$action" - target=:$target - else - target=':*' - fi - - if _builder_item_in_array "$action$target" "${_builder_chosen_action_targets[@]}"; then - # To avoid WET re-processing of the $action$target string set - _builder_matched_action="$action$target" - if [[ $target == ':*' ]]; then - _builder_matched_action_name="$action" - else - _builder_matched_action_name="$action$target" - fi - return 0 - else - _builder_matched_action= - return 1 - fi -} - -# -# Wraps builder_start_action and builder_finish action for single-command -# actions. Can be used together with a local function for multi-command actions. -# Do be aware that this pseudo-closure style cannot be mixed with operators such -# as `<`, `>`, `&&`, `;`, `()` and so on. -# -# ### Usage -# -# ```bash -# builder_run_action action[:target] command [command-params...] -# ``` -# -# ### Parameters -# -# * 1: `action[:target]` name of action, and optionally also target, if target -# excluded starts for all defined targets -# * 2: command command to run if action is started -# * 3...: command-params parameters for command -# -# ### Example -# -# ```bash -# function do_build() { -# mkdir -p build/cjs-src -# npm run build -# } -# -# builder_run_action clean rm -rf ./build/ ./tsconfig.tsbuildinfo -# builder_run_action configure verify_npm_setup -# builder_run_action build do_build -# ``` -# -function builder_run_action() { - local action=$1 - shift - if builder_start_action $action; then - ($@) - builder_finish_action success $action - fi - return 0 -} - -# -# Returns `0` if the user has asked to perform action on target on the command -# line, and then starts the action. Should be paired with -# `builder_finish_action`. -# -# ### Usage -# -# ```bash -# if builder_start_action action[:target]; then ...; fi -# ``` -# -# ### Parameters -# -# * 1: `action[:target]` name of action, and optionally also target, if -# target excluded starts for all defined targets -# -# ### Example -# -# ```bash -# if builder_start_action build:app; then ... -# ``` -# -builder_start_action() { - if builder_has_action $1; then - # In a dependency quick build (the default), determine whether we actually - # need to run this step. Uses data passed to builder_describe_outputs to - # verify whether a target output is present. - if builder_is_dep_build && - ! builder_is_full_dep_build && - _builder_dep_output_exists $_builder_matched_action; then - builder_echo "skipping $_builder_matched_action_name, up-to-date" - return 1 - fi - - builder_echo blue "## $_builder_matched_action_name starting..." - if [ -n "${_builder_current_action}" ]; then - _builder_warn_if_incomplete - fi - _builder_current_action="$_builder_matched_action" - - # Build dependencies as required - _builder_do_build_deps "$_builder_matched_action" - return 0 - else - return 1 - fi -} - -# -# Returns 0 if the user has --option on the command line -# -# Usage: -# if build_has_option option; then ...; fi -# Parameters: -# 1: option name of option, i.e. --option -# Example: -# if build_has_option --debug; then -# -builder_has_option() { - local option="$1" - - if _builder_item_in_array "$option" "${_builder_chosen_options[@]}"; then - return 0 - fi - return 1 -} - -# -# Trims leading and following whitespace from the input parameters -# -# ### Usage -# -# ```bash -# my_string="$(builder_trim "$my_string")" -# ``` -# -# ### Parameters -# -# * `my_string` An input string -# -builder_trim() { - local var="$*" - # remove leading whitespace characters - var="${var#"${var%%[![:space:]]*}"}" - # remove trailing whitespace characters - var="${var%"${var##*[![:space:]]}"}" - printf '%s' "$var" -} - -# -# Expands an in-repo-relative path to a repo-relative path. A path starting with -# `/` is expected to be relative to repo root, not filesystem root. Otherwise, -# it's relative to current script path, not current working directory. The -# returned path will not have a prefix `/`, and will be relative to -# `$KEYMAN_ROOT`. Assumes realpath is installed (brew coreutils on macOS). -# -_builder_expand_relative_path() { - local path="$1" - if [[ "$path" =~ ^/ ]]; then - echo "${path:1}" - else - realpath --canonicalize-missing --relative-to="$KEYMAN_ROOT" "$THIS_SCRIPT_PATH/$path" - fi -} - -# -# Expands an `[action][:target]` string, replacing missing values with `*`, -# for example: -# -# * `build` --> `build:*` -# * `build:app` --> `build:app` -# * `:app` --> `*:app` -# -# Supports multiple action:targets in the string -# -_builder_expand_action_target() { - local input="$1" target= action= - if [[ "$input" =~ : ]]; then - IFS=":" read -r action target <<< "$input" - else - action="$input" - fi - - if [[ -z "$action" ]]; then - action='*' - fi - if [[ -z "$target" ]]; then - target='*' - fi - - echo "$action:$target" -} - -_builder_expand_action_targets() { - local input=($1) e output=() - for e in "${input[@]}"; do - e="$(_builder_expand_action_target "$e")" - output+=("$e") - done - if [[ ${#output[@]} == 0 ]]; then - echo "*:*" - else - echo "${output[@]}" - fi -} - -_builder_child_base= -# -# Describes the path from the build script's working directory to the common subfolder -# containing child scripts / projects without defined custom paths. -# -# This function must be called to set the child base path before builder_describe is -# called in order to work correctly. Furthermore, note that this setting will be -# ignored by targets with custom paths. -# -# ### Usage -# -# ```bash -# builder_set_child_base path -# ``` -# -# ### Parameters -# -# * `path` The relative path from the directory containing the calling script to -# the base folder to use for child-project detection and resolution -# -builder_set_child_base() { - _builder_child_base="$1/" -} - -# -# Describes a build script, defines available parameters and their meanings. Use -# together with `builder_parse` to process input parameters. -# -# ### Usage -# -# ```bash -# builder_describe description param_desc... -# ``` -# -# ### Parameters -# -# * `description` A short description of what the script does. -# * `param_desc` Space separated name and description of parameter, e.g. -# `"build Builds the target"` -# This parameter may be repeated to describe all parameters. -# -# There are four types of parameters that may be specified: -# -# * **Option:** `"--option[,-o][+][=var] [One line description]"` -# -# All options must have a longhand form with two prefix hyphens, -# e.g. `--option`. The `,-o` shorthand form is optional. When testing if -# the option is set with `builder_has_option`, always use the longhand -# form. -# -# If `=var` is specified, then the next parameter will be a variable stored in -# `$var` for that option. e.g. `--option=opt` means `$opt` will have the value -# `"foo"` when the script is called for `--option foo`. -# -# If `+` is specified, then the option will be passed to child scripts. All -# child scripts _must_ accept this option, or they will fail. It is acceptable -# for the child script to declare the option but ignore it. However, the option -# will _not_ be passed to dependencies. -# -# * **Action**: `"action [One line description]"` -# -# Actions must be a single word, lower case. To specify an action as the -# default, append a `+` to the action name, e.g. `"test+ Test the project"`. -# If there is no default specified, then it will be `build`. -# -# * **Target:** `":target[=path] [One line description]"` -# -# A target always starts with colon, e.g. `:project`. If a folder exists with -# the same name as a target, then that automatically denotes the target as a -# "child project". This can simplify parent-child style scripts, using the -# [`builder_run_child_actions`] function. -# -# A child project with an alternate folder can also be specified by appending -# `=path` to the target definition, for example `:app=src/app`. Where -# possible, avoid differences in names of child projects and folders. -# -# * **Dependency:** `"@/path/to/dependency[:target] [action][:target] ..."`` -# -# A dependency always starts with `@`. The path to the dependency will be -# relative to the build script folder, or to the root of the repository, if -# the path starts with `/`, not to the root of the file system. It is an error -# to specify a dependency outside the repo root. -# -# Relative paths will be expanded to full paths, again, relative to the root -# of the repository. -# -# A dependency definition can include a target for that dependency, for -# example, `"@/core:arch"`. This would build only the ':arch' target for the -# core module. -# -# Dependencies may be limited to specific `action:target` pairs on the current -# script. If not specified, dependencies will be built for all actions on all -# targets. Either `action` or `:target` may be omitted, and multiple actions -# and targets may be specified, space separated. -# -builder_describe() { - _builder_record_function_call builder_describe - - _builder_description="$1" - _builder_actions=() - _builder_targets=() - _builder_options=() - _builder_deps=() # array of all dependencies for this script - _builder_options_inheritable=() # array of all options that should be passed to child scripts - _builder_default_action=build - declare -A -g _builder_params - declare -A -g _builder_options_short - declare -A -g _builder_options_var - declare -A -g _builder_dep_path # array of output files for action:target pairs - declare -A -g _builder_dep_related_actions # array of action:targets associated with a given dependency - declare -A -g _builder_internal_dep # array of internal action:targets dependency relationships - declare -A -g _builder_target_paths # array of target child project paths - declare -A -g _builder_dep_targets # array of :targets given for a specific dependency (comma separated if more than one) - shift - local sub=() - # describe each target, action, and option possibility - while [[ $# -gt 0 ]]; do - local key="$1" - local value="$key" - local description= - if [[ $key =~ [[:space:]] ]]; then - IFS=" " read -r -a sub <<< "$key" - value="${sub[0]}" - description="$(builder_trim "${sub[@]:1}")" - fi - - if [[ $value =~ ^: ]]; then - # Parameter is a target - local target_path= - if [[ $value =~ = ]]; then - # The target has a custom child project path - IFS="=" read -r -a sub <<< "$value" - target_path="${sub[@]:1}" - value="${sub[0]}" - if [[ ! -d "$THIS_SCRIPT_PATH/$target_path" ]]; then - builder_die "Target path '$target_path' for $value does not exist." - fi - else - # If the target name matches a folder name, implicitly - # make it available as a child project - if [[ -d "$THIS_SCRIPT_PATH/$_builder_child_base${value:1}" ]]; then - target_path="$_builder_child_base${value:1}" - fi - fi - _builder_targets+=($value) - if [[ ! -z "$target_path" ]]; then - _builder_target_paths[$value]="$target_path" - fi - elif [[ $value =~ ^@ ]]; then - # Parameter is a dependency - local dependency="${value:1}" - local dependency_target= # all targets - if [[ $dependency =~ : ]]; then - IFS=":" read -r dependency dependency_target <<< "$dependency" - dependency_target=":$dependency_target" - fi - - dependency="`_builder_expand_relative_path "$dependency"`" - _builder_deps+=($dependency) - _builder_dep_related_actions[$dependency]="$(_builder_expand_action_targets "$description")" - _builder_dep_targets[$dependency]="$dependency_target" - # We don't want to add deps to params, so shift+continue - shift - continue - elif [[ $value =~ ^-- ]]; then - # Parameter is an option - # Look for a shorthand version of the option - local option_var= - if [[ $value =~ = ]]; then - IFS="=" read -r -a sub <<< "$value" - option_var="${sub[@]:1}" - value="${sub[0]}" - fi - - local is_inheritable=false - - if [[ $value =~ \+$ ]]; then - # final + indicates that option is inheritable - is_inheritable=true - value="${value:0:-1}" - fi - - if [[ $value =~ , ]]; then - IFS="," read -r -a sub <<< "$value" - local option_long="${sub[0]}" - local option_short="${sub[@]:1}" - _builder_options+=($option_long) - if $is_inheritable; then - _builder_options_inheritable+=($option_long) - fi - _builder_options_short[$option_short]="$option_long" - if [[ ! -z "$option_var" ]]; then - _builder_options_var[$option_long]="$option_var" - fi - value="$option_long, $option_short" - else - _builder_options+=($value) - if $is_inheritable; then - _builder_options_inheritable+=($value) - fi - if [[ ! -z "$option_var" ]]; then - _builder_options_var[$value]="$option_var" - fi - fi - - if [[ ! -z $option_var ]]; then - value="$value $option_var" - fi - - else - # Parameter is an action - if [[ $value =~ \+$ ]]; then - # If the action name has a '+' suffix then it is the default action - value=${value//+} - _builder_default_action=$value - fi - _builder_actions+=($value) - fi - - if [[ -z "${description}" ]]; then - description=$(_builder_get_default_description "$value") - fi - _builder_params[${value}]="$description" - - shift - done - - # We'll always add a :project if no target is specified - if (( ! ${#_builder_targets[@]} )); then - _builder_targets+=(:project) - _builder_params[\:project]=$(_builder_get_default_description ":project") - fi -} - -# -# Defines an output file or folder expected to be present after successful -# completion of an action for a target. Used to skip actions for dependency -# builds. If `:target` is not provided, assumes `:project`. -# -# Relative paths are relative to script folder; absolute paths are relative -# to repository root, not filesystem root. -# -# ### Usage -# -# ```bash -# builder_describe_outputs action:target filename [...] -# ``` -# -# ### Parameters -# -# * 1: `action[:target]` action and/or target associated with file -# * 2: `filename` name of file or folder to check -# * 3+: ... repeat previous arguments for additional outputs -# -# ### Example -# -# ```bash -# builder_describe_outputs \ -# configure /node_modules \ -# build build/index.js -# ``` -# -function builder_describe_outputs() { - _builder_record_function_call builder_describe_outputs - - while [[ $# -gt 0 ]]; do - local key="$1" path="$2" action= target= - path="`_builder_expand_relative_path "$path"`" - - if [[ $key =~ : ]]; then - IFS=":" read -r action target <<< "$key" - target=":$target" - else - # Add dependency expected output file for all targets, as well as a - # wildcard target match - action="$key" - for target in "${_builder_targets[@]}"; do - _builder_dep_path[$action$target]="$path" - done - target=':*' - fi - _builder_dep_path[$action$target]="$path" - shift 2 - done - - _builder_define_default_internal_dependencies - - # We only want to define internal dependencies after both builder_parse and builder_describe_outputs have been called - if _builder_has_function_been_called builder_parse; then - _builder_add_chosen_action_target_dependencies - fi -} - -_builder_get_default_description() { - local description= - local value="$1" - # default descriptions for common build actions, targets, and options - case "$value" in - clean) description="remove build/ folder and build artifacts" ;; - configure) description="install dependencies, e.g. npm" ;; - build) description="build target(s)" ;; - test) description="run automated tests" ;; - :project) description="this project" ;; - :app) description="main app" ;; - :engine) description="engine module" ;; - :module) description="this module" ;; - :tools) description="build tools for this project" ;; - --debug) description="debug build" ;; - esac - echo "$description" -} - -_builder_parameter_error() { - local program="$1" - local type="$2" - local param="$3" - builder_echo red "$program: invalid $type: $param" - echo - builder_display_usage - exit 64 -} - -# -# Pre-initializes the color setting based on the options specified to a -# a build.sh script. This is called automatically during init. -# -# Parameters -# 1: "$@" all command-line arguments -# -_builder_check_color() { - # Process command-line arguments - while [[ $# -gt 0 ]] ; do - local key="$1" - - case "$key" in - --color) - builder_use_color true - ;; - --no-color) - builder_use_color false - ;; - esac - shift # past the processed argument - done -} - -# -# For every build action:target in _builder_chosen_action_targets, add -# its full internal dependency tree -# -_builder_add_chosen_action_target_dependencies() { - local action_target i=0 new_actions=() - - # Iterate through every action specified on command line; we use this loop - # style so that any new actions added here will also be iteratively checked - while (( $i < ${#_builder_chosen_action_targets[@]} )); do - action_target=${_builder_chosen_action_targets[$i]} - - # If we have an internal dependency for the chosen action:target pair - if [[ ! -z ${_builder_internal_dep[$action_target]+x} ]]; then - local dep_outputs=(${_builder_internal_dep[$action_target]}) dep_output - for dep_output in "${dep_outputs[@]}"; do - # If there is a defined output for this dependency - if [[ ! -z ${_builder_dep_path[$dep_output]+x} ]]; then - # If the output for the dependency is missing, or we have --force-deps - if [[ ! -e "$KEYMAN_ROOT/${_builder_dep_path[$dep_output]}" ]] || builder_is_full_dep_build; then - # Add the dependency to the chosen action:target list - if ! _builder_item_in_array "$dep_output" "${_builder_chosen_action_targets[@]}"; then - _builder_chosen_action_targets+=($dep_output) - new_actions+=($dep_output) - fi - fi - fi - done - fi - i=$((i + 1)) - done - - if [[ ${#new_actions[@]} -gt 0 ]]; then - if builder_is_full_dep_build; then - builder_echo "Automatically running all dependency actions due to --force-deps:" - else - builder_echo "Automatically running following required actions with missing outputs:" - fi - for e in "${new_actions[@]}"; do - builder_echo "* $e" - done - fi -} - -# -# If we have described outputs, then we will setup our -# default internal dependency chain: -# -# configure <- build <- (test,install,publish) -# -_builder_define_default_internal_dependencies() { - for target in "${_builder_targets[@]}"; do - _builder_define_default_internal_deps_for_target "$target" - done - - _builder_define_default_internal_deps_for_target ':*' -} - -_builder_define_default_internal_deps_for_target() { - local target=$1 - _builder_define_default_internal_dep "$target" configure build - _builder_define_default_internal_dep "$target" build test - _builder_define_default_internal_dep "$target" build install -} - -_builder_define_default_internal_dep() { - local target=$1 dep=$2 action=$3 - if _builder_item_in_array $dep "${_builder_actions[@]}" && - _builder_item_in_array $action "${_builder_actions[@]}"; then - [[ -z ${_builder_internal_dep[$action$target]+x} ]] && - _builder_internal_dep[$action$target]=$dep$target || - _builder_internal_dep[$action$target]="${_builder_internal_dep[$action$target]} $dep$target" - fi -} - -# -# Define a local dependency between one action:target and -# another. -# -# Usage: -# builder_describe_internal_dependency action:target depaction:deptarget ... -# Parameters: -# 1: action:target The action and target that has a dependency -# 2: depaction:deptarget The dependency action and target -# Example: -# builder_describe_internal_dependency \ -# mac:build mac-x86_64:build \ -# mac:build mac-arm64:build -# -# Note: actions and targets must be fully specified, and this _must_ -# be called before either builder_describe_outputs or builder_parse in -# order for dependencies to be resolved. -builder_describe_internal_dependency() { - while [[ $# -gt 0 ]]; do - local action_target=$1 dep_action_target=$2 - [[ -z ${_builder_internal_dep[$action_target]+x} ]] && - _builder_internal_dep[$action_target]=$dep_action_target || - _builder_internal_dep[$action_target]="${_builder_internal_dep[$action_target]} $dep_action_target" - shift 2 - done -} - -# Initializes a build.sh script, parses command line. Will abort the script if -# invalid parameters are passed in. Use together with builder_describe which -# sets up the possible command line parameters -# -# Usage: -# builder_parse "$@" -# Parameters -# 1: $@ command-line arguments -builder_parse() { - _builder_record_function_call builder_parse - - local exp=() - builder_extra_params=() - - while [[ $# -gt 0 ]] ; do - local action= target= - local key="$1" - if [[ $key == "--" ]]; then - shift - builder_extra_params=("$@") - break - fi - - if [[ $key =~ ^- ]]; then - exp+=($key) - else - # Expand comma separated values - if [[ $key =~ : ]]; then - IFS=: read -r action target <<< "$key" - else - action="$key" - target= - fi - - local actions targets - IFS=, read -r -a actions <<< "$action" - IFS=, read -r -a targets <<< "$target" - - if [[ "${#actions[@]}" -eq 0 ]]; then - # No actions, so must be at least one :target - for target in "${targets[@]}"; do - exp+=(:$target) - done - else - for action in "${actions[@]}"; do - if [[ "${#targets[@]}" -eq 0 ]]; then - # No :targets so just expand actions - exp+=($action) - else - # Actions:targets, expand them all - for target in "${targets[@]}"; do - exp+=($action:$target) - done - fi - done - fi - fi - - shift - done - - _builder_parse_expanded_parameters "${exp[@]}" -} - -_builder_parse_expanded_parameters() { - _builder_build_deps=--deps - builder_verbose= - builder_debug= - local _params=($@) - _builder_chosen_action_targets=() - _builder_chosen_options=() - _builder_current_action= - _builder_is_child=1 - - local n=0 - - # Process command-line arguments - while [[ $# -gt 0 ]] ; do - local key="$1" - local action= - local target= - local e has_action has_target has_option longhand_option - - if [[ $key =~ : ]]; then - IFS=: read -r action target <<< "$key" - target=:$target - else - action="$key" - target= - fi - - # Expand shorthand parameters - - new_action=$(_builder_expand_shorthand $action "${_builder_actions[@]}") || - case $? in - 1) - action=$new_action - ;; - *) - builder_warn "Parameter $action has $? matches, could mean any of {$new_action}" - exit 1 - ;; - esac - - new_target=$(_builder_expand_shorthand $target "${_builder_targets[@]}") || - case $? in - 1) - target=$new_target - ;; - *) - builder_warn "Parameter $target has $? matches, could mean any of {$new_target}" - exit 1 - ;; - esac - - _builder_item_in_array "$action" "${_builder_actions[@]}" && has_action=1 || has_action=0 - _builder_item_in_array "$target" "${_builder_targets[@]}" && has_target=1 || has_target=0 - - if (( has_action )) || (( has_target )); then - # Document parameter expansion for end use - _params[$n]=$action$target - fi - n=$((n + 1)) - - # Expand short -o to --option in options lookup - if [[ ! -z ${_builder_options_short[$key]+x} ]]; then - key=${_builder_options_short[$key]} - fi - _builder_item_in_array "$key" "${_builder_options[@]}" && has_option=1 || has_option=0 - - if (( has_action )) && (( has_target )); then - # apply the selected action and selected target - _builder_chosen_action_targets+=("$action$target") - elif (( has_action )); then - # apply the selected action to all targets - if [[ ! -z $target ]]; then - # A target was specified but is not valid - _builder_parameter_error "$0" target "$target" - fi - - for e in "${_builder_targets[@]}"; do - _builder_chosen_action_targets+=("$action$e") - done - elif (( has_target )); then - # apply the default action to the selected target - - if [[ ! -z $action ]]; then - # An action was specified but is not valid - _builder_parameter_error "$0" action "$action" - fi - - _builder_chosen_action_targets+=("$_builder_default_action$target") - elif (( has_option )); then - _builder_chosen_options+=("$key") - if [[ ! -z ${_builder_options_var[$key]+x} ]]; then - shift - if [[ $# -eq 0 ]]; then - _builder_parameter_error "$0" parameter "$key" - fi - # Set the variable associated with this option to the next parameter value - # A little bit of hoop jumping here to avoid issues with cygwin paths being - # corrupted too early in the game - local varname=${_builder_options_var[$key]} - declare -g $varname="$1" - fi - - else - case "$key" in - --help|-h) - builder_display_usage - exit 0 - ;; - --color) - builder_use_color true - ;; - --no-color) - builder_use_color false - ;; - --verbose|-v) - _builder_chosen_options+=(--verbose) - builder_verbose=--verbose - ;; - --debug|-d) - _builder_chosen_options+=(--debug) - builder_debug=--debug - ;; - --deps|--no-deps|--force-deps) - _builder_build_deps=$key - ;; - --builder-dep-parent) - # internal use parameter for dependency builds - identifier of parent script - shift - builder_dep_parent="$1" - ;; - --builder-child) - _builder_is_child=0 - ;; - --builder-report-dependencies) - # internal reporting function, ignores all other parameters - _builder_report_dependencies - ;; - *) - # script does not recognize anything of action or target form at this point. - _builder_parameter_error "$0" parameter "$key" - esac - fi - shift # past the processed argument - done - - if (( ! ${#_builder_chosen_action_targets[@]} )); then - for e in "${_builder_targets[@]}"; do - _builder_chosen_action_targets+=("$_builder_default_action$e") - done - fi - - # We only want to define internal dependencies after both builder_parse and builder_describe_outputs have been called - if _builder_has_function_been_called builder_describe_outputs; then - _builder_add_chosen_action_target_dependencies - fi - - if $_builder_debug_internal; then - builder_echo_debug "Selected actions and targets:" - for e in "${_builder_chosen_action_targets[@]}"; do - builder_echo_debug "* $e" - done - builder_echo_debug - builder_echo_debug "Selected options:" - for e in "${_builder_chosen_options[@]}"; do - builder_echo_debug "* $e" - done - fi - - if builder_is_dep_build; then - builder_echo setmark "dependency build, started by $builder_dep_parent" - builder_echo grey "build.sh parameters: <${_params[@]}>" - if [[ -z ${_builder_deps_built+x} ]]; then - builder_die "FATAL ERROR: Expected '_builder_deps_built' variable to be set" - fi - elif builder_is_child_build; then - builder_echo setmark "child build, parameters: <${_params[@]}>" - if [[ -z ${_builder_deps_built+x} ]]; then - builder_die "FATAL ERROR: Expected '_builder_deps_built' variable to be set" - fi - else - # This is a top-level invocation, so we want to track which dependencies - # have been built, so they don't get built multiple times. - builder_echo setmark "build.sh parameters: <${_params[@]}>" - if [[ ${#builder_extra_params[@]} -gt 0 ]]; then - builder_echo grey "build.sh extra parameters: <${builder_extra_params[@]}>" - fi - export _builder_deps_built=`mktemp` - fi - - if builder_is_debug_build; then - BUILDER_CONFIGURATION=debug - else - BUILDER_CONFIGURATION=release - fi - - # Now that we've successfully parsed options adhering to the _builder spec, we may activate our - # action_failure and action_hanging traps. (We don't want them active on scripts not yet using - # said script.) - # - # Note: if an error occurs within a script's function in a `set -e` script, it becomes an exit - # instead for the function's caller. So, we need both `err` and `exit` here. - # See https://medium.com/@dirk.avery/the-bash-trap-trap-ce6083f36700. - trap _builder_failure_trap err exit -} - -_builder_pad() { - local count=$1 - local text1=$2 - local text2=$3 - local fmt="%-${count}s%s\n" - printf $fmt "$text1" "$text2" -} - -builder_display_usage() { - local e program description - - # Minimum padding is 12 characters, increase this if necessary - # if you add other, longer, global options (like --verbose, --debug) - local width=12 - - for e in "${!_builder_params[@]}"; do - if (( ${#e} > $width )); then - width=${#e} - fi - done - - width=$((width + 6)) - - program="$(basename "$0")" - if [[ ! -z ${_builder_description+x} ]]; then - echo "Summary:" - echo " $_builder_description" - echo - fi - echo "Script Identifier:" - echo " $THIS_SCRIPT_IDENTIFIER" - echo - - echo "Usage:" - echo " $program [options...] [action][:target]..." - echo - echo "Actions: " - - for e in "${_builder_actions[@]}"; do - if _builder_item_in_glob_array "$e" "${_builder_params[@]}"; then - description="${_builder_params[$e]}" - else - description=$(_builder_get_default_description "$e") - fi - _builder_pad $width " $e" "$description" - done - - echo - echo "Targets: " - - for e in "${_builder_targets[@]}"; do - if _builder_item_in_glob_array "$e" "${_builder_params[@]}"; then - description="${_builder_params[$e]}" - else - description=$(_builder_get_default_description "$e") - fi - _builder_pad $width " $e" "$description" - done - - echo - echo "Options: " - - for e in "${!_builder_params[@]}"; do - if [[ $e =~ ^-- ]]; then - _builder_pad $width " $e" "${_builder_params[$e]}" - fi - done - - _builder_pad $width " --verbose, -v" "Verbose logging" - _builder_pad $width " --debug, -d" "Debug build" - _builder_pad $width " --color" "Force colorized output" - _builder_pad $width " --no-color" "Never use colorized output" - if builder_has_dependencies; then - _builder_pad $width " --deps" "Build dependencies if required (default)" - _builder_pad $width " --no-deps" "Skip build of dependencies" - _builder_pad $width " --force-deps" "Reconfigure and rebuild all dependencies" - fi - _builder_pad $width " --help, -h" "Show this help" - - echo - echo "Dependencies: " - - if builder_has_dependencies; then - for d in "${_builder_deps[@]}"; do - echo " $d" - done - else - echo " This module has no dependencies" - fi - - # Defined in `builder_use_color`; this assumes that said func has been called. - local c1=$BUILDER_TERM_START - local c0=$BUILDER_TERM_END - echo - echo -e "* Specify ${c1}action:target${c0} to run a specific ${c1}action${c0} against a specific ${c1}:target${c0}." - echo -e "* If ${c1}action${c0} is specified without a ${c1}target${c0} suffix, it will be applied to all ${c1}:target${c0}s." - echo -e "* If ${c1}:target${c0} is specified without an ${c1}action${c0} prefix, ${c1}$_builder_default_action:target${c0} will be inferred." - echo -e "* If no ${c1}action${c0}, ${c1}:target${c0}, or ${c1}action:target${c0} entries are specified, ${c1}$_builder_default_action${c0} will run on all ${c1}:target${c0}s." - echo -} - -builder_finish_action() { - local result="$1" - local action="$2" target action_name - - if [[ $action =~ : ]]; then - IFS=: read -r action target <<< "$action" - target=":$target" - else - target=':*' - fi - - if [[ "$target" == ":*" ]]; then - action_name="$action" - else - action_name="$action$target" - fi - - local matched_action="$action$target" - - if [[ "$matched_action" == "${_builder_current_action}" ]]; then - if [[ $result == success ]]; then - # Sanity check: if there is a described output for this action, does the corresponding - # file or directory exist now? - if _builder_dep_output_defined $matched_action && ! _builder_dep_output_exists "$matched_action"; then - builder_echo warning "Expected output: '${_builder_dep_path[$matched_action]}'." - builder_echo warning "## $action_name completed successfully, but output does not exist" - else - builder_echo success "## $action_name completed successfully" - fi - elif [[ $result == failure ]]; then - builder_echo error "## $action_name failed" - else - builder_echo error "## $action_name failed with message: $result" - fi - - # Remove $action$target from the array; it is no longer a current action - _builder_current_action= - else - builder_echo warning "reporting result of $action_name but the action was never started!" - fi -} - -#------------------------------------------------------------------------------------------ -# Dependencies -#------------------------------------------------------------------------------------------ - -_builder_dep_output_defined() { - if [[ ! -z ${_builder_dep_path[$1]+x} ]]; then - return 0 - else - return 1 - fi -} - -_builder_dep_output_exists() { - if _builder_dep_output_defined $1 && [[ -e "$KEYMAN_ROOT/${_builder_dep_path[$1]}" ]]; then - return 0 - else - return 1 - fi -} - -# -# Returns `0` if the dependency should be built for the given action:target -# -_builder_should_build_dep() { - local action_target="$1" - local dep="$2" - local related_actions=(${_builder_dep_related_actions[$dep]}) - - if [[ $action_target =~ ^clean ]]; then - # don't attempt to build dependencies for a 'clean' action - return 1 - fi - - if ! _builder_item_in_glob_array "$action_target" "${related_actions[@]}"; then - return 1 - fi - return 0 -} - -# -# Removes a dependency from the list of available dependencies -# -# Parameters: -# $1 path to dependency -# -builder_remove_dep() { - local dependency="$1" i - dependency="`_builder_expand_relative_path "$dependency"`" - - for i in "${!_builder_deps[@]}"; do - if [[ ${_builder_deps[i]} = $dependency ]]; then - unset '_builder_deps[i]' - fi - done - - # rebuild the array to remove the empty item - _builder_deps=( "${_builder_deps[@]}" ) -} - -# -# Configure and build all dependencies -# Later, may restrict by either action or target -# -_builder_do_build_deps() { - local action_target="$1" - - if [[ $_builder_build_deps == --no-deps ]]; then - # we've been asked to skip dependencies - return 0 - fi - - for dep in "${_builder_deps[@]}"; do - # Don't attempt to build dependencies that don't match the current - # action:target (wildcards supported for matches here) - if ! _builder_should_build_dep "$action_target" "$dep"; then - builder_echo "Skipping dependency $dep for $_builder_matched_action_name" - continue - fi - - # Only configure and build the dependency once per invocation - if builder_has_module_been_built "$dep"; then - continue - fi - - dep_target= - if [[ ! -z ${_builder_dep_targets[$dep]+x} ]]; then - # TODO: in the future split _builder_dep_targets into comma-separated - # array for multiple targets for a dep? - dep_target=${_builder_dep_targets[$dep]} - fi - - builder_set_module_has_been_built "$dep" - "$KEYMAN_ROOT/$dep/build.sh" "configure$dep_target" "build$dep_target" \ - $builder_verbose \ - $builder_debug \ - $_builder_build_deps \ - --builder-dep-parent "$THIS_SCRIPT_IDENTIFIER" && ( - if $_builder_debug_internal; then - builder_echo success "## Dependency $dep for $_builder_matched_action_name successfully" - fi - ) || ( - result=$? - builder_echo error "## Dependency failed with exit code $result" - exit $result - ) || exit $? # Required due to above subshell masking exit - done -} - -# -# returns `0` if we are in a dependency doing a build. -# -builder_is_dep_build() { - if [[ ! -z ${builder_dep_parent+x} ]]; then - return 0 - fi - return 1 -} - -# -# returns `0` if we are in a child script doing a build -# -builder_is_child_build() { - return $_builder_is_child -} - -# -# returns `0` if we should attempt to do quick builds in a dependency build, for -# example skipping `tsc -b` where a parent may also do it; corresponds to the -# `--deps` parameter (which is the default). -# -builder_is_quick_dep_build() { - if [[ $_builder_build_deps == --deps ]]; then - return 0 - fi - return 1 -} - -# -# returns `0` if we should do a full configure and build in a dependency build; -# corresponds to the `--force-deps`` parameter. -# -builder_is_full_dep_build() { - if [[ $_builder_build_deps == --force-deps ]]; then - return 0 - fi - return 1 -} - -# -# returns `0` if the current build script has at least one dependency. -# -builder_has_dependencies() { - if [[ ${#_builder_deps[@]} -eq 0 ]]; then - return 1 - fi - return 0 -} - -# -# Tests if a dependency module has been built already in the current script -# invocation; if not running in a builder context, always returns `1` (i.e. -# "false"). -# -# ### Usage -# -# ```bash -# builder_has_module_been_built dependency-name -# ``` -# -# ### Parameters -# -# * 1: `dependency-name` the `$SCRIPT_IDENTIFIER` of the dependency -# (repo-relative path without leading `/`); or for -# external dependencies, a path-like starting with -# `/external/`. -# -# ### Examples -# -# ```bash -# if builder_has_module_been_built common/web/keyman-version; then ... -# if builder_has_module_been_built /external/npm-ci; then ... -# ``` -# -builder_has_module_been_built() { - local module="$1" - - - if [[ -z ${_builder_deps_built+x} ]]; then - # not in a builder context, so we assume a build is needed - return 1 - fi - - if [[ -f $_builder_deps_built ]] && grep -qx "$module" $_builder_deps_built; then - # dependency history file contains the dependency module - return 0 - fi - return 1 -} - -# -# Updates the dependency module build state for the current script invocation; -# if not running in a builder context, a no-op. -# -# ### Usage -# -# ```bash -# builder_set_module_has_been_built dependency-name -# ``` -# -# ### Parameters -# -# * 1: `dependency-name` the `$SCRIPT_IDENTIFIER` of the dependency -# (repo-relative path without leading `/`); or for -# external dependencies, a path-like starting with -# `/external/`. -# -# ### Examples -# -# ```bash -# builder_set_module_has_been_built common/web/keyman-version -# builder_set_module_has_been_built /external/npm-ci -# ``` -# -builder_set_module_has_been_built() { - local module="$1" - - if [[ ! -z ${_builder_deps_built+x} ]]; then - echo "$module" >> $_builder_deps_built - fi -} - -# -# Reports on all described dependencies, then exits -# used by builder-controls.sh -# -_builder_report_dependencies() { - echo "${_builder_deps[@]}" - exit 0 -} - -#------------------------------------------------------------------------------------------ -# Utility functions -#------------------------------------------------------------------------------------------ - -# -# returns `0` if we should be verbose in output -# -builder_verbose() { - if [[ $builder_verbose == --verbose ]]; then - return 0 - fi - return 1 -} - -# -# returns `0` if we are doing a debug build -# -builder_is_debug_build() { - if [[ $builder_debug == --debug ]]; then - return 0 - fi - return 1 -} - -# -# Track whether functions have already been called; -# later we may use this to prevent multiple calls to, e.g. -# builder_describe -# - -_builder_function_calls=() - -_builder_record_function_call() { - local func=$1 - if _builder_has_function_been_called $1; then - # builder_die "ERROR: $func cannot be called more than once." - return 0 - fi - _builder_function_calls+=($1) -} - -_builder_has_function_been_called() { - local func=$1 - if _builder_item_in_array $1 "${_builder_function_calls[@]}"; then - return 0 - fi - return 1 -} - -# -# Initialize builder once all functions are declared -# -_builder_init -_builder_check_color "$@" - -# _builder_debug_internal flag can be used to emit verbose logs for builder itself, -# e.g.: -# _builder_debug_internal=true ./build.sh -# -if [ -z ${_builder_debug_internal+x} ]; then - _builder_debug_internal=false -fi - -if $_builder_debug_internal; then - builder_echo_debug "Command line: $0 $@" -fi From ca8335c584d2d30c999003e66cdfef6e5a5e0ca1 Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Mon, 16 Oct 2023 09:05:37 +0700 Subject: [PATCH 35/73] chore: Update build.sh to use bootstrapper --- build.sh | 128 ++++++++++--------------------------------------------- 1 file changed, 23 insertions(+), 105 deletions(-) diff --git a/build.sh b/build.sh index aaa7dafe..f855fc4c 100755 --- a/build.sh +++ b/build.sh @@ -1,33 +1,20 @@ #!/usr/bin/env bash -# -# Setup keyman.com site to run via Docker. -# -set -eu +## START STANDARD SITE BUILD SCRIPT INCLUDE +readonly THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")" +readonly BOOTSTRAP="$(dirname "$THIS_SCRIPT")/resources/bootstrap.inc.sh" +readonly BOOTSTRAP_VERSION=v0.3 +[ -f "$BOOTSTRAP" ] && source "$BOOTSTRAP" || source <(curl -fs https://raw.githubusercontent.com/keymanapp/shared-sites/$BOOTSTRAP_VERSION/bootstrap.inc.sh) +## END STANDARD SITE BUILD SCRIPT INCLUDE -## START STANDARD BUILD SCRIPT INCLUDE -# adjust relative paths as necessary -THIS_SCRIPT="$(greadlink -f "${BASH_SOURCE[0]}" 2>/dev/null || readlink -f "${BASH_SOURCE[0]}")" -. "$(dirname "$THIS_SCRIPT")/resources/builder.inc.sh" -## END STANDARD BUILD SCRIPT INCLUDE +readonly KEYMAN_CONTAINER_NAME=keyman-website +readonly KEYMAN_CONTAINER_DESC=keyman-com-app +readonly KEYMAN_IMAGE_NAME=keyman-website +readonly HOST_KEYMAN_COM=keyman.com.localhost -################################ Main script ################################ - -function _get_docker_image_id() { - echo "$(docker images -q keyman-website)" -} +source _common/keyman-local-ports.inc.sh +source _common/docker.inc.sh -function _get_docker_container_id() { - echo "$(docker ps -a -q --filter ancestor=keyman-website)" -} - -function _stop_docker_container() { - KEYMAN_CONTAINER=$(_get_docker_container_id) - if [ ! -z "$KEYMAN_CONTAINER" ]; then - docker container stop $KEYMAN_CONTAINER - else - echo "No Docker container to stop" - fi -} +################################ Main script ################################ builder_describe \ "Setup keyman.com site to run via Docker." \ @@ -40,86 +27,11 @@ builder_describe \ builder_parse "$@" + # This script runs from its own folder cd "$REPO_ROOT" -if builder_start_action configure; then - # Nothing to do - builder_finish_action success configure -fi - -if builder_start_action clean; then - # Stop and cleanup Docker containers and images used for the site - _stop_docker_container - - KEYMAN_CONTAINER=$(_get_docker_container_id) - if [ ! -z "$KEYMAN_CONTAINER" ]; then - docker container rm $KEYMAN_CONTAINER - else - echo "No Docker container to clean" - fi - - KEYMAN_IMAGE=$(_get_docker_image_id) - if [ ! -z "$KEYMAN_IMAGE" ]; then - docker rmi keyman-website - else - echo "No Docker image to clean" - fi - - builder_finish_action success clean -fi - -# Stop the Docker container -builder_run_action stop _stop_docker_container - -if builder_start_action build; then - # Download docker image. --mount option requires BuildKit - DOCKER_BUILDKIT=1 docker build -t keyman-website . - - builder_finish_action success build -fi - -if builder_start_action start; then - # Start the Docker container - - if [ -d vendor ]; then - builder_die "vendor folder is in the way. Please delete it" - fi - - if [ ! -z $(_get_docker_image_id) ]; then - if [[ $OSTYPE =~ msys|cygwin ]]; then - # Windows needs leading slashes for path - SITE_HTML="//$(pwd):/var/www/html/" - else - SITE_HTML="$(pwd):/var/www/html/" - fi - - docker run --rm -d -p 8053:80 -v ${SITE_HTML} \ - -e S_KEYMAN_COM=localhost:8054 \ - --name keyman-com-app \ - keyman-website - else - echo "${COLOR_RED}ERROR: Docker container doesn't exist. Run ./build.sh build first${COLOR_RESET}" - builder_finish_action fail start - fi - - # Skip if link already exists - if [ -L vendor ]; then - builder_echo "\nLink to vendor/ already exists" - else - # Create link to vendor/ folder - KEYMAN_CONTAINER=$(_get_docker_container_id) - if [ ! -z "$KEYMAN_CONTAINER" ]; then - docker exec -i $KEYMAN_CONTAINER sh -c "ln -s /var/www/vendor vendor && chown -R www-data:www-data vendor" - else - echo "No Docker container running to create link to vendor/" - fi - fi - - builder_finish_action success start -fi - -if builder_start_action test; then +function test_docker_container() { # TODO: lint tests set +e; set +o pipefail; @@ -128,6 +40,12 @@ if builder_start_action test; then grep -B 1 "BROKEN"; echo "Done checking links" +} + +builder_run_action configure bootstrap_configure +builder_run_action clean clean_docker_container $KEYMAN_IMAGE_NAME $KEYMAN_CONTAINER_NAME +builder_run_action stop stop_docker_container $KEYMAN_IMAGE_NAME $KEYMAN_CONTAINER_NAME +builder_run_action build build_docker_container $KEYMAN_IMAGE_NAME $KEYMAN_CONTAINER_NAME +builder_run_action start start_docker_container $KEYMAN_IMAGE_NAME $KEYMAN_CONTAINER_NAME $KEYMAN_CONTAINER_DESC $HOST_KEYMAN_COM $PORT_KEYMAN_COM - builder_finish_action success test -fi +builder_run_action test test_docker_container From 320e81d0300a02748c1ec61bbaf5a52587c080c5 Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Tue, 17 Oct 2023 10:41:44 +0700 Subject: [PATCH 36/73] chore: remove web.config files --- _legacy/web.config | 60 ------- android/app/web.config | 14 -- archive/web.config | 13 -- downloads/releases/web.config | 26 --- go/android/web.config | 23 --- go/desktop/web.config | 74 -------- go/developer/web.config | 80 --------- go/download/web.config | 16 -- go/ios/web.config | 23 --- go/linux/web.config | 38 ----- go/macos/web.config | 18 -- go/web.config | 75 --------- go/windows/web.config | 42 ----- iphone-and-ipad/app/web.config | 14 -- web.config | 298 --------------------------------- 15 files changed, 814 deletions(-) delete mode 100644 _legacy/web.config delete mode 100644 android/app/web.config delete mode 100644 archive/web.config delete mode 100644 downloads/releases/web.config delete mode 100644 go/android/web.config delete mode 100644 go/desktop/web.config delete mode 100644 go/developer/web.config delete mode 100644 go/download/web.config delete mode 100644 go/ios/web.config delete mode 100644 go/linux/web.config delete mode 100644 go/macos/web.config delete mode 100644 go/web.config delete mode 100644 go/windows/web.config delete mode 100644 iphone-and-ipad/app/web.config delete mode 100644 web.config diff --git a/_legacy/web.config b/_legacy/web.config deleted file mode 100644 index fe90836c..00000000 --- a/_legacy/web.config +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/android/app/web.config b/android/app/web.config deleted file mode 100644 index b511ba1a..00000000 --- a/android/app/web.config +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - \ No newline at end of file diff --git a/archive/web.config b/archive/web.config deleted file mode 100644 index 5ad18063..00000000 --- a/archive/web.config +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/downloads/releases/web.config b/downloads/releases/web.config deleted file mode 100644 index 79dd776e..00000000 --- a/downloads/releases/web.config +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/go/android/web.config b/go/android/web.config deleted file mode 100644 index a548c3c0..00000000 --- a/go/android/web.config +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - diff --git a/go/desktop/web.config b/go/desktop/web.config deleted file mode 100644 index 5c9cad1b..00000000 --- a/go/desktop/web.config +++ /dev/null @@ -1,74 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/go/developer/web.config b/go/developer/web.config deleted file mode 100644 index 54e75859..00000000 --- a/go/developer/web.config +++ /dev/null @@ -1,80 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/go/download/web.config b/go/download/web.config deleted file mode 100644 index 2c55cacf..00000000 --- a/go/download/web.config +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/go/ios/web.config b/go/ios/web.config deleted file mode 100644 index d0bc8857..00000000 --- a/go/ios/web.config +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - diff --git a/go/linux/web.config b/go/linux/web.config deleted file mode 100644 index 05c6e941..00000000 --- a/go/linux/web.config +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/go/macos/web.config b/go/macos/web.config deleted file mode 100644 index f0d1a5ab..00000000 --- a/go/macos/web.config +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/go/web.config b/go/web.config deleted file mode 100644 index 08fc8b50..00000000 --- a/go/web.config +++ /dev/null @@ -1,75 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/go/windows/web.config b/go/windows/web.config deleted file mode 100644 index f6b6fdf8..00000000 --- a/go/windows/web.config +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/iphone-and-ipad/app/web.config b/iphone-and-ipad/app/web.config deleted file mode 100644 index d853d806..00000000 --- a/iphone-and-ipad/app/web.config +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - \ No newline at end of file diff --git a/web.config b/web.config deleted file mode 100644 index cca1ebfa..00000000 --- a/web.config +++ /dev/null @@ -1,298 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - " - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - From 8f94aaa4ee3d0330567d8e24a85744d2c93e0e27 Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Tue, 17 Oct 2023 10:41:57 +0700 Subject: [PATCH 37/73] fix: downloads/releases redirect --- .htaccess | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.htaccess b/.htaccess index 0c054fa6..ef94fd82 100644 --- a/.htaccess +++ b/.htaccess @@ -46,7 +46,7 @@ RewriteRule "^downloads/releases/(alpha|beta|stable)/(.+)$" "/downloads/releases RewriteRule "^downloads/releases/(?!_version_downloads\b)(.+)$" "/downloads/releases/_version_downloads.php?version=$1" [R,END] # index -RedirectMatch "^downloads/releases/?$" "/downloads" +RewriteRule "^downloads/releases(\/)?$" "/downloads" [R,END] # From b61170ee192db310ad44592ccf499207371bca3c Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Tue, 17 Oct 2023 11:07:03 +0700 Subject: [PATCH 38/73] fix: Migrate .well-known/web.config --- .htaccess | 5 +++++ .well-known/web.config | 25 ------------------------- 2 files changed, 5 insertions(+), 25 deletions(-) delete mode 100644 .well-known/web.config diff --git a/.htaccess b/.htaccess index ef94fd82..8a8dadc8 100644 --- a/.htaccess +++ b/.htaccess @@ -17,9 +17,14 @@ RewriteBase / Redirect 301 "/" "https://keyman.com" +AddType application/json apple-app-site-association + # Custom error messages # ErrorDocument 404 /_includes/errors/404.php +# apple-app-site-association +RewriteRule "^.well-known/apple-app-site-association$" "/.well-known/apple-app-site-association.json" [L] +RewriteRule "^apple-app-site-association$" "/.well-known/apple-app-site-association.json" [L] # TODO: Append query strings 12x [QSA] diff --git a/.well-known/web.config b/.well-known/web.config deleted file mode 100644 index 712b4cb0..00000000 --- a/.well-known/web.config +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - From c242327c3bc96a75519effef44298a32a65f060b Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Wed, 18 Oct 2023 08:46:13 +0700 Subject: [PATCH 39/73] Apply suggestions from code review Co-authored-by: Marc Durdin --- build.sh | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/build.sh b/build.sh index f855fc4c..3882cd73 100755 --- a/build.sh +++ b/build.sh @@ -2,7 +2,7 @@ ## START STANDARD SITE BUILD SCRIPT INCLUDE readonly THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")" readonly BOOTSTRAP="$(dirname "$THIS_SCRIPT")/resources/bootstrap.inc.sh" -readonly BOOTSTRAP_VERSION=v0.3 +readonly BOOTSTRAP_VERSION=chore/v0.4 [ -f "$BOOTSTRAP" ] && source "$BOOTSTRAP" || source <(curl -fs https://raw.githubusercontent.com/keymanapp/shared-sites/$BOOTSTRAP_VERSION/bootstrap.inc.sh) ## END STANDARD SITE BUILD SCRIPT INCLUDE @@ -27,10 +27,6 @@ builder_describe \ builder_parse "$@" - -# This script runs from its own folder -cd "$REPO_ROOT" - function test_docker_container() { # TODO: lint tests set +e; From 9af6c5d918893e519a8a0a790a2441c2f1f5f132 Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Wed, 18 Oct 2023 10:37:02 +0700 Subject: [PATCH 40/73] chore: Fix pathing for cdnrefresh --- cdn/cdnrefresh.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cdn/cdnrefresh.php b/cdn/cdnrefresh.php index a6284a54..ca443ac3 100644 --- a/cdn/cdnrefresh.php +++ b/cdn/cdnrefresh.php @@ -15,7 +15,7 @@ function generate_hashed_version_dir($source, $deploy, $folder) { $d = opendir($folder); while(($f = readdir($d)) !== false) { if($f == '.' || $f == '..') continue; - $f = "$folder\\$f"; + $f = "$folder" . DIRECTORY_SEPARATOR . "$f"; if(is_dir($f)) { generate_hashed_version_dir($source, $deploy, $f); } else { @@ -36,7 +36,7 @@ function generate_hashed_version_file($source, $deploy, $source_file) { $dest_file = $source_file_short; } if(!file_exists($deploy . $dest_file)) { - echo $source_file . " => " . $deploy . $dest_file . "\n"; + echo $source_file . " => " . $deploy . $dest_file . "
"; // Copy the new hashed filename into the deploy folder copy($source_file, $deploy . $dest_file); @@ -53,8 +53,8 @@ function generate_hash($root, $resource_file) { global $resource_list; $resource_list = array(); - $deploy = $root . "\\deploy"; - $source = $root . "\\dev"; + $deploy = $root . DIRECTORY_SEPARATOR . "deploy"; + $source = $root . DIRECTORY_SEPARATOR . "dev"; if(!file_exists($deploy)) { mkdir($deploy); From a048a1b3b984bd1406d8d1f08874acf598316da6 Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Wed, 18 Oct 2023 10:37:14 +0700 Subject: [PATCH 41/73] chore: Generate cdn in init-container.sh --- .gitattributes | 3 +++ resources/init-container.sh | 7 +++++++ 2 files changed, 10 insertions(+) create mode 100644 .gitattributes create mode 100755 resources/init-container.sh diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..ab02d70e --- /dev/null +++ b/.gitattributes @@ -0,0 +1,3 @@ + +Dockerfile text eol=lf +*.sh eol=lf diff --git a/resources/init-container.sh b/resources/init-container.sh new file mode 100755 index 00000000..d9b40c4b --- /dev/null +++ b/resources/init-container.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash + +echo "---- Generating CDN ---" +rm -rf cdn/deploy +cd cdn +php -d include_path=/var/www/html/_includes:. cdnrefresh.php +cd .. From fa5cfa2f85c3f17ebd4acc0818f8e10878a3c0d1 Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Wed, 18 Oct 2023 10:41:40 +0700 Subject: [PATCH 42/73] chore: Cleanup CDN on clean action --- build.sh | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/build.sh b/build.sh index 3882cd73..6658e1dd 100755 --- a/build.sh +++ b/build.sh @@ -38,8 +38,16 @@ function test_docker_container() { echo "Done checking links" } +# Custom cleanup of CDN +function clean_docker_container_cdn() { + clean_docker_container $KEYMAN_IMAGE_NAME $KEYMAN_CONTAINER_NAME + + # Cleanup CDN + rm -rf cdn/deploy +} + builder_run_action configure bootstrap_configure -builder_run_action clean clean_docker_container $KEYMAN_IMAGE_NAME $KEYMAN_CONTAINER_NAME +builder_run_action clean clean_docker_container_cdn builder_run_action stop stop_docker_container $KEYMAN_IMAGE_NAME $KEYMAN_CONTAINER_NAME builder_run_action build build_docker_container $KEYMAN_IMAGE_NAME $KEYMAN_CONTAINER_NAME builder_run_action start start_docker_container $KEYMAN_IMAGE_NAME $KEYMAN_CONTAINER_NAME $KEYMAN_CONTAINER_DESC $HOST_KEYMAN_COM $PORT_KEYMAN_COM From be451111712f59b7fb65ef2d4e52c90ad2baa4ec Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Wed, 18 Oct 2023 11:05:45 +0700 Subject: [PATCH 43/73] chore: cleanup Revert clean and cdnrefresh line separator --- build.sh | 10 +--------- cdn/cdnrefresh.php | 2 +- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/build.sh b/build.sh index 6658e1dd..3882cd73 100755 --- a/build.sh +++ b/build.sh @@ -38,16 +38,8 @@ function test_docker_container() { echo "Done checking links" } -# Custom cleanup of CDN -function clean_docker_container_cdn() { - clean_docker_container $KEYMAN_IMAGE_NAME $KEYMAN_CONTAINER_NAME - - # Cleanup CDN - rm -rf cdn/deploy -} - builder_run_action configure bootstrap_configure -builder_run_action clean clean_docker_container_cdn +builder_run_action clean clean_docker_container $KEYMAN_IMAGE_NAME $KEYMAN_CONTAINER_NAME builder_run_action stop stop_docker_container $KEYMAN_IMAGE_NAME $KEYMAN_CONTAINER_NAME builder_run_action build build_docker_container $KEYMAN_IMAGE_NAME $KEYMAN_CONTAINER_NAME builder_run_action start start_docker_container $KEYMAN_IMAGE_NAME $KEYMAN_CONTAINER_NAME $KEYMAN_CONTAINER_DESC $HOST_KEYMAN_COM $PORT_KEYMAN_COM diff --git a/cdn/cdnrefresh.php b/cdn/cdnrefresh.php index ca443ac3..ce3f4f99 100644 --- a/cdn/cdnrefresh.php +++ b/cdn/cdnrefresh.php @@ -36,7 +36,7 @@ function generate_hashed_version_file($source, $deploy, $source_file) { $dest_file = $source_file_short; } if(!file_exists($deploy . $dest_file)) { - echo $source_file . " => " . $deploy . $dest_file . "
"; + echo $source_file . " => " . $deploy . $dest_file . "\n"; // Copy the new hashed filename into the deploy folder copy($source_file, $deploy . $dest_file); From e7a466a3e9d8c8c7e8a46ffae0505769d11ae238 Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Wed, 18 Oct 2023 17:02:04 +0700 Subject: [PATCH 44/73] chore: Add test page for go links --- build.sh | 3 + test/index.md | 339 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 342 insertions(+) create mode 100644 test/index.md diff --git a/build.sh b/build.sh index 3882cd73..75b7f7aa 100755 --- a/build.sh +++ b/build.sh @@ -29,6 +29,8 @@ builder_parse "$@" function test_docker_container() { # TODO: lint tests + echo "TIER_TEST" > tier.txt + echo "---- Testing links ----" set +e; set +o pipefail; npx broken-link-checker http://localhost:8053 --ordered --recursive --host-requests 50 -e --filter-level 3 | \ @@ -36,6 +38,7 @@ function test_docker_container() { grep -B 1 "BROKEN"; echo "Done checking links" + rm tier.txt } builder_run_action configure bootstrap_configure diff --git a/test/index.md b/test/index.md new file mode 100644 index 00000000..dfb14246 --- /dev/null +++ b/test/index.md @@ -0,0 +1,339 @@ +--- +title: Go Test Links +description: Test page for links +--- + +## android + +### /go/android/X.Y/download-keyboards/languages + +[download-keyboards/languages](/go/android/16.0/download-keyboards/languages/km) + +[live: download-keyboards/languages](https://keyman.com/go/android/16.0/download-keyboards/languages/km) + +### /go/android/X.Y/download-keyboards + +[download-keyboards](/go/android/16.0/download-keyboards) + +[live: download-keyboards](https://keyman.com/go/android/16.0/download-keyboards) + +------ + +## desktop + +### /go/desktop/13.0/download-keyboards + +[download-keyboards](/go/desktop/13.0/download-keyboards) + +[live: download-keyboards](https://keyman.com/go/desktop/13.0/download-keyboards) + +### /go/desktop/X.Y/download-keyboards + +[download-keyboards](/go/desktop/16.0/download-keyboards) + +[live: download-keyboards](https://keyman.com/go/desktop/16.0/download-keyboards) + +### /go/desktop/X.Y/keep-in-touch + +[keep-in-touch](/go/desktop/16.0/keep-in-touch) + +[live: keep-in-touch](https://keyman.com/go/desktop/16.0/keep-in-touch) + +### /go/desktop/X.Y/forums + +[forums](/go/desktop/16.0/forums) + +[live: forums](https://keyman.com/go/desktop/16.0/forums) + +### /go/desktop/X.Y/issue-1285 + +[issue-1285](/go/desktop/16.0/issue-1285) + +[live: issue-1285](https://keyman.com/go/desktop/16.0/issue-1285) + +### /go/desktop/X.Y/support + +[support](/go/desktop/16.0/support) + +[live: support](https://keyman.com/go/desktop/16.0/support) + +### /go/desktop/X.Y/create-locale + +[create-locale](/go/desktop/16.0/create-locale) + +[live: create-locale](https://secure.tavultesoft.com/keyman/support/locale/) + + +### /go/desktop/X.Y/view-exception/ to /contact/exception + +This endpoint is not used in 14.0 or later + +[view-exception](/go/desktop/13.0/view-exception) + +[live: view-exception](https://keyman.com/go/desktop/13.0/view-exception) + + +### /go/desktop/X.Y/view-exception?id= + +This endpoint is not used in 14.0 or later + +[view-excception?id=1234](/go/desktop/13.0/view-exception?id=1234) + +[live: view-exception?id=1234](https://keyman.com/go/desktop/13.0/view-exception?id=1234) + + +### /go/desktop/X.Y/home + +[home](/go/desktop/16.0/home) + +[live: home](https://keyman.com/go/desktop/16.0/home) + + +### /go/desktop/X.Y/archived-downloads + +[archived-downloads](/go/desktop/16.0/archived-downloads) + +[live: archived-downloads](https://keyman.com/go/desktop/16.0/archived-downloads) + + +### /go/desktop/X.Y/privacy + +[privacy](/go/desktop/16.0/privacy) + +[live: privacy](https://keyman.com/go/desktop/16.0/privacy) + +------ + +## developer + +Links for Developer 10.0 onward + +### /go/developer/X.Y/help-keyboards + + +[help-keyboards](/go/developer/16.0/help-keyboards) + +[live: help-keyboards](https://keyman.com/go/developer/16.0/help-keyboards) + +Direct help to the major version + + +### /go/developer/X.Y/help-(mobile|packages) + +[help-mobile](/go/developer/16.0/help-mobile) + +[live: help-mobile](https://keyman.com/go/developer/16.0/help-mobile) + +[help-packages](/go/developer/16.0/help-mobile) + +[live: help-packages](https://keyman.com/go/developer/16.0/help-mobile) + + +### /go/developer/X.Y/keymanweb + +[keymanweb](/go/developer/16.0/keymanweb) + +[live: keymanweb](https://keyman.com/go/developer/16.0/keymanweb) + + +### /go/developer/X.Y/keyman-engine-home + +[keyman-engine-home](/go/developer/16.0/keyman-engine-home) + +[live: keyman-engine-home](https://keyman.com/go/developer/16.0/keyman-engine-home) + + +### /go/developer/X.Y/language-lookup + +[language-lookup](/go/developer/16.0/language-lookup) + +[live: language-lookup](https://keyman.com/go/developer/16.0/language-lookup) + + +### /go/developer/X.Y/view-exception/ to /contact/exception + +[view-exception](/go/developer/16.0/view-exception) + +[live: view-exception](https://keyman.com/go/developer/16.0/view-exception) + + +### /go/developer/X.Y/view-exception?id= + +[view-exception?id=1234](/go/developer/16.0/view-exception?id=1234) + +[live: view-exception?id=1234](https://keyman.com/go/developer/16.0/view-exception?id=1234) + + +### /go/developer/X.Y/docs/language + +Context-sensitive help in Keyman Developer + +[docs/language/guide/rules](/go/developer/16.0/docs/language/guide/rules) + +[live: docs/language/guide/rules](https://keyman.com/go/developer/16.0/docs/language/guide/rules) + + +### /go/developer/X.Y/docs + +All other context help, direct to the major version + +[docs/context/keyboard-editor](/go/developer/16.0/docs/context/keyboard-editor) + +[live: docs/context/keyboard-editor](https://keyman.com/go/developer/16.0/docs/context/keyboard-editor) + + +### /go/developer/X.Y/home + +[home](/go/developer/16.0/home) + +[live: home](https://keyman.com/go/developer/16.0/home) + +### /go/developer/X.Y/ios-app + +see includes/appstore.php + +[ios-app](/go/developer/16.0/ios-app) + +[live: ios-app](https://keyman.com/go/developer/16.0/ios-app) + + +### /go/developer/X.Y/android-app + +see includes/playstore.php + +[android-app](/go/developer/16.0/android-app) + +[live: android-app](https://keyman.com/go/developer/16.0/android-app) + + +---- + +## download + +[keyman-windows](/go/download/keyman-windows) + +[live: keyman-windows](https://keyman.com/go/download/keyman-windows) + + +---- + +## ios + +### /go/ios/X.Y/download-keyboards/languages + +[download-keyboards/languages/km](/go/ios/16.0/download-keyboards/languages/km) + +[live: download-keyboards/languages/km](https://keyman.com/go/ios/16.0/download-keyboards/languages/km) + + +### /go/ios/X.Y/download-keyboards + +[download-keyboards](/go/ios/16.0/download-keyboards) + +[live: download-keyboards](https://keyman.com/go/ios/16.0/download-keyboards) + + + +---- + +## linux + + +### "/go/linux/X.Y/download-keyboards" + +[download-keyboards](/go/linux/16.0/download-keyboards) + +[live: download-keyboards](https://keyman.com/go/linux/16.0/download-keyboards) + + +### /go/linux/X.Y/forums + +[forums](/go/linux/16.0/forums) + +[live: forums](https://keyman.com/go/linux/16.0/forums) + +### /go/linux/X.Y/support + +[support](/go/linux/16.0/support) + +[live: support](https://keyman.com/go/linux/16.0/support) + + +### /go/linux/X.Y/privacy + +[privacy](/go/linux/16.0/privacy) + +[live: privacy](https://keyman.com/go/linux/16.0/privacy) + +### /go/linux/X.Y/linux-configuration.png + +permanent link to screenshot of linux-configuration + +[linux-configuration.png](/go/linux/16.0/linux-configuration.png) + +[live: linux-configuration.png](https://keyman.com/go/linux/16.0/linux-configuration.png) + + +---- + +## macos + +### /go/macos/X.Y/download-keyboards + +[download-keyboards](/go/macos/16.0/download-keyboards) + +[live: download-keyboards](https://keyman.com/go/macos/16.0/download-keyboards) + +---- + +## package (no .htaccess to check) + + +---- + +## windows + +Links for Keyman for Windows 14.0 onward + +### /go/windows/X.Y/download-keyboards + +[download-keyboards](/go/windows/16.0/download-keyboards) + +[live: download-keyboards](/go/windows/16.0/download-keyboards) + + +### /go/windows/X.Y/keep-in-touch + +[keep-in-touch](/go/windows/16.0/keep-in-touch) + +[live: keep-in-touch](https://keyman.com/go/windows/16.0/keep-in-touch) + + +### /go/windows/X.Y/issue-1285 + +[issue-1285](/go/windows/16.0/issue-1285) + +[live: issue-1285](https://keyman.com/go/windows/16.0/issue-1285) + +### /go/windows/X.Y/create-locale + +[create-locale](/go/windows/16.0/create-locale) + +[live: create-locale](https://keyman.com/go/windows/16.0/create-locale) + + +### /go/windows/X.Y/home + +[home](/go/windows/16.0/home) + +[live: home](https://keyman.com/go/windows/16.0/home) + + +### /go/windows/X.Y/archived-downloads + +[archived-downloads](/go/windows/16.0/archived-downloads) + +[live: archived-downloads](https://keyman.com/go/windows/16.0/archived-downloads) + + +---- \ No newline at end of file From e92e33ab724602ae8acf6c32d1a22d82b89d613f Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Thu, 19 Oct 2023 10:17:43 +0700 Subject: [PATCH 45/73] chore: fix go/download redirect --- go/download/.htaccess | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go/download/.htaccess b/go/download/.htaccess index 3220c485..f520ffb8 100644 --- a/go/download/.htaccess +++ b/go/download/.htaccess @@ -2,4 +2,4 @@ # Links for Developer 10.0 onward # /go/download/program -RedirectMatch "/go/download/(?!_download.php)(.+)" "/go/download/_download.php?object=$1" +RewriteRule "^(?!_download.php)(.+)$" "/go/download/_download.php?object=$1" [END] From f57642fced84e67e183c61158ea6a6dc77ef3ca0 Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Thu, 19 Oct 2023 10:18:52 +0700 Subject: [PATCH 46/73] chore: ignore tier file --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 43329935..1658575f 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,8 @@ /.vscode cdn/deploy/ +tier.txt + vendor* /node_modules/ From efd19e5986a813150446b1788943b5e6b73b92ac Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Thu, 19 Oct 2023 11:41:01 +0700 Subject: [PATCH 47/73] fix: some keyboard redirects --- .htaccess | 2 +- go/.htaccess | 3 +-- test/index.md | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 67 insertions(+), 4 deletions(-) diff --git a/.htaccess b/.htaccess index 8a8dadc8..15fdf2da 100644 --- a/.htaccess +++ b/.htaccess @@ -90,7 +90,7 @@ RewriteRule "^keyboards/download/([^/]+)$" "/keyboards/keyboard.php?id=$1" [L] # /keyboards/share/[id] to /keyboards/share.php # if the keyboard exists in the repo, then share.php will redirecct to /keyboards/ -RewriteRule "^keyboards/share/(^/]+)$" "/keyboards/share.php?id=$1" [L] +RewriteRule "^keyboards/share/([^/]+)$" "/keyboards/share.php?id=$1" [L] # /keyboards/{id}.json to /keyboards/keyboard.json.php RewriteRule "^keyboards/(?!keyboard.json)(.*)\.json$" "/keyboards/keyboard.json.php?id=$1" [L] diff --git a/go/.htaccess b/go/.htaccess index 52438d69..74541387 100644 --- a/go/.htaccess +++ b/go/.htaccess @@ -12,8 +12,7 @@ RedirectMatch "/go/(([1-9][0-9])([.]?)([0-9]))/developer-help-(mobile|packages)( # # download-model/keyboard package -#RedirectMatch "/go/package/download/model/([^/]+)$" "https://keyman.com/go/package/download.php?type=model&id=$1" -RedirectMatch "/go/package/download/(model|keyboard)/([^\/]+)\/?$" "https://keyman.com/go/package/download.php?type=$1&id=$2" +RedirectMatch "/go/package/download/(model|keyboard)/([^/]+)\/?$" "https://keyman.com/go/package/download.php?type=$1&id=$2" # keyboard/id/share RedirectMatch "/go/keyboard/([^/?]+)/share$" "/keyboards/share/$1" diff --git a/test/index.md b/test/index.md index dfb14246..12af07a6 100644 --- a/test/index.md +++ b/test/index.md @@ -3,6 +3,70 @@ title: Go Test Links description: Test page for links --- +[why](/go/why) + +[live: why](https://keyman.com/go/why) + + +### Developer 10.0 onward redirects for package guide +[developer-help-mobile](/go/16.0/developer-help-mobile) + +[live: developer-help-mobile](https://keyman.com/go/16.0/developer-help-mobile) + +[developer-help-mobile](/go/16.0/developer-help-packages) + +[live: developer-help-mobile](https://keyman.com/go/16.0/developer-help-packages) + +---- + +## package/download + + +### download-model/keyboard package + +[package/download/model/nrc.en.mtnt](/go/package/download/model/nrc.en.mtnt) + +[live: package/download/model/nrc.en.mtnt](https://keyman.com/go/package/download/model/nrc.en.mtnt) + +[package/download/keyboard/sil_ipa](/go/package/download/keyboard/sil_ipa) + +[live: package/download/keyboard/sil_ipa](https://keyman.com/go/package/download/keyboard/sil_ipa) + + + +### keyboard/id/share + +[keyboard/sil_ipa/share](/go/keyboard/sil_ipa/share) + +[live: keyboard/sil_ipa/share](https://keyman.com/go/keyboard/sil_ipa/share) + + +## Non-app-specific endpoints + + +### go/support + +[support](/go/16.0/support) + +[live: support](https://keyman.com/go/16.0/support) + + +### go/privacy + +[privacy](/go/16.0/privacy) + +[live: privacy](https://keyman.com/go/16.0/privacy) + + +### go/community + +[community](/go/16.0/community) + +[live: community](https://keyman.com/go/16.0/community) + + +---- + ## android ### /go/android/X.Y/download-keyboards/languages @@ -299,7 +363,7 @@ Links for Keyman for Windows 14.0 onward [download-keyboards](/go/windows/16.0/download-keyboards) -[live: download-keyboards](/go/windows/16.0/download-keyboards) +[live: download-keyboards](https://keyman.com/go/windows/16.0/download-keyboards) ### /go/windows/X.Y/keep-in-touch From 6919b0ffe88cb0ddc502536e4e001f9350c8674b Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Fri, 20 Oct 2023 10:15:21 +0700 Subject: [PATCH 48/73] chore: Try to fix _legacy links --- .htaccess | 16 +++--- _includes/includes/md/mdhost.php | 1 + _legacy/.htaccess | 40 ++++++------- test/index.md | 19 ++++--- test/keyboards.md | 98 ++++++++++++++++++++++++++++++++ test/legacy.md | 65 +++++++++++++++++++++ 6 files changed, 203 insertions(+), 36 deletions(-) create mode 100644 test/keyboards.md create mode 100644 test/legacy.md diff --git a/.htaccess b/.htaccess index 15fdf2da..afdf20fc 100644 --- a/.htaccess +++ b/.htaccess @@ -62,7 +62,7 @@ RewriteRule "^downloads/releases(\/)?$" "/downloads" [R,END] # /keyboards/{install|download|share}/{id}/ to /keyboards/x/id # RedirectMatch "^keyboards/(install|download|share)/([^/]+)/$" "/keyboards/$1/$2" -RewriteRule "^keyboards/(install|download|share)/([^/]+)/$" "/keyboards/$1/$2" [R=301,L] +RewriteRule "^keyboards/(install|download|share)/([^/]+)/$" "/keyboards/$1/$2" [R=301,END,QSA] # /keyboards/{id}/ to /keyboards/id RedirectMatch 301 "^keyboards/([^/]+)/$" "/keyboards/$1" @@ -81,22 +81,22 @@ RewriteRule "^keyboard(/.*)$" "/keyboards$1" [L] # # /keyboards/install/[id] to /keyboards/install.php -RewriteRule "^keyboards/install/([^/]+)$" "/keyboards/install.php?id=$1" [L] +RewriteRule "^keyboards/install/([^/]+)$" "/keyboards/install.php?id=$1" [END,QSA] # /keyboards/download/[id] to /keyboards/keyboard.php # This formerly redirected to a download, but we no longer need it; keep it for # legacy links -RewriteRule "^keyboards/download/([^/]+)$" "/keyboards/keyboard.php?id=$1" [L] +RewriteRule "^keyboards/download/([^/]+)$" "/keyboards/keyboard.php?id=$1" [END,QSA] # /keyboards/share/[id] to /keyboards/share.php -# if the keyboard exists in the repo, then share.php will redirecct to /keyboards/ +# if the keyboard exists in the repo, then share.php will redirect to /keyboards/ RewriteRule "^keyboards/share/([^/]+)$" "/keyboards/share.php?id=$1" [L] # /keyboards/{id}.json to /keyboards/keyboard.json.php -RewriteRule "^keyboards/(?!keyboard.json)(.*)\.json$" "/keyboards/keyboard.json.php?id=$1" [L] +RewriteRule "^keyboards/(?!keyboard.json)(.*)\.json$" "/keyboards/keyboard.json.php?id=$1" [END] # /keyboards/{id} to /keyboards/keyboard.php -RewriteRule "^keyboards/(?!index\.php|install|keyboard|session|share)([^/]+)$" "/keyboards/keyboard.php?id=$1" [L,QSA] +RewriteRule "^keyboards/(?!index\.php|install|keyboard|session|share)([^/]+)$" "/keyboards/keyboard.php?id=$1" [END,QSA] # @@ -110,13 +110,13 @@ RewriteRule "^keyboards/(?!index\.php|install|keyboard|session|share)([^/]+)$" " RewriteRule "^keyboards/languages/(.*)" "/keyboards/index.php?q=l:id:$1" [L] # /keyboards/download to /keyboards/download.php -RewriteRule "^keyboards/download(.php)?" "/keyboards/download.php" [L] +RewriteRule "^keyboards/download(.php)?" "/keyboards/download.php" [L,QSA] # /keyboards/legacy to /keyboards/keyboard.php RewriteRule "^keyboards/legacy/(.*)" "/keyboards/keyboard.php?legacy=$1" [L] # /keyboards/countries to /keyboards/index.php -RewriteRule "^keyboards/countries/(.*)" "/keyboards/index.php?q=c:id:$1" [L] +RewriteRule "^keyboards/countries/(.*)" "/keyboards/index.php?q=c:id:$1" [END] # Synonym paths diff --git a/_includes/includes/md/mdhost.php b/_includes/includes/md/mdhost.php index 0a5ba995..530dc210 100644 --- a/_includes/includes/md/mdhost.php +++ b/_includes/includes/md/mdhost.php @@ -13,6 +13,7 @@ head([ 'title' => $md->PageTitle(), 'css' => ['template.css','prism.css'], + 'showMenu' => $md->ShowMenu(), 'js' => ['prism.js'] ]); diff --git a/_legacy/.htaccess b/_legacy/.htaccess index b03e4101..0e4e6f01 100644 --- a/_legacy/.htaccess +++ b/_legacy/.htaccess @@ -1,31 +1,31 @@ # Keyboard search -# legacy /keyboards?q=... to /keyboards/index.php -RedirectMatch "/_legacy/keyboards" "/keyboards/index.php" +# legacy /keyboards?q=... to keyboards/index.php +RewriteRule "^keyboards$" "/_legacy/keyboards/index.php" [END] -# legacy /keyboards/ to /keyboards -RedirectMatch 301 "/_legacy/keyboards/" "/keyboards" +# legacy /keyboards/ to keyboards +RewriteRule "^keyboards/$" "/_legacy/keyboards" [R=301,END,QSA] -# legacy /keyboards/languages to /keyboards/index.php -RedirectMatch "/_legacy/keyboards/languages/(.*)" "/keyboards/index.php?q=l:id:$1" +# legacy /keyboards/languages to keyboards/index.php +RewriteRule "^keyboards/languages/(.*)" "/_legacy/keyboards/index.php?q=l:id:$1" [END] -# "legacy /keyboards/download to /keyboards/download.php" -RedirectMatch "/_legacy/keyboards/download(\.php)?" "/keyboards/download.php" +# "legacy /keyboards/download to keyboards/download.php +RewriteRule "^keyboards/download(\.php)?" "/_legacy/keyboards/download.php" [END,QSA] -# "legacy /keyboards/legacy to /keyboards/keyboard.php" -RedirectMatch "/_legacy/keyboards/legacy/(.*)" "/keyboards/keyboard.php?legacy=$1" +# "legacy /keyboards/legacy to keyboards/keyboard.php +RewriteRule "^keyboards/legacy/(.*)" "/_legacy/keyboards/keyboard.php?legacy=$1" [END] -# "legacy /keyboards/countries to /keyboards/index.php" -RedirectMatch "/_legacy/keyboards/countries/(.*)" "/keyboards/index.php?q=c:id:$1" +# "legacy /keyboards/countries to keyboards/index.php +RewriteRule "^keyboards/countries/(.*)" "/_legacy/keyboards/index.php?q=c:id:$1" [END] -# "legacy /keyboards/{name}/share to /keyboards/share.php" -RedirectMatch "/_legacy/keyboards/([^/]+)/share" "/keyboards/share.php?id=$1" +# "legacy /keyboards/{name}/share to keyboards/share.php +RewriteRule "^keyboards/([^/]+)/share" "/_legacy/keyboards/share.php?id=$1" [END] -# "legacy /keyboards/{name}.json to /keyboards/keyboard.json.php" -RedirectMatch "/_legacy/keyboards/(.*)\.json$" "/keyboards/keyboard.json.php?id=$1" +# "legacy /keyboards/{name}.json to keyboards/keyboard.json.php +RewriteRule "^keyboards/(.*)\.json$" "/_legacy/keyboards/keyboard.json.php?id=$1" [END] -# "legacy /keyboards/{name} to /keyboards/keyboard.php" -RedirectMatch "/_legacy/keyboards/(.*)" "/keyboards/keyboard.php?id=$1" +# "legacy /keyboards/{name} to keyboards/keyboard.php +RewriteRule "^keyboards/(.*)" "/_legacy/keyboards/keyboard.php?id=$1" [END] -# "legacy /keyboard/{name} to /keyboards/..." stopProcessing="true"> -RedirectMatch "/_legacy/keyboard/(.*)$" "/keyboards/$1" +# "legacy /keyboard/{name} to keyboards/... +RedirectMatch "/_legacy/keyboard/(.*)$" "/_legacy/keyboards/$1" diff --git a/test/index.md b/test/index.md index 12af07a6..3b872f16 100644 --- a/test/index.md +++ b/test/index.md @@ -1,12 +1,23 @@ --- title: Go Test Links description: Test page for links +showmenu: false --- [why](/go/why) [live: why](https://keyman.com/go/why) +## Products + +[macosx to mac](/macosx/download) + +[live: macosx to mac](https://keyman.com/macosx/download) + +[desktop to Windows](/desktop/download) + +[live: desktop to Windows](https://keyman.com/desktop/download) + ### Developer 10.0 onward redirects for package guide [developer-help-mobile](/go/16.0/developer-help-mobile) @@ -33,14 +44,6 @@ description: Test page for links [live: package/download/keyboard/sil_ipa](https://keyman.com/go/package/download/keyboard/sil_ipa) - -### keyboard/id/share - -[keyboard/sil_ipa/share](/go/keyboard/sil_ipa/share) - -[live: keyboard/sil_ipa/share](https://keyman.com/go/keyboard/sil_ipa/share) - - ## Non-app-specific endpoints diff --git a/test/keyboards.md b/test/keyboards.md new file mode 100644 index 00000000..676ac704 --- /dev/null +++ b/test/keyboards.md @@ -0,0 +1,98 @@ +--- +title: Test Links of Keyboard Searches +description: Test page for keyboard links +showmenu: false +--- + +## Keyboards + +### keyboard/id/share + +[keyboard/sil_ipa/share](/go/keyboard/sil_ipa/share) + +[live: keyboard/sil_ipa/share](https://keyman.com/go/keyboard/sil_ipa/share) + +### keyboards/install/id + +[keyboards/install/sil_ipa](/keyboards/install/sil_ipa) + +[live: keyboards/install/sil_ipa](https://keyman.com/keyboards/install/sil_ipa) + +### keyboards/download/id + +[keyboards/download/sil_ipa](/keyboards/download/sil_ipa) + +[live: keyboards/download/sil_ipa](https://keyman.com/keyboards/download/sil_ipa) + +### keyboards/id.json + +[keyboards/sil_ipa.json](/keyboards/sil_ipa.json) + +[live: keyboards/sil_ipa.json](https://keyman.com/keyboards/sil_ipa.json) + +### keyboards/countries/id + +[keyboards/countries/kh](/keyboards/countries/kh) + +[live: keyboards/countries/kh](https://keyman.com/keyboards/countries/kh) + +---- + +## legacy /keyboards + +[_legacy/keyboards](/_legacy/keyboards) + +[live: _legacy/keyboards](https://keyman.com/_legacy/keyboards) + +[_legacy/keyboards/](/_legacy/keyboards/) + +[live: _legacy/keyboards/](https://keyman.com/_legacy/keyboards/) + + +### legacy /keyboards/languages/id + +[_legacy/keyboards/languages/km](/_legacy/keyboards/languages/km) + +[live: _legacy/keyboards/languages/km](https://keyman.com/_legacy/keyboards/languages/km) + +### legacy /keyboards/download + +[_legacy/keyboards/download](/_legacy/keyboards/download?id=sil_ipa&platform=windows&mode=standalone) + +[live: _legacy/keyboards/download](https://keyman.com/_legacy/keyboards/download?id=sil_ipa&platform=windows&mode=standalone) + +### legacy /keyboards/legacy + +[_legacy/keyboards/legacy/id](/_legacy/keyboards/legacy/sil_ipa) + +[live: _legacy/keyboards/legacy/id](https://keyman.com/_legacy/keyboards/legacy/sil_ipa) + +### legacy /keyboards/countries/id + +[_legacy/keyboards/countries/kh](/_legacy/keyboards/countries/kh) + +[live: _legacy/keyboards/countries/kh](https://keyman.com/_legacy/keyboards/countries/kh) + +### legacy /keyboards/id/share + +[_legacy/keyboards/sil_ipa/share](/_legacy/keyboards/sil_ipa/share) + +[live: _legacy/keyboards/sil_ipa/share](https://keyman.com/_legacy/keyboards/sil_ipa/share) + +### legacy /keyboards/id.json + +[_legacy/keyboards/sil_ipa.json](/_legacy/keyboards/sil_ipa.json) + +[live: _legacy/keyboards/sil_ipa.json](https://keyman.com/_legacy/keyboards/sil_ipa.json) + +### legacy /keyboards/id + +[_legacy/keyboards/sil_ipa](/_legacy/keyboards/sil_ipa) + +[live: _legacy/keyboards/sil_ipa](https://keyman.com/_legacy/keyboards/sil_ipa) + +### legacy /keyboard/id + +[_legacy/keyboard/sil_ipa](/_legacy/keyboard/sil_ipa) + +[live: _legacy/keyboard/sil_ipa](https://keyman.com/_legacy/keyboard/sil_ipa) \ No newline at end of file diff --git a/test/legacy.md b/test/legacy.md new file mode 100644 index 00000000..a55b927f --- /dev/null +++ b/test/legacy.md @@ -0,0 +1,65 @@ +--- +title: Test Links of Legacy Keyboard Searches +description: Test page for legacy keyboard links +showmenu: false +--- + +## legacy /keyboards + + +[_legacy/keyboards](/_legacy/keyboards) + +[live: _legacy/keyboards](https://keyman.com/_legacy/keyboards) + +[_legacy/keyboards/](/_legacy/keyboards/) + +[live: _legacy/keyboards/](https://keyman.com/_legacy/keyboards/) + + +### legacy /keyboards/languages/id + +[_legacy/keyboards/languages/km](/_legacy/keyboards/languages/km) + +[live: _legacy/keyboards/languages/km](https://keyman.com/_legacy/keyboards/languages/km) + +### legacy /keyboards/download + +[_legacy/keyboards/download](/_legacy/keyboards/download?id=sil_ipa&platform=windows&mode=standalone) + +[live: _legacy/keyboards/download](https://keyman.com/_legacy/keyboards/download?id=sil_ipa&platform=windows&mode=standalone) + +### legacy /keyboards/legacy + +[_legacy/keyboards/legacy/id](/_legacy/keyboards/legacy/sil_ipa) + +[live: _legacy/keyboards/legacy/id](https://keyman.com/_legacy/keyboards/legacy/sil_ipa) + +### legacy /keyboards/countries/id + +[_legacy/keyboards/countries/kh](/_legacy/keyboards/countries/kh) + +[live: _legacy/keyboards/countries/kh](https://keyman.com/_legacy/keyboards/countries/kh) + +### legacy /keyboards/id/share + +[_legacy/keyboards/sil_ipa/share](/_legacy/keyboards/sil_ipa/share) + +[live: _legacy/keyboards/sil_ipa/share](https://keyman.com/_legacy/keyboards/sil_ipa/share) + +### legacy /keyboards/id.json + +[_legacy/keyboards/sil_ipa.json](/_legacy/keyboards/sil_ipa.json) + +[live: _legacy/keyboards/sil_ipa.json](https://keyman.com/_legacy/keyboards/sil_ipa.json) + +### legacy /keyboards/id + +[_legacy/keyboards/sil_ipa](/_legacy/keyboards/sil_ipa) + +[live: _legacy/keyboards/sil_ipa](https://keyman.com/_legacy/keyboards/sil_ipa) + +### legacy /keyboard/id + +[_legacy/keyboard/sil_ipa](/_legacy/keyboard/sil_ipa) + +[live: _legacy/keyboard/sil_ipa](https://keyman.com/_legacy/keyboard/sil_ipa) From cd4d38776a5c45a5ce56e087fa7ea9cd81b75f49 Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Wed, 25 Oct 2023 08:52:19 +0700 Subject: [PATCH 49/73] chore: split out test pages --- test/go.md | 397 ++++++++++++++++++++++++++++++++++++++++++++++++++ test/index.md | 393 +------------------------------------------------ 2 files changed, 403 insertions(+), 387 deletions(-) create mode 100644 test/go.md diff --git a/test/go.md b/test/go.md new file mode 100644 index 00000000..5151c749 --- /dev/null +++ b/test/go.md @@ -0,0 +1,397 @@ +--- +title: Go Test Links +description: Test page for /go links +showmenu: false +--- + + +[why](/go/why) + +[live: why](https://keyman.com/go/why) + + +### Developer 10.0 onward redirects for package guide + +[developer-help-mobile](/go/16.0/developer-help-mobile) + +[live: developer-help-mobile](https://keyman.com/go/16.0/developer-help-mobile) + +[developer-help-mobile](/go/16.0/developer-help-packages) + +[live: developer-help-mobile](https://keyman.com/go/16.0/developer-help-packages) + +---- + +## package/download + + +### download-model/keyboard package + +[package/download/model/nrc.en.mtnt](/go/package/download/model/nrc.en.mtnt) + +[live: package/download/model/nrc.en.mtnt](https://keyman.com/go/package/download/model/nrc.en.mtnt) + +[package/download/keyboard/sil_ipa](/go/package/download/keyboard/sil_ipa) + +[live: package/download/keyboard/sil_ipa](https://keyman.com/go/package/download/keyboard/sil_ipa) + + +## Non-app-specific endpoints + +### go/support + +[support](/go/16.0/support) + +[live: support](https://keyman.com/go/16.0/support) + + +### go/privacy + +[privacy](/go/16.0/privacy) + +[live: privacy](https://keyman.com/go/16.0/privacy) + + +### go/community + +[community](/go/16.0/community) + +[live: community](https://keyman.com/go/16.0/community) + + +---- + +## android + +### /go/android/X.Y/download-keyboards/languages +Royce, Scott, and Darcy attending Colloquium on Fonts for Southeast Asian scripts +[download-keyboards/languages](/go/android/16.0/download-keyboards/languages/km) + +[live: download-keyboards/languages](https://keyman.com/go/android/16.0/download-keyboards/languages/km) + +### /go/android/X.Y/download-keyboards + +[download-keyboards](/go/android/16.0/download-keyboards) + +[live: download-keyboards](https://keyman.com/go/android/16.0/download-keyboards) + +------ + +## desktop + +### /go/desktop/13.0/download-keyboards + +[download-keyboards](/go/desktop/13.0/download-keyboards) + +[live: download-keyboards](https://keyman.com/go/desktop/13.0/download-keyboards) + +### /go/desktop/X.Y/download-keyboards + +[download-keyboards](/go/desktop/16.0/download-keyboards) + +[live: download-keyboards](https://keyman.com/go/desktop/16.0/download-keyboards) + +### /go/desktop/X.Y/keep-in-touch + +[keep-in-touch](/go/desktop/16.0/keep-in-touch) + +[live: keep-in-touch](https://keyman.com/go/desktop/16.0/keep-in-touch) + +### /go/desktop/X.Y/forums + +[forums](/go/desktop/16.0/forums) + +[live: forums](https://keyman.com/go/desktop/16.0/forums) + +### /go/desktop/X.Y/issue-1285 + +[issue-1285](/go/desktop/16.0/issue-1285) + +[live: issue-1285](https://keyman.com/go/desktop/16.0/issue-1285) + +### /go/desktop/X.Y/support + +[support](/go/desktop/16.0/support) + +[live: support](https://keyman.com/go/desktop/16.0/support) + +### /go/desktop/X.Y/create-locale + +[create-locale](/go/desktop/16.0/create-locale) + +[live: create-locale](https://secure.tavultesoft.com/keyman/support/locale/) + + +### /go/desktop/X.Y/view-exception/ to /contact/exception + +This endpoint is not used in 14.0 or later + +[view-exception](/go/desktop/13.0/view-exception) + +[live: view-exception](https://keyman.com/go/desktop/13.0/view-exception) + + +### /go/desktop/X.Y/view-exception?id= + +This endpoint is not used in 14.0 or later + +[view-excception?id=1234](/go/desktop/13.0/view-exception?id=1234) + +[live: view-exception?id=1234](https://keyman.com/go/desktop/13.0/view-exception?id=1234) + + +### /go/desktop/X.Y/home + +[home](/go/desktop/16.0/home) + +[live: home](https://keyman.com/go/desktop/16.0/home) + + +### /go/desktop/X.Y/archived-downloads + +[archived-downloads](/go/desktop/16.0/archived-downloads) + +[live: archived-downloads](https://keyman.com/go/desktop/16.0/archived-downloads) + + +### /go/desktop/X.Y/privacy + +[privacy](/go/desktop/16.0/privacy) + +[live: privacy](https://keyman.com/go/desktop/16.0/privacy) + +------ + +## developer + +Links for Developer 10.0 onward + +### /go/developer/X.Y/help-keyboards + + +[help-keyboards](/go/developer/16.0/help-keyboards) + +[live: help-keyboards](https://keyman.com/go/developer/16.0/help-keyboards) + +Direct help to the major version + + +### /go/developer/X.Y/help-(mobile|packages) + +[help-mobile](/go/developer/16.0/help-mobile) + +[live: help-mobile](https://keyman.com/go/developer/16.0/help-mobile) + +[help-packages](/go/developer/16.0/help-mobile) + +[live: help-packages](https://keyman.com/go/developer/16.0/help-mobile) + + +### /go/developer/X.Y/keymanweb + +[keymanweb](/go/developer/16.0/keymanweb) + +[live: keymanweb](https://keyman.com/go/developer/16.0/keymanweb) + + +### /go/developer/X.Y/keyman-engine-home + +[keyman-engine-home](/go/developer/16.0/keyman-engine-home) + +[live: keyman-engine-home](https://keyman.com/go/developer/16.0/keyman-engine-home) + + +### /go/developer/X.Y/language-lookup + +[language-lookup](/go/developer/16.0/language-lookup) + +[live: language-lookup](https://keyman.com/go/developer/16.0/language-lookup) + + +### /go/developer/X.Y/view-exception/ to /contact/exception + +[view-exception](/go/developer/16.0/view-exception) + +[live: view-exception](https://keyman.com/go/developer/16.0/view-exception) + + +### /go/developer/X.Y/view-exception?id= + +[view-exception?id=1234](/go/developer/16.0/view-exception?id=1234) + +[live: view-exception?id=1234](https://keyman.com/go/developer/16.0/view-exception?id=1234) + + +### /go/developer/X.Y/docs/language + +Context-sensitive help in Keyman Developer + +[docs/language/guide/rules](/go/developer/16.0/docs/language/guide/rules) + +[live: docs/language/guide/rules](https://keyman.com/go/developer/16.0/docs/language/guide/rules) + + +### /go/developer/X.Y/docs + +All other context help, direct to the major version + +[docs/context/keyboard-editor](/go/developer/16.0/docs/context/keyboard-editor) + +[live: docs/context/keyboard-editor](https://keyman.com/go/developer/16.0/docs/context/keyboard-editor) + + +### /go/developer/X.Y/home + +[home](/go/developer/16.0/home) + +[live: home](https://keyman.com/go/developer/16.0/home) + +### /go/developer/X.Y/ios-app + +see includes/appstore.php + +[ios-app](/go/developer/16.0/ios-app) + +[live: ios-app](https://keyman.com/go/developer/16.0/ios-app) + + +### /go/developer/X.Y/android-app + +see includes/playstore.php + +[android-app](/go/developer/16.0/android-app) + +[live: android-app](https://keyman.com/go/developer/16.0/android-app) + + +---- + +## download + +[keyman-windows](/go/download/keyman-windows) + +[live: keyman-windows](https://keyman.com/go/download/keyman-windows) + + +---- + +## ios + +### /go/ios/X.Y/download-keyboards/languages + +[download-keyboards/languages/km](/go/ios/16.0/download-keyboards/languages/km) + +[live: download-keyboards/languages/km](https://keyman.com/go/ios/16.0/download-keyboards/languages/km) + + +### /go/ios/X.Y/download-keyboards + +[download-keyboards](/go/ios/16.0/download-keyboards) + +[live: download-keyboards](https://keyman.com/go/ios/16.0/download-keyboards) + + + +---- + +## linux + + +### /go/linux/X.Y/download-keyboards + +[download-keyboards](/go/linux/16.0/download-keyboards) + +[live: download-keyboards](https://keyman.com/go/linux/16.0/download-keyboards) + + +### /go/linux/X.Y/forums + +[forums](/go/linux/16.0/forums) + +[live: forums](https://keyman.com/go/linux/16.0/forums) + +### /go/linux/X.Y/support + +[support](/go/linux/16.0/support) + +[live: support](https://keyman.com/go/linux/16.0/support) + + +### /go/linux/X.Y/privacy + +[privacy](/go/linux/16.0/privacy) + +[live: privacy](https://keyman.com/go/linux/16.0/privacy) + +### /go/linux/X.Y/linux-configuration.png + +permanent link to screenshot of linux-configuration + +[linux-configuration.png](/go/linux/16.0/linux-configuration.png) + +[live: linux-configuration.png](https://keyman.com/go/linux/16.0/linux-configuration.png) + + +---- + +## macos + +### /go/macos/X.Y/download-keyboards + +[download-keyboards](/go/macos/16.0/download-keyboards) + +[live: download-keyboards](https://keyman.com/go/macos/16.0/download-keyboards) + +---- + +## package (no .htaccess to check) + + +---- + +## windows + +Links for Keyman for Windows 14.0 onward + +### /go/windows/X.Y/download-keyboards + +[download-keyboards](/go/windows/16.0/download-keyboards) + +[live: download-keyboards](https://keyman.com/go/windows/16.0/download-keyboards) + + +### /go/windows/X.Y/keep-in-touch + +[keep-in-touch](/go/windows/16.0/keep-in-touch) + +[live: keep-in-touch](https://keyman.com/go/windows/16.0/keep-in-touch) + + +### /go/windows/X.Y/issue-1285 + +[issue-1285](/go/windows/16.0/issue-1285) + +[live: issue-1285](https://keyman.com/go/windows/16.0/issue-1285) + +### /go/windows/X.Y/create-locale + +[create-locale](/go/windows/16.0/create-locale) + +[live: create-locale](https://keyman.com/go/windows/16.0/create-locale) + + +### /go/windows/X.Y/home + +[home](/go/windows/16.0/home) + +[live: home](https://keyman.com/go/windows/16.0/home) + + +### /go/windows/X.Y/archived-downloads + +[archived-downloads](/go/windows/16.0/archived-downloads) + +[live: archived-downloads](https://keyman.com/go/windows/16.0/archived-downloads) + + +---- \ No newline at end of file diff --git a/test/index.md b/test/index.md index 3b872f16..a24f6355 100644 --- a/test/index.md +++ b/test/index.md @@ -1,12 +1,9 @@ --- -title: Go Test Links -description: Test page for links +title: Test Links +description: Test pages for links showmenu: false --- -[why](/go/why) - -[live: why](https://keyman.com/go/why) ## Products @@ -19,388 +16,10 @@ showmenu: false [live: desktop to Windows](https://keyman.com/desktop/download) -### Developer 10.0 onward redirects for package guide -[developer-help-mobile](/go/16.0/developer-help-mobile) - -[live: developer-help-mobile](https://keyman.com/go/16.0/developer-help-mobile) - -[developer-help-mobile](/go/16.0/developer-help-packages) - -[live: developer-help-mobile](https://keyman.com/go/16.0/developer-help-packages) - ----- - -## package/download - - -### download-model/keyboard package - -[package/download/model/nrc.en.mtnt](/go/package/download/model/nrc.en.mtnt) - -[live: package/download/model/nrc.en.mtnt](https://keyman.com/go/package/download/model/nrc.en.mtnt) - -[package/download/keyboard/sil_ipa](/go/package/download/keyboard/sil_ipa) - -[live: package/download/keyboard/sil_ipa](https://keyman.com/go/package/download/keyboard/sil_ipa) - - -## Non-app-specific endpoints - - -### go/support - -[support](/go/16.0/support) - -[live: support](https://keyman.com/go/16.0/support) - - -### go/privacy - -[privacy](/go/16.0/privacy) - -[live: privacy](https://keyman.com/go/16.0/privacy) - - -### go/community - -[community](/go/16.0/community) - -[live: community](https://keyman.com/go/16.0/community) - - ----- - -## android - -### /go/android/X.Y/download-keyboards/languages - -[download-keyboards/languages](/go/android/16.0/download-keyboards/languages/km) - -[live: download-keyboards/languages](https://keyman.com/go/android/16.0/download-keyboards/languages/km) - -### /go/android/X.Y/download-keyboards - -[download-keyboards](/go/android/16.0/download-keyboards) - -[live: download-keyboards](https://keyman.com/go/android/16.0/download-keyboards) - ------- - -## desktop - -### /go/desktop/13.0/download-keyboards - -[download-keyboards](/go/desktop/13.0/download-keyboards) - -[live: download-keyboards](https://keyman.com/go/desktop/13.0/download-keyboards) - -### /go/desktop/X.Y/download-keyboards - -[download-keyboards](/go/desktop/16.0/download-keyboards) - -[live: download-keyboards](https://keyman.com/go/desktop/16.0/download-keyboards) - -### /go/desktop/X.Y/keep-in-touch - -[keep-in-touch](/go/desktop/16.0/keep-in-touch) - -[live: keep-in-touch](https://keyman.com/go/desktop/16.0/keep-in-touch) - -### /go/desktop/X.Y/forums - -[forums](/go/desktop/16.0/forums) - -[live: forums](https://keyman.com/go/desktop/16.0/forums) - -### /go/desktop/X.Y/issue-1285 - -[issue-1285](/go/desktop/16.0/issue-1285) - -[live: issue-1285](https://keyman.com/go/desktop/16.0/issue-1285) - -### /go/desktop/X.Y/support - -[support](/go/desktop/16.0/support) - -[live: support](https://keyman.com/go/desktop/16.0/support) - -### /go/desktop/X.Y/create-locale - -[create-locale](/go/desktop/16.0/create-locale) - -[live: create-locale](https://secure.tavultesoft.com/keyman/support/locale/) - - -### /go/desktop/X.Y/view-exception/ to /contact/exception - -This endpoint is not used in 14.0 or later - -[view-exception](/go/desktop/13.0/view-exception) - -[live: view-exception](https://keyman.com/go/desktop/13.0/view-exception) - - -### /go/desktop/X.Y/view-exception?id= - -This endpoint is not used in 14.0 or later - -[view-excception?id=1234](/go/desktop/13.0/view-exception?id=1234) - -[live: view-exception?id=1234](https://keyman.com/go/desktop/13.0/view-exception?id=1234) - - -### /go/desktop/X.Y/home - -[home](/go/desktop/16.0/home) - -[live: home](https://keyman.com/go/desktop/16.0/home) - - -### /go/desktop/X.Y/archived-downloads - -[archived-downloads](/go/desktop/16.0/archived-downloads) - -[live: archived-downloads](https://keyman.com/go/desktop/16.0/archived-downloads) - - -### /go/desktop/X.Y/privacy - -[privacy](/go/desktop/16.0/privacy) - -[live: privacy](https://keyman.com/go/desktop/16.0/privacy) - ------- - -## developer - -Links for Developer 10.0 onward - -### /go/developer/X.Y/help-keyboards - - -[help-keyboards](/go/developer/16.0/help-keyboards) - -[live: help-keyboards](https://keyman.com/go/developer/16.0/help-keyboards) - -Direct help to the major version - - -### /go/developer/X.Y/help-(mobile|packages) - -[help-mobile](/go/developer/16.0/help-mobile) - -[live: help-mobile](https://keyman.com/go/developer/16.0/help-mobile) - -[help-packages](/go/developer/16.0/help-mobile) - -[live: help-packages](https://keyman.com/go/developer/16.0/help-mobile) - - -### /go/developer/X.Y/keymanweb - -[keymanweb](/go/developer/16.0/keymanweb) - -[live: keymanweb](https://keyman.com/go/developer/16.0/keymanweb) - - -### /go/developer/X.Y/keyman-engine-home - -[keyman-engine-home](/go/developer/16.0/keyman-engine-home) - -[live: keyman-engine-home](https://keyman.com/go/developer/16.0/keyman-engine-home) - - -### /go/developer/X.Y/language-lookup - -[language-lookup](/go/developer/16.0/language-lookup) - -[live: language-lookup](https://keyman.com/go/developer/16.0/language-lookup) - - -### /go/developer/X.Y/view-exception/ to /contact/exception - -[view-exception](/go/developer/16.0/view-exception) - -[live: view-exception](https://keyman.com/go/developer/16.0/view-exception) - - -### /go/developer/X.Y/view-exception?id= - -[view-exception?id=1234](/go/developer/16.0/view-exception?id=1234) - -[live: view-exception?id=1234](https://keyman.com/go/developer/16.0/view-exception?id=1234) - - -### /go/developer/X.Y/docs/language - -Context-sensitive help in Keyman Developer - -[docs/language/guide/rules](/go/developer/16.0/docs/language/guide/rules) - -[live: docs/language/guide/rules](https://keyman.com/go/developer/16.0/docs/language/guide/rules) - - -### /go/developer/X.Y/docs - -All other context help, direct to the major version - -[docs/context/keyboard-editor](/go/developer/16.0/docs/context/keyboard-editor) - -[live: docs/context/keyboard-editor](https://keyman.com/go/developer/16.0/docs/context/keyboard-editor) - - -### /go/developer/X.Y/home - -[home](/go/developer/16.0/home) - -[live: home](https://keyman.com/go/developer/16.0/home) - -### /go/developer/X.Y/ios-app - -see includes/appstore.php - -[ios-app](/go/developer/16.0/ios-app) - -[live: ios-app](https://keyman.com/go/developer/16.0/ios-app) - - -### /go/developer/X.Y/android-app - -see includes/playstore.php - -[android-app](/go/developer/16.0/android-app) - -[live: android-app](https://keyman.com/go/developer/16.0/android-app) - - ----- - -## download - -[keyman-windows](/go/download/keyman-windows) - -[live: keyman-windows](https://keyman.com/go/download/keyman-windows) - - ----- - -## ios - -### /go/ios/X.Y/download-keyboards/languages - -[download-keyboards/languages/km](/go/ios/16.0/download-keyboards/languages/km) - -[live: download-keyboards/languages/km](https://keyman.com/go/ios/16.0/download-keyboards/languages/km) - - -### /go/ios/X.Y/download-keyboards - -[download-keyboards](/go/ios/16.0/download-keyboards) - -[live: download-keyboards](https://keyman.com/go/ios/16.0/download-keyboards) - - - ----- - -## linux - - -### "/go/linux/X.Y/download-keyboards" - -[download-keyboards](/go/linux/16.0/download-keyboards) - -[live: download-keyboards](https://keyman.com/go/linux/16.0/download-keyboards) - - -### /go/linux/X.Y/forums - -[forums](/go/linux/16.0/forums) - -[live: forums](https://keyman.com/go/linux/16.0/forums) - -### /go/linux/X.Y/support - -[support](/go/linux/16.0/support) - -[live: support](https://keyman.com/go/linux/16.0/support) - - -### /go/linux/X.Y/privacy - -[privacy](/go/linux/16.0/privacy) - -[live: privacy](https://keyman.com/go/linux/16.0/privacy) - -### /go/linux/X.Y/linux-configuration.png - -permanent link to screenshot of linux-configuration - -[linux-configuration.png](/go/linux/16.0/linux-configuration.png) - -[live: linux-configuration.png](https://keyman.com/go/linux/16.0/linux-configuration.png) - - ----- - -## macos - -### /go/macos/X.Y/download-keyboards - -[download-keyboards](/go/macos/16.0/download-keyboards) - -[live: download-keyboards](https://keyman.com/go/macos/16.0/download-keyboards) - ----- - -## package (no .htaccess to check) - - ----- - -## windows - -Links for Keyman for Windows 14.0 onward - -### /go/windows/X.Y/download-keyboards - -[download-keyboards](/go/windows/16.0/download-keyboards) - -[live: download-keyboards](https://keyman.com/go/windows/16.0/download-keyboards) - - -### /go/windows/X.Y/keep-in-touch - -[keep-in-touch](/go/windows/16.0/keep-in-touch) - -[live: keep-in-touch](https://keyman.com/go/windows/16.0/keep-in-touch) - - -### /go/windows/X.Y/issue-1285 - -[issue-1285](/go/windows/16.0/issue-1285) - -[live: issue-1285](https://keyman.com/go/windows/16.0/issue-1285) - -### /go/windows/X.Y/create-locale - -[create-locale](/go/windows/16.0/create-locale) - -[live: create-locale](https://keyman.com/go/windows/16.0/create-locale) - - -### /go/windows/X.Y/home - -[home](/go/windows/16.0/home) - -[live: home](https://keyman.com/go/windows/16.0/home) - - -### /go/windows/X.Y/archived-downloads - -[archived-downloads](/go/windows/16.0/archived-downloads) +## Other Test Pages -[live: archived-downloads](https://keyman.com/go/windows/16.0/archived-downloads) +[/go links](./go) +[/keyboards links](./keyboards) ----- \ No newline at end of file +[/_legacy keyboards links](./legacy) From 9ab8efb38fbb8da7b5d84741436a3a421e995543 Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Wed, 25 Oct 2023 11:32:16 +0700 Subject: [PATCH 50/73] fix: keyboard links --- .htaccess | 21 +++++++------ test/go.md | 8 ++++- test/keyboards.md | 78 +++++++++++++++++++++-------------------------- 3 files changed, 53 insertions(+), 54 deletions(-) diff --git a/.htaccess b/.htaccess index afdf20fc..b710f1b2 100644 --- a/.htaccess +++ b/.htaccess @@ -61,20 +61,21 @@ RewriteRule "^downloads/releases(\/)?$" "/downloads" [R,END] # Cleanup various URLS with permanent redirects # /keyboards/{install|download|share}/{id}/ to /keyboards/x/id -# RedirectMatch "^keyboards/(install|download|share)/([^/]+)/$" "/keyboards/$1/$2" +# Remove final / RewriteRule "^keyboards/(install|download|share)/([^/]+)/$" "/keyboards/$1/$2" [R=301,END,QSA] # /keyboards/{id}/ to /keyboards/id -RedirectMatch 301 "^keyboards/([^/]+)/$" "/keyboards/$1" +# Remove final / +RewriteRule "^keyboards/([^/]+)/$" "/keyboards/$1" [R=301,END,QSA] -# /keyboards/ to /keyboards -RedirectMatch 301 "^keyboards/$" "/keyboards" +# /keyboards/ to /keyboards (Handled by other redirect) +# Remove final / # Old share url /keyboards/{id}/share[/] to /keyboards/share/id -RedirectMatch "^keyboards/(?!install|download|share)/share(/?)$" "/keyboards/share/$1" +RewriteRule "^keyboards/(.*)/share(/?)$" "/keyboards/share.php?id=$1" [R=301] # /keyboard/{content} to /keyboards/... -RewriteRule "^keyboard(/.*)$" "/keyboards$1" [L] +RewriteRule "^keyboard(/.*)$" "/keyboards$1" [R,END] # # Install | Download | Share | bare | .json --> @@ -90,7 +91,7 @@ RewriteRule "^keyboards/download/([^/]+)$" "/keyboards/keyboard.php?id=$1" [END, # /keyboards/share/[id] to /keyboards/share.php # if the keyboard exists in the repo, then share.php will redirect to /keyboards/ -RewriteRule "^keyboards/share/([^/]+)$" "/keyboards/share.php?id=$1" [L] +RewriteRule "^keyboards/share/([^/]+)$" "/keyboards/share.php?id=$1" [END] # /keyboards/{id}.json to /keyboards/keyboard.json.php RewriteRule "^keyboards/(?!keyboard.json)(.*)\.json$" "/keyboards/keyboard.json.php?id=$1" [END] @@ -107,13 +108,13 @@ RewriteRule "^keyboards/(?!index\.php|install|keyboard|session|share)([^/]+)$" " # RewriteRule "^keyboards$" "/keyboards/index.php" [L] # /keyboards/languages to /keyboards/index.php -RewriteRule "^keyboards/languages/(.*)" "/keyboards/index.php?q=l:id:$1" [L] +RewriteRule "^keyboards/languages/(.*)" "/keyboards/index.php?q=l:id:$1" [END] # /keyboards/download to /keyboards/download.php -RewriteRule "^keyboards/download(.php)?" "/keyboards/download.php" [L,QSA] +RewriteRule "^keyboards/download(.php)?" "/keyboards/download.php" [END,QSA] # /keyboards/legacy to /keyboards/keyboard.php -RewriteRule "^keyboards/legacy/(.*)" "/keyboards/keyboard.php?legacy=$1" [L] +RewriteRule "^keyboards/legacy/(.*)" "/keyboards/keyboard.php?legacy=$1" [END] # /keyboards/countries to /keyboards/index.php RewriteRule "^keyboards/countries/(.*)" "/keyboards/index.php?q=c:id:$1" [END] diff --git a/test/go.md b/test/go.md index 5151c749..bc17b15f 100644 --- a/test/go.md +++ b/test/go.md @@ -394,4 +394,10 @@ Links for Keyman for Windows 14.0 onward [live: archived-downloads](https://keyman.com/go/windows/16.0/archived-downloads) ----- \ No newline at end of file +---- + +### /go/keyboard/id/share + +[keyboard/sil_ipa/share](/go/keyboard/sil_ipa/share) + +[live: keyboard/sil_ipa/share](https://keyman.com/go/keyboard/sil_ipa/share) diff --git a/test/keyboards.md b/test/keyboards.md index 676ac704..8f5f1bee 100644 --- a/test/keyboards.md +++ b/test/keyboards.md @@ -4,13 +4,8 @@ description: Test page for keyboard links showmenu: false --- -## Keyboards -### keyboard/id/share - -[keyboard/sil_ipa/share](/go/keyboard/sil_ipa/share) - -[live: keyboard/sil_ipa/share](https://keyman.com/go/keyboard/sil_ipa/share) +## keyboards/{install|download|share}/id ### keyboards/install/id @@ -24,75 +19,72 @@ showmenu: false [live: keyboards/download/sil_ipa](https://keyman.com/keyboards/download/sil_ipa) -### keyboards/id.json +### keyboards/share/id -[keyboards/sil_ipa.json](/keyboards/sil_ipa.json) +[keyboards/share/sil_ipa](/keyboards/share/sil_ipa) -[live: keyboards/sil_ipa.json](https://keyman.com/keyboards/sil_ipa.json) +[live: keyboards/share/sil_ipa](https://keyman.com/keyboards/share/sil_ipa) -### keyboards/countries/id - -[keyboards/countries/kh](/keyboards/countries/kh) +---- -[live: keyboards/countries/kh](https://keyman.com/keyboards/countries/kh) +### keyboards/id/ ----- +[keyboards/sil_ipa/](/keyboards/sil_ipa/) -## legacy /keyboards +[live: keyboards/sil_ipa/](https://keyman.com/keyboards/sil_ipa/) -[_legacy/keyboards](/_legacy/keyboards) +### keyboards/ -[live: _legacy/keyboards](https://keyman.com/_legacy/keyboards) +[keyboards/](/keyboards/) -[_legacy/keyboards/](/_legacy/keyboards/) +[live: keyboards/](https://keyman.com/keyboards/) -[live: _legacy/keyboards/](https://keyman.com/_legacy/keyboards/) +### Old share keyboards/id/share +[keyboards/sil_ipa/share](/keyboards/sil_ipa/share) -### legacy /keyboards/languages/id +[live: keyboards/sil_ipa/share](https://keyman.com/keyboards/sil_ipa/share) -[_legacy/keyboards/languages/km](/_legacy/keyboards/languages/km) -[live: _legacy/keyboards/languages/km](https://keyman.com/_legacy/keyboards/languages/km) +### keyboard/{content} -### legacy /keyboards/download +[keyboard/sil_ipa](/keyboard/sil_ipa) -[_legacy/keyboards/download](/_legacy/keyboards/download?id=sil_ipa&platform=windows&mode=standalone) +[live: keyboard/sil_ipa](https://keyman.com/keyboard/sil_ipa) -[live: _legacy/keyboards/download](https://keyman.com/_legacy/keyboards/download?id=sil_ipa&platform=windows&mode=standalone) -### legacy /keyboards/legacy +## Install | Download | Share | bare | .json -[_legacy/keyboards/legacy/id](/_legacy/keyboards/legacy/sil_ipa) +### keyboards/id.json -[live: _legacy/keyboards/legacy/id](https://keyman.com/_legacy/keyboards/legacy/sil_ipa) +[keyboards/sil_ipa.json](/keyboards/sil_ipa.json) -### legacy /keyboards/countries/id +[live: keyboards/sil_ipa.json](https://keyman.com/keyboards/sil_ipa.json) -[_legacy/keyboards/countries/kh](/_legacy/keyboards/countries/kh) +---- -[live: _legacy/keyboards/countries/kh](https://keyman.com/_legacy/keyboards/countries/kh) +## Search -### legacy /keyboards/id/share +### keyboards/languages/id -[_legacy/keyboards/sil_ipa/share](/_legacy/keyboards/sil_ipa/share) +[keyboards/languages/km](/keyboards/languages/km) -[live: _legacy/keyboards/sil_ipa/share](https://keyman.com/_legacy/keyboards/sil_ipa/share) +[live: keyboards/languages/km](https://keyman.com/keyboards/languages/km) -### legacy /keyboards/id.json +### keyboards/download.php -[_legacy/keyboards/sil_ipa.json](/_legacy/keyboards/sil_ipa.json) +[keyboards/download.php?id=sil_ipa](/keyboards/download.php?id=sil_ipa) -[live: _legacy/keyboards/sil_ipa.json](https://keyman.com/_legacy/keyboards/sil_ipa.json) +[live: keyboards/download.php?id=sil_ipa](https://keyman.com/keyboards/download.php?id=sil_ipa) -### legacy /keyboards/id +### keyboards/legacy -[_legacy/keyboards/sil_ipa](/_legacy/keyboards/sil_ipa) +[keyboards/legacy/cameroon querty non-u kbd-fonts](/keyboards/legacy/cameroon%20qwerty%20non-u%20kbd-fonts) -[live: _legacy/keyboards/sil_ipa](https://keyman.com/_legacy/keyboards/sil_ipa) +[live: keyboards/legacy/cameroon querty non-u kbd-fonts](https://keyman.com/keyboards/legacy/cameroon%20qwerty%20non-u%20kbd-fonts) -### legacy /keyboard/id +### keyboards/countries/id -[_legacy/keyboard/sil_ipa](/_legacy/keyboard/sil_ipa) +[keyboards/countries/kh](/keyboards/countries/kh) -[live: _legacy/keyboard/sil_ipa](https://keyman.com/_legacy/keyboard/sil_ipa) \ No newline at end of file +[live: keyboards/countries/kh](https://keyman.com/keyboards/countries/kh) From 7cebe2a01eda479075e36fc8c3378d52da86fc8d Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Thu, 26 Oct 2023 13:25:46 +0700 Subject: [PATCH 51/73] revert share --- .htaccess | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.htaccess b/.htaccess index b710f1b2..d5012540 100644 --- a/.htaccess +++ b/.htaccess @@ -72,7 +72,7 @@ RewriteRule "^keyboards/([^/]+)/$" "/keyboards/$1" [R=301,END,QSA] # Remove final / # Old share url /keyboards/{id}/share[/] to /keyboards/share/id -RewriteRule "^keyboards/(.*)/share(/?)$" "/keyboards/share.php?id=$1" [R=301] +RewriteRule "^keyboards/(.*)/share(/?)$" "/keyboards/share/$1" [R=301] # /keyboard/{content} to /keyboards/... RewriteRule "^keyboard(/.*)$" "/keyboards$1" [R,END] From 2eece10ebf00ccfa99be17de3b2fbdb25ee73d33 Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Tue, 31 Oct 2023 07:17:37 +0700 Subject: [PATCH 52/73] chore: Move internal test pages to _test --- {test => _test}/go.md | 0 {test => _test}/index.md | 10 +++++++--- {test => _test}/keyboards.md | 0 {test => _test}/legacy.md | 0 4 files changed, 7 insertions(+), 3 deletions(-) rename {test => _test}/go.md (100%) rename {test => _test}/index.md (68%) rename {test => _test}/keyboards.md (100%) rename {test => _test}/legacy.md (100%) diff --git a/test/go.md b/_test/go.md similarity index 100% rename from test/go.md rename to _test/go.md diff --git a/test/index.md b/_test/index.md similarity index 68% rename from test/index.md rename to _test/index.md index a24f6355..71d08cdb 100644 --- a/test/index.md +++ b/_test/index.md @@ -1,6 +1,6 @@ --- -title: Test Links -description: Test pages for links +title: Internal Test Links +description: Internal Test Pages for Checking Broken Links showmenu: false --- @@ -16,10 +16,14 @@ showmenu: false [live: desktop to Windows](https://keyman.com/desktop/download) -## Other Test Pages +## Links to Other Test Pages [/go links](./go) [/keyboards links](./keyboards) [/_legacy keyboards links](./legacy) + +## Link to Main Page + +[Main Page](/) diff --git a/test/keyboards.md b/_test/keyboards.md similarity index 100% rename from test/keyboards.md rename to _test/keyboards.md diff --git a/test/legacy.md b/_test/legacy.md similarity index 100% rename from test/legacy.md rename to _test/legacy.md From 0c25170402572ee708c0b26e6463be57e2b58ec8 Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Tue, 31 Oct 2023 07:18:04 +0700 Subject: [PATCH 53/73] chore: have link checker start at /_test --- .github/workflows/ci.yml | 2 +- build.sh | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a5c7c65f..dc82c023 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -34,7 +34,7 @@ jobs: run: | set +e; set +o pipefail; - npx broken-link-checker http://localhost:8053 --ordered --recursive --host-requests 50 -e --filter-level 3 | \ + npx broken-link-checker http://localhost:8053/test --ordered --recursive --host-requests 50 -e --filter-level 3 | \ grep -E "BROKEN|Getting links from" | \ grep -B 1 "BROKEN" exit ${PIPESTATUS[0]} diff --git a/build.sh b/build.sh index 75b7f7aa..dd8cae3b 100755 --- a/build.sh +++ b/build.sh @@ -33,9 +33,9 @@ function test_docker_container() { echo "---- Testing links ----" set +e; set +o pipefail; - npx broken-link-checker http://localhost:8053 --ordered --recursive --host-requests 50 -e --filter-level 3 | \ - grep -E "BROKEN|Getting links from" | \ - grep -B 1 "BROKEN"; + npx broken-link-checker http://localhost:8053/_test --recursive --ordered ---host-requests 50 -e --filter-level 3 #| \ + #grep -E "BROKEN|Getting links from" | \ + #grep -B 1 "BROKEN"; echo "Done checking links" rm tier.txt From bdae5876a0c9adbc3719ab10469aaf2046d6ff28 Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Tue, 31 Oct 2023 07:23:42 +0700 Subject: [PATCH 54/73] chore: undo comments --- build.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/build.sh b/build.sh index dd8cae3b..fe21743a 100755 --- a/build.sh +++ b/build.sh @@ -33,9 +33,9 @@ function test_docker_container() { echo "---- Testing links ----" set +e; set +o pipefail; - npx broken-link-checker http://localhost:8053/_test --recursive --ordered ---host-requests 50 -e --filter-level 3 #| \ - #grep -E "BROKEN|Getting links from" | \ - #grep -B 1 "BROKEN"; + npx broken-link-checker http://localhost:8053/_test --recursive --ordered ---host-requests 50 -e --filter-level 3 | \ + grep -E "BROKEN|Getting links from" | \ + grep -B 1 "BROKEN"; echo "Done checking links" rm tier.txt From 6eb11ef151c47c79d5a905fc4455574141820183 Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Tue, 31 Oct 2023 07:25:20 +0700 Subject: [PATCH 55/73] fix: ci link --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index dc82c023..4df86ded 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -34,7 +34,7 @@ jobs: run: | set +e; set +o pipefail; - npx broken-link-checker http://localhost:8053/test --ordered --recursive --host-requests 50 -e --filter-level 3 | \ + npx broken-link-checker http://localhost:8053/_test --ordered --recursive --host-requests 50 -e --filter-level 3 | \ grep -E "BROKEN|Getting links from" | \ grep -B 1 "BROKEN" exit ${PIPESTATUS[0]} From f20ef6df5b4a4cfa4d7a0a150cd10170aafe6a81 Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Thu, 9 Nov 2023 08:53:30 +0700 Subject: [PATCH 56/73] fix: Attempt to fix BLC_UNKNOWN --- .htaccess | 2 -- go/developer/.htaccess | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/.htaccess b/.htaccess index d5012540..56bc599d 100644 --- a/.htaccess +++ b/.htaccess @@ -26,8 +26,6 @@ AddType application/json apple-app-site-association RewriteRule "^.well-known/apple-app-site-association$" "/.well-known/apple-app-site-association.json" [L] RewriteRule "^apple-app-site-association$" "/.well-known/apple-app-site-association.json" [L] -# TODO: Append query strings 12x [QSA] - # macosx and macos to mac (ignore case) RedirectMatch 301 "^(?i)/(macosx|macos)\b(.*)$" "/mac$2" diff --git a/go/developer/.htaccess b/go/developer/.htaccess index 4f0053e1..3e638e5e 100644 --- a/go/developer/.htaccess +++ b/go/developer/.htaccess @@ -17,7 +17,7 @@ RedirectMatch "/go/developer/([1-9][0-9]\.[0-9])/keyman-engine-home" "/engine/" # "/go/developer/X.Y/language-lookup" -RedirectMatch "/go/developer/([1-9][0-9]\.[0-9])/language-lookup" "https://www.ethnologue.com/" +RedirectMatch 301 "/go/developer/([1-9][0-9]\.[0-9])/language-lookup" "https://www.ethnologue.com/" # "/go/developer/X.Y/view-exception/ to /contact/exception" From 9acf1d542b9d13f058311611a3bf079eefea15fe Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Mon, 13 Nov 2023 14:01:17 +0700 Subject: [PATCH 57/73] fix: disable language-lookup --- _test/go.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/_test/go.md b/_test/go.md index bc17b15f..f0227d0d 100644 --- a/_test/go.md +++ b/_test/go.md @@ -201,12 +201,13 @@ Direct help to the major version [live: keyman-engine-home](https://keyman.com/go/developer/16.0/keyman-engine-home) -### /go/developer/X.Y/language-lookup - -[language-lookup](/go/developer/16.0/language-lookup) - -[live: language-lookup](https://keyman.com/go/developer/16.0/language-lookup) +### Skipping /go/developer/X.Y/language-lookup +ethnlogue has a redirect that the link checker does not follow. BLC is returning BLC_UNKNOWN -- it gets the base link but then doesn't follow the redirect so it doesn't know if it is valid or not. +``` +/go/developer/16.0/language-lookup +live: https://keyman.com/go/developer/16.0/language-lookup +``` ### /go/developer/X.Y/view-exception/ to /contact/exception From 2b2cbed5739e50dad9ef46e173925105118320af Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Mon, 13 Nov 2023 18:08:06 +0700 Subject: [PATCH 58/73] Update _test/go.md Co-authored-by: Marc Durdin --- _test/go.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_test/go.md b/_test/go.md index f0227d0d..ee89838f 100644 --- a/_test/go.md +++ b/_test/go.md @@ -202,7 +202,7 @@ Direct help to the major version ### Skipping /go/developer/X.Y/language-lookup -ethnlogue has a redirect that the link checker does not follow. BLC is returning BLC_UNKNOWN -- it gets the base link but then doesn't follow the redirect so it doesn't know if it is valid or not. +keyman.com has a redirect to ethnologue that the link checker does not follow. BLC is returning BLC_UNKNOWN -- it gets the base link but then doesn't follow the redirect so it doesn't know if it is valid or not. ``` /go/developer/16.0/language-lookup From 30f9d3a49e29e0d7f27cd8cb45cdf0bbc83763c1 Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Mon, 13 Nov 2023 19:25:20 +0700 Subject: [PATCH 59/73] fix: getenv() instead of $_SERVER vars --- _includes/includes/template.php | 5 ++++- go/package/download.php | 4 +++- keyboards/h/sinhala/index.php | 3 ++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/_includes/includes/template.php b/_includes/includes/template.php index 667d9c9c..658a5069 100644 --- a/_includes/includes/template.php +++ b/_includes/includes/template.php @@ -6,6 +6,8 @@ require_once(__DIR__ . '/../2020/KeymanVersion.php'); require_once(__DIR__ . '/../2020/templates/Head.php'); + $env = getenv(); + function template_finish($foot) { //ob_end_flush(); @@ -16,8 +18,9 @@ function template_finish($foot) { function head($args=[]){ // Args are title='My Page Title', css='page.css' showMenu=true/false, showHeader=true/false, foot=true/false + global $env; - $agent = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : ''; + $agent = isset($env['HTTP_USER_AGENT']) ? $env['HTTP_USER_AGENT'] : ''; // Get device if (strstr($agent,'Windows')) { $device = 'Windows'; diff --git a/go/package/download.php b/go/package/download.php index 9023a365..6b1273ad 100644 --- a/go/package/download.php +++ b/go/package/download.php @@ -12,6 +12,7 @@ use Keyman\Site\Common\KeymanHosts; use Keyman\Site\Common\JsonApiFailure; + $env = getenv(); KeymanComSentry::init(); PackageDownloadPage::redirect_to_file( @@ -91,13 +92,14 @@ public static function redirect_to_file($type, $id, $version, $platform, $tier, } private static function report_download_event($id, $platform, $tier, $bcp47, $update) { + global $env; $url = KeymanHosts::Instance()->api_keyman_com . "/increment-download/".rawurlencode($id); if(KeymanHosts::Instance()->Tier() !== KeymanHosts::TIER_TEST) { if(KeymanHosts::Instance()->Tier() === KeymanHosts::TIER_DEVELOPMENT) $key = 'local'; else - $key = $_SERVER['API_KEYMAN_COM_INCREMENT_DOWNLOAD_KEY']; + $key = $env['API_KEYMAN_COM_INCREMENT_DOWNLOAD_KEY']; $c = curl_init($url); curl_setopt($c, CURLOPT_HEADER, 0); diff --git a/keyboards/h/sinhala/index.php b/keyboards/h/sinhala/index.php index 285d0040..c6ddc4e9 100644 --- a/keyboards/h/sinhala/index.php +++ b/keyboards/h/sinhala/index.php @@ -1,5 +1,6 @@ Date: Tue, 14 Nov 2023 06:32:03 +0700 Subject: [PATCH 60/73] revert: Keep HTTP_ vars --- _includes/includes/template.php | 5 +---- keyboards/h/sinhala/index.php | 3 +-- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/_includes/includes/template.php b/_includes/includes/template.php index 658a5069..667d9c9c 100644 --- a/_includes/includes/template.php +++ b/_includes/includes/template.php @@ -6,8 +6,6 @@ require_once(__DIR__ . '/../2020/KeymanVersion.php'); require_once(__DIR__ . '/../2020/templates/Head.php'); - $env = getenv(); - function template_finish($foot) { //ob_end_flush(); @@ -18,9 +16,8 @@ function template_finish($foot) { function head($args=[]){ // Args are title='My Page Title', css='page.css' showMenu=true/false, showHeader=true/false, foot=true/false - global $env; - $agent = isset($env['HTTP_USER_AGENT']) ? $env['HTTP_USER_AGENT'] : ''; + $agent = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : ''; // Get device if (strstr($agent,'Windows')) { $device = 'Windows'; diff --git a/keyboards/h/sinhala/index.php b/keyboards/h/sinhala/index.php index c6ddc4e9..285d0040 100644 --- a/keyboards/h/sinhala/index.php +++ b/keyboards/h/sinhala/index.php @@ -1,6 +1,5 @@ Date: Wed, 15 Nov 2023 12:39:11 +0700 Subject: [PATCH 61/73] chore: Test .well-known/ links --- .htaccess | 1 - _test/index.md | 2 ++ _test/well-known.md | 13 +++++++++++++ 3 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 _test/well-known.md diff --git a/.htaccess b/.htaccess index 56bc599d..a096b311 100644 --- a/.htaccess +++ b/.htaccess @@ -24,7 +24,6 @@ AddType application/json apple-app-site-association # apple-app-site-association RewriteRule "^.well-known/apple-app-site-association$" "/.well-known/apple-app-site-association.json" [L] -RewriteRule "^apple-app-site-association$" "/.well-known/apple-app-site-association.json" [L] # macosx and macos to mac (ignore case) RedirectMatch 301 "^(?i)/(macosx|macos)\b(.*)$" "/mac$2" diff --git a/_test/index.md b/_test/index.md index 71d08cdb..b9ee79eb 100644 --- a/_test/index.md +++ b/_test/index.md @@ -24,6 +24,8 @@ showmenu: false [/_legacy keyboards links](./legacy) +[/well-known links](./well-known) + ## Link to Main Page [Main Page](/) diff --git a/_test/well-known.md b/_test/well-known.md new file mode 100644 index 00000000..a275af3f --- /dev/null +++ b/_test/well-known.md @@ -0,0 +1,13 @@ +--- +title: Test Links for .well-known +description: Test page for .well-known links +showmenu: false +--- + +## .well-known + +### apple-app-site-association + +[apple-app-association](/.well-known/apple-app-site-association) + +[live: apple-app-association](https://keyman.com/.well-known/apple-app-site-association) From 2e2ecc94293620339e0a22b39d7b3c923fbdceb7 Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Wed, 15 Nov 2023 12:44:56 +0700 Subject: [PATCH 62/73] chore: Cleanup redirect for live site --- .htaccess | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/.htaccess b/.htaccess index a096b311..52d2c94a 100644 --- a/.htaccess +++ b/.htaccess @@ -10,13 +10,7 @@ DirectorySlash off RewriteEngine on RewriteBase / -# Redirect http://keyman.com to https://keyman.com, -# but only if on a live site (keyman.com) and not -# matching `/.well-known/(.*)$` (for Let's Encrypt) - - Redirect 301 "/" "https://keyman.com" - - +# Add mime type for apple-app-site-association AddType application/json apple-app-site-association # Custom error messages From 7b5632883317b85e6bbd2fd0f9f16ed72e996d54 Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Wed, 15 Nov 2023 13:37:34 +0700 Subject: [PATCH 63/73] chore: Also test language landing pages --- _test/index.md | 7 +++ _test/language-landing.md | 111 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 118 insertions(+) create mode 100644 _test/language-landing.md diff --git a/_test/index.md b/_test/index.md index b9ee79eb..be6b99b7 100644 --- a/_test/index.md +++ b/_test/index.md @@ -4,6 +4,11 @@ description: Internal Test Pages for Checking Broken Links showmenu: false --- +## Connect With Art + +[connectwithart](/connectwithart) + +[live: connectwithart](https://keyman.com/connectwithart) ## Products @@ -22,6 +27,8 @@ showmenu: false [/keyboards links](./keyboards) +[keyboard language landing links](./language-landing) + [/_legacy keyboards links](./legacy) [/well-known links](./well-known) diff --git a/_test/language-landing.md b/_test/language-landing.md new file mode 100644 index 00000000..c8b111e3 --- /dev/null +++ b/_test/language-landing.md @@ -0,0 +1,111 @@ +--- +title: Test Links of Keyboard Language Landing Pages +description: Test page for keyboard language landing links +showmenu: false +--- + + +## per-language landing pages + +[/albanian](/albanian) + +[/ancient-egyptian](/ancient-egyptian) + +[ancient-hebrew](/ancient-hebrew) + +[/arabic](/arabic) + +[/assamese](/assamese) + +[/basic_kbdsn1](/basic_kbdsn1) + +[/bengali](/bengali) + +[/cherokee](/cherokee) + +[/cheyenne](/cheyenne) + +[/dinka](/dinka) + +[/dutch](/dutch) + +[/farsi](/farsi) + +[/hebrew](/hebrew) + +[/hindi](/hindi) + +[/igbo](/igbo) + +[/khmer](/khmer) + +[/lao](/lao) + +[/malayalam](/malayalam) + +[/maltese](/maltese) + +[/marathi](/marathi) + +[/mongolian](/mongolian) + +[/nepali](/nepali) + +[/oriya](/oriya) + +[/rawang](/rawang) + +[/russian](/russian) + +[/serbian](/serbian) + +[/sindhi](/sindhi) + +[/thai](/thai) + +[/yiddish](/yiddish) + +[/yoruba](/yoruba) + + +### eurolatin + +[/ancient-greek](/ancient-greek) + +[/french](/french) + +[/german](/german) + +[/italian](/italian) + +[/spanish](/spanish) + +[/swedish](/swedish) + +----- + +## dedicated-keyboard-landing pages + +[/amharic](/amharic) + +[/burmese](/burmese) + +[/cameroon](/cameroon) + +[/ethiopic](/ethiopic) + +[/eurolatin](/eurolatin) + +[/greek](/greek) + +[/ipa](/ipa) + +[/sinhala](/sinhala) + +[/tamil](/tamil) + +[/tibetan](/tibetan) + +[/tigrigna](/tigrigna) + +[/urdu](/urdu) From c98753781d047b2e198e58e39f45a1295ed0dfb2 Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Wed, 15 Nov 2023 15:55:37 +0700 Subject: [PATCH 64/73] chore: add control/info --- _control/info.php | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 _control/info.php diff --git a/_control/info.php b/_control/info.php new file mode 100644 index 00000000..4102694d --- /dev/null +++ b/_control/info.php @@ -0,0 +1,5 @@ +TIER: " . KeymanHosts::Instance()->Tier() . "

"; From 8f661b46c41755412a14916c857c3fcfa0cb933a Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Sat, 25 Nov 2023 07:02:05 +0700 Subject: [PATCH 65/73] fix: Pin sha of php:7.4-apache This pins the sha of the Docker image for php:7.4-apache. Relates to keymanapp/keyman.com#403 --- Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 4a37f3c9..71f0b396 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ # syntax=docker/dockerfile:1 -FROM php:7.4-apache AS composer-builder +FROM php:7.4-apache@sha256:c9d7e608f73832673479770d66aacc8100011ec751d1905ff63fae3fe2e0ca6d AS composer-builder # Install Zip to use composer RUN apt-get update && apt-get install -y \ @@ -18,7 +18,7 @@ COPY composer.* /composer/ RUN composer install # Site -FROM php:7.4-apache +FROM php:7.4-apache@sha256:c9d7e608f73832673479770d66aacc8100011ec751d1905ff63fae3fe2e0ca6d COPY resources/keyman-site.conf /etc/apache2/conf-available/ RUN cp /usr/local/etc/php/php.ini-production /usr/local/etc/php/php.ini RUN chown -R www-data:www-data /var/www/html/ From 7f3c33deb021278cb625a8660a0c1079a416951f Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Tue, 12 Dec 2023 14:33:04 +0700 Subject: [PATCH 66/73] chore: trivial readme.md --- README.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 00000000..950cf704 --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +# keyman.com \ No newline at end of file From 1e54f2770bf59e8f2ab84c1693c115f51c297ed2 Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Thu, 18 Jan 2024 13:56:15 +0700 Subject: [PATCH 67/73] chore: Update readme to trigger webhook --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 950cf704..c900463d 100644 --- a/README.md +++ b/README.md @@ -1 +1,3 @@ -# keyman.com \ No newline at end of file +# keyman.com + +TODO From ae365da28e6011e0a31890bf4377581dfa7a9d1f Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Fri, 26 Jan 2024 10:03:36 +0700 Subject: [PATCH 68/73] chore: Add _control/ready --- .htaccess | 2 ++ _control/ready.php | 15 +++++++++++++++ 2 files changed, 17 insertions(+) create mode 100644 _control/ready.php diff --git a/.htaccess b/.htaccess index 52d2c94a..a9276a04 100644 --- a/.htaccess +++ b/.htaccess @@ -44,6 +44,8 @@ RewriteRule "^downloads/releases/(?!_version_downloads\b)(.+)$" "/downloads/rele # index RewriteRule "^downloads/releases(\/)?$" "/downloads" [R,END] +# Ready +RewriteRule "^_control/ready$" "_control/ready.php" [END] # # Keyboard landing pages (TODO) diff --git a/_control/ready.php b/_control/ready.php new file mode 100644 index 00000000..f9e1766f --- /dev/null +++ b/_control/ready.php @@ -0,0 +1,15 @@ + Date: Fri, 26 Jan 2024 10:11:58 +0700 Subject: [PATCH 69/73] fix: Add content type --- _control/ready.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/_control/ready.php b/_control/ready.php index f9e1766f..071f8ef1 100644 --- a/_control/ready.php +++ b/_control/ready.php @@ -1,4 +1,6 @@ Date: Thu, 1 Feb 2024 10:49:14 +0700 Subject: [PATCH 70/73] fix: go links for model/keyboards --- _test/go.md | 35 ++++++++++++++++++++++++++++++++++- go/.htaccess | 19 ++++++++++++++++--- 2 files changed, 50 insertions(+), 4 deletions(-) diff --git a/_test/go.md b/_test/go.md index ee89838f..ed64ed2a 100644 --- a/_test/go.md +++ b/_test/go.md @@ -345,8 +345,41 @@ permanent link to screenshot of linux-configuration ---- -## package (no .htaccess to check) +## keyboard permalinks +### download-kmp + +[keyboard/khmer_angkor/download/kmp](/go/keyboard/khmer_angkor/download/kmp) + +[live: keyboard/khmer_angkor/download/kmp](https://keyman.com/go/keyboard/khmer_angkor/download/kmp) + +### download-exe + +[keyboard/khmer_angkor/download/exe](/go/keyboard/khmer_angkor/download/exe) + +[live: keyboard/khmer_angkor/download/exe](https://keyman.com/go/keyboard/khmer_angkor/download/exe) + +### download-js + +[keyboard/khmer_angkor/download/js](/go/keyboard/khmer_angkor/download/js) + +[live: keyboard/khmer_angkor/download/js](https://keyman.com/go/keyboard/khmer_angkor/download/js) + +--- + +## package/download + +### model + +[nrc.en.mtmt](/go/package/download/model/nrc.en.mtnt) + +[live: nrc.en.mtnt](https://keyman.com/go/package/download/model/nrc.en.mtnt) + +### keyboard, platform=android&tier=alpha + +[khmer_angkor](/go/package/download/khmer_angkor&platform=android&tier=alpha) + +[live: khmer_angkor](https://keyman.com/go/package/download/khmer_angkor&platform=android&tier=alpha) ---- diff --git a/go/.htaccess b/go/.htaccess index 74541387..56e046cf 100644 --- a/go/.htaccess +++ b/go/.htaccess @@ -5,14 +5,27 @@ RedirectMatch "/go/why\/?$" "https://marc.durdin.net/2018/03/the-case-for-keyman # Developer 10.0 onward redirects for package guide RedirectMatch "/go/(([1-9][0-9])([.]?)([0-9]))/developer-help-(mobile|packages)(/)?" "https://help.keyman.com/developer/$1/guides/distribute/packages" -# TODO: Download redirects for keyboard permalinks (these three rules need refresh) +# Download redirects for keyboard permalinks (TODO: these three rules need refresh) + +# download-kmp +RedirectMatch "/go/keyboard/([^/?]+)/download/kmp$" "/keyboards/download?id=$1&platform=windows&mode=standalone" + +#download-exe +RedirectMatch "/go/keyboard/([^/?]+)/download/exe$" "/keyboards/download?id=$1&platform=windows&mode=bundle" + +# download-js +RedirectMatch "/go/keyboard/([^/?]+)/download/js$" "/keyboards/download?id=$1&platform=web&mode=standalone" + # # go/package/download # -# download-model/keyboard package -RedirectMatch "/go/package/download/(model|keyboard)/([^/]+)\/?$" "https://keyman.com/go/package/download.php?type=$1&id=$2" +# download-model-package +RewriteRule "^package/download/model/([^/]+)$" "package/download.php?type=model&id=$1" [END,QSA] + +# download-package +RewriteRule "^package/download/(keyboard/)?([^/]+)$" "package/download.php?type=keyboard&id=$2" [END,QSA] # keyboard/id/share RedirectMatch "/go/keyboard/([^/?]+)/share$" "/keyboards/share/$1" From 7955a0982afa654cf9126542a3a47aa7c6c716e8 Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Mon, 5 Feb 2024 11:26:45 +0700 Subject: [PATCH 71/73] Update staging to use shared-sites v0.4 --- build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sh b/build.sh index fe21743a..c3ab6272 100755 --- a/build.sh +++ b/build.sh @@ -2,7 +2,7 @@ ## START STANDARD SITE BUILD SCRIPT INCLUDE readonly THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")" readonly BOOTSTRAP="$(dirname "$THIS_SCRIPT")/resources/bootstrap.inc.sh" -readonly BOOTSTRAP_VERSION=chore/v0.4 +readonly BOOTSTRAP_VERSION=v0.4 [ -f "$BOOTSTRAP" ] && source "$BOOTSTRAP" || source <(curl -fs https://raw.githubusercontent.com/keymanapp/shared-sites/$BOOTSTRAP_VERSION/bootstrap.inc.sh) ## END STANDARD SITE BUILD SCRIPT INCLUDE From 742bfa2bb6d0b5c78fc1d3b55be205f06e46169c Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Thu, 8 Feb 2024 14:05:31 +0700 Subject: [PATCH 72/73] chore: Add liveliness check --- _control/alive.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 _control/alive.txt diff --git a/_control/alive.txt b/_control/alive.txt new file mode 100644 index 00000000..e7ad0e79 --- /dev/null +++ b/_control/alive.txt @@ -0,0 +1,2 @@ +Alive + From e671b882f4b2fb0e749500b1fb7a767e24b70fb5 Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Mon, 12 Feb 2024 14:12:17 +1100 Subject: [PATCH 73/73] chore: rename alive.txt to alive --- _control/{alive.txt => alive} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename _control/{alive.txt => alive} (100%) diff --git a/_control/alive.txt b/_control/alive similarity index 100% rename from _control/alive.txt rename to _control/alive