diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 000000000..e1cc3d5ed --- /dev/null +++ b/.dockerignore @@ -0,0 +1,22 @@ +.git/ +*.zip +test/ +# keep the test database in the image here +!test/BaseWithSomeBooks/ +vendor/ +# remove docker files +docker/ +docker-compose.yaml +docker-compose-dev.yaml +# remove development files +.vscode/ +.yarn/ +#!.yarn/releases +#!.yarn/plugins +.pnp.* +# remove unused directories +resources/epub-loader/ +resources/tbszip/stuffs/ +resources/php-epub-meta/assets/ +resources/php-epub-meta/test/ +tools/ diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..5aa9925c9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,19 @@ +/feedbook/* +/coverage/* +/saucetest/* +/thumbnails/* +/vendor/ +/clover.xml +/test/text.atom +/*.phar +/cops.zip +/cops-*.zip +/cops.sublime-* +/config_local.php +/config_local.*.php +.yarn/* +#!.yarn/releases +#!.yarn/plugins +.pnp.* +.editorconfig +.gitattributes diff --git a/.gitremotes b/.gitremotes new file mode 100644 index 000000000..f8eb39775 --- /dev/null +++ b/.gitremotes @@ -0,0 +1,3 @@ +[remote "upstream"] + url = https://github.com/seblucas/cops.git + fetch = +refs/heads/*:refs/remotes/upstream/* diff --git a/.hgignore b/.hgignore deleted file mode 100644 index 96944414e..000000000 --- a/.hgignore +++ /dev/null @@ -1,2 +0,0 @@ -syntax: glob -feedbook/* diff --git a/.hgtags b/.hgtags index 1d0aed5dc..ad6f4b22a 100644 --- a/.hgtags +++ b/.hgtags @@ -11,3 +11,19 @@ c5703623704b81dca4228e211830125029cf86a1 0.2.3 5cc3b8ed121d9df57e013e050a75e5602cf2198e 0.3.0 aca483636af460c93f9817e083e85d1976aa1b7d 0.3.1 5888006bc559842de0364ec3e67f641aa1653d0e 0.3.2 +2ff58ed42cecf00b24d981426dff507fa1e86c20 0.3.3 +3cdee8daedf28e6611203ce90c90bb8906003e22 0.3.4 +89ed9654ac9c5de1695f63992aa92d55ef82f2b9 0.4.0 +07e901e7e35334e3747358ac5ba829347696a5d6 0.5.0 +4525a844482c54b57cf394887541f6c483c429d7 0.6.0 +ef69515ccafa912360c35a23e303cb180d7e95b9 0.6.1 +605e2b671bf46530fed4a13b2c5924ef1266b132 0.6.2 +2e7fb43f056b5694720b5eaedc2a9a2b7d2507f6 0.9.0 +3fda691df53aacdec7c017e576d5eefb47a7aa1b 1.0.0RC1 +0fc8e1890d9be461f734bb5f93295a5af497d929 1.0.0RC2 +681dce395a601d04a60ee5505a57b861a234f472 1.0.0RC3 +728d8d2062b27af51e02330bc67633d3ade0101e 1.0.0 +87a31fd7b1de76b704d81d85ac3a8c5c18e8f441 1.0.1 +e61fd2d791c5801b8fa67bb403305287a4ee0a49 1.1.0 +0c7dc20d311f5a60780461c69b0d2e22d175f1b0 1.1.1 +a8934d81cf995c408eef0e6088e925d295775c34 1.1.2 diff --git a/.htaccess b/.htaccess index 0603a65d0..5074d184c 100644 --- a/.htaccess +++ b/.htaccess @@ -1,6 +1,8 @@ +DirectoryIndex index.php + - XSendFile on + XSendFile on @@ -13,21 +15,72 @@ ########################################### # On WAMP one user had to add this line in his httpd.conf -# None of the abose was working +# None of the above was working ########################################### #XSendFilePath +########################################### +# If you want to use user based configuration with +# apache 2.4 + php-fpm enable this +# https://github.com/seblucas/cops/issues/213 +########################################### +#SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1 + RewriteEngine on -RewriteRule ^download/(.*)/.*\.kepub\.epub$ fetch.php?data=$1&type=epub [L] -RewriteRule ^download/(.*)/.*\.(.*)$ fetch.php?data=$1&type=$2 [L] +RewriteRule ^download/(\d*)/(\d*)/.*\.kepub\.epub$ fetch.php?data=$1&db=$2&type=epub [L] +RewriteRule ^view/(\d*)/(\d*)/.*\.kepub\.epub$ fetch.php?data=$1&db=$2&type=epub&view=1 [L] +RewriteRule ^download/(\d*)/(\d*)/.*\.(.*)$ fetch.php?data=$1&db=$2&type=$3 [L] +RewriteRule ^view/(\d*)/(\d*)/.*\.(.*)$ fetch.php?data=$1&db=$2&type=$3&view=1 [L] +RewriteRule ^download/(\d*)/.*\.kepub\.epub$ fetch.php?data=$1&type=epub [L] +RewriteRule ^view/(\d*)/.*\.kepub\.epub$ fetch.php?data=$1&type=epub&view=1 [L] +RewriteRule ^download/(\d*)/.*\.(.*)$ fetch.php?data=$1&type=$2 [L] +RewriteRule ^view/(\d*)/.*\.(.*)$ fetch.php?data=$1&type=$2&view=1 [L] + + + +ExpiresActive on + +# Data +ExpiresByType text/xml "access plus 0 seconds" +ExpiresByType application/xml "access plus 0 seconds" +ExpiresByType application/json "access plus 0 seconds" +ExpiresByType application/xhtml+xml "access plus 0 seconds" + +# Favicon (cannot be renamed) +ExpiresByType image/x-icon "access plus 1 week" + +# Media: images +ExpiresByType image/png "access plus 1 month" +ExpiresByType image/jpg "access plus 1 month" +ExpiresByType image/jpeg "access plus 1 month" + +# Webfonts +ExpiresByType font/truetype "access plus 1 month" +ExpiresByType font/opentype "access plus 1 month" +ExpiresByType application/x-font-woff "access plus 1 month" +ExpiresByType image/svg+xml "access plus 1 month" +ExpiresByType application/vnd.ms-fontobject "access plus 1 month" + +# CSS and JavaScript +ExpiresByType text/css "access plus 1 year" +ExpiresByType application/javascript "access plus 1 year" +ExpiresByType text/javascript "access plus 1 year" ########################################### # Uncomment if you wish to protect access with a password ########################################### +# If your covers and books are not available as soon as you protect it +# You can try replacing the FilesMatch directive by this one +# +# it helps for Sony PRS-TX and Aldiko, but beware fetch.php can be accessed +# without authentication (see $config ['cops_fetch_protect'] for a workaround). +########################################### +# #AuthUserFile /path/to/file #AuthGroupFile /dev/null #AuthName "Acces securise" #AuthType Basic #Require valid-user +# diff --git a/.scrutinizer.yml b/.scrutinizer.yml new file mode 100644 index 000000000..63ac8b5fd --- /dev/null +++ b/.scrutinizer.yml @@ -0,0 +1,142 @@ +filter: + excluded_paths: + - 'resources/*' + - 'test/*' + - 'tools/*' + dependency_paths: + - 'vendor/*' + +checks: + php: + fix_php_opening_tag: true + remove_php_closing_tag: true + avoid_closing_tag: true + one_class_per_file: true + side_effects_or_types: true + no_mixed_inline_html: false + require_braces_around_control_structures: true + php5_style_constructor: true + no_global_keyword: true + avoid_usage_of_logical_operators: true + psr2_class_declaration: true + no_underscore_prefix_in_properties: false + no_underscore_prefix_in_methods: false + blank_line_after_namespace_declaration: true + single_namespace_per_use: false + psr2_switch_declaration: true + psr2_control_structure_declaration: false + avoid_superglobals: false + security_vulnerabilities: true + no_exit: false + uppercase_constants: true + return_doc_comments: true + remove_extra_empty_lines: true + properties_in_camelcaps: true + prefer_while_loop_over_for_loop: true + phpunit_assertions: true + parameter_doc_comments: true + optional_parameters_at_the_end: true + no_long_variable_names: + maximum: '20' + no_goto: true + function_in_camel_caps: true + fix_use_statements: + remove_unused: true + preserve_multiple: false + preserve_blanklines: false + order_alphabetically: true + encourage_single_quotes: true + encourage_postdec_operator: true + classes_in_camel_caps: true + avoid_multiple_statements_on_same_line: true + avoid_fixme_comments: true + + javascript: + valid_typeof: true + yoda: + setting: 'Disallow Yoda Conditions' + wrap_iife: true + no_use_before_define: true + no_unused_vars: true + no_unreachable: true + no_undef: true + no_trailing_spaces: true + no_space_before_semi: true + no_shadow: true + no_self_compare: true + no_script_url: true + no_return_assign: true + no_reserved_keys: true + no_redeclare: true + no_mixed_spaces_and_tabs: true + no_loop_func: true + no_irregular_whitespace: true + +coding_style: + php: + spaces: + around_operators: + concatenation: true + ternary_operator: + before_condition: false + after_condition: false + before_alternative: false + after_alternative: false + other: + after_type_cast: false + braces: + classes_functions: + class: new-line + function: new-line + closure: end-of-line + if: + opening: end-of-line + for: + opening: end-of-line + while: + opening: end-of-line + do_while: + opening: end-of-line + switch: + opening: end-of-line + try: + opening: end-of-line + upper_lower_casing: + keywords: + general: lower + constants: + true_false_null: lower + +tools: + php_analyzer: true + php_code_sniffer: + config: + standard: "PSR2" + php_cs_fixer: + enabled: true + config: { level: psr2 } + php_mess_detector: true + php_loc: + enabled: true + excluded_dirs: [vendor] + php_code_coverage: + test_command: vendor/bin/phpunit + +build: + environment: + timezone: "Europe/Berlin" + php: "7.1.12" + mysql: false + postgresql: false + redis: false + dependencies: + before: + - sudo composer selfupdate + - composer global require "fxp/composer-asset-plugin:~1.1" + tests: + override: + - + command: "vendor/bin/phpunit" + coverage: + file: "clover.xml" + format: "clover" diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 000000000..25db5f6f7 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,61 @@ +language: php +dist: trusty + +matrix: + include: + - php: "5.4" + - php: "5.5" + - php: "5.6" + addons: + sauce_connect: true + hosts: + - cops-travis + - php: "7.0" + - php: "hhvm" + allow_failures: + - php: "hhvm" + - php: "5.5" + - php: "5.4" + +before_script: + - composer selfupdate + - composer global require "fxp/composer-asset-plugin:~1.1" + - 'if [ "${TRAVIS_PHP_VERSION}" = "5.5" ] || [ "${TRAVIS_PHP_VERSION}" = "5.4" ]; then rm composer.lock && sed -i "/platform/d" composer.json ; fi' + - composer install + - npm install -g jshint + - jshint --version +script: + - vendor/bin/phpunit + - jshint --verbose --show-non-errors util.js + - php test/coverage-checker.php clover.xml 45 +after_success: + - chmod +x test/prepareSauceTest.sh + - test/prepareSauceTest.sh +env: + global: + - SAUCE_USERNAME=seblucas + - secure: VVxocvmz6WYr3tZSTA42M/LUhaHoBWw5onh85hnquoMaxspd3tDCyfQIowTTmEXikRh2T0CkTH7X3dhVwRTd/Ha9isja1qDo9Lc2flGCoWICF7WFZuom084+d+O+EWx4WZMAw4Lz4w6a5xflpPKnzNs9B0+de0BdTlQ5qSXVrcA= + +sudo: false + +before_deploy: + - composer install --no-dev --optimize-autoloader + - wget http://www.phing.info/get/phing-latest.phar + - php phing-latest.phar + - export RELEASE_FILE=$(ls ./cops-*.zip) + +deploy: + provider: releases + api_key: + secure: nUQ6uX4+x3VtyrtKjHANl3zLyc0Q9qe2O10ufOFBgcQwWETrE6Gk+Rwn/Kz6OJkg0AGfioptvjh8c28ELV98M+KmhiwhT1VQgs3pa6x9CbggA8fdbGUCq+SC8lnU7MBYIO5gZ36F3RfPwXxXkd09bajiVLbI024IqFSIAONzLXw= + skip_cleanup: true + file: + - "${RELEASE_FILE}" + on: + tags: true + repo: seblucas/cops + php: 5.6 + +cache: + directories: + - $HOME/.composer/cache diff --git a/CHANGELOG b/CHANGELOG deleted file mode 100644 index 5ba575123..000000000 --- a/CHANGELOG +++ /dev/null @@ -1,118 +0,0 @@ -0.3.2 - 20130303 - * Add dutch translation. Provided by Northguy. - * Fix an ugly bug introduced in 0.3.1. Reported by mariosipad. - * Small fixes/enhancement to the update metadata tools : - * The book's name is Author - Title.epub - * Add the Calibre uuid so that the book is automatically recognised by Calibre. - * Update the cover - * Fix display of the HTML catalog on Kobo's browser. - * Enable kepub.epub download with cover fix (enable with $config['cops_provide_kepub']). - * Hopefully fix browsing with PRS-T1. Thanks to Northguy. - * Hopefully fix the OPDS catalog when the summary is full of HTML crap. - * Merged 3 patches from Tyler J. Wagner : - * Detect empty publication date set in Calibre to avoid having (0101) as publication year. - * Don't print "Languages" if there are none defined. - * Don't print the tag string if there's no tags. - * If an OPDS client try to access index.php it will be automatically redirected to feed.php. - * Move the search & sort tool box to a new line (also fix a w3c error). - - -0.3.1 - 20130127 - * Add Facets to the OPDS catalog (check config item cops_books_filter). - So far the only OPDS client that support facets are Mantano Reader and Bluefire - * Fix book sort in some list. Patch provided by Tyler J. Wagner. - * Update .htaccess to check if Xsendfile is available. Thanks to Gaspine for the patch. - * Add basic support of custom columns. Check the following config item : cops_calibre_custom_column - * Usage of X-Accel-Redirect / X-Sendfile is not necessary anymore. Warning all Nginx users - who wants to still use X-Accel-Redirect must add - $config['cops_x_accel_redirect'] = "X-Accel-Redirect" in their config_local.php - * Fix COPS on IIS / Windows. Reported by Kevnancy. - * Simplified config_default.php - * Add a new config_local.php.example with the minimal configuration item to change. - - -0.3.0 - 20130106 - * Add a config item to avoid using Fancyapps (pop-ups). Reported by mcister and Northguy. - * Update documentation of .htaccess. Thanks to Stephane. - * Add a config item to specify a custom icon. Based on a patch by Tyler J. Wagner. - * Better handling of content type for book. Reported by Morg. - * Upped the size of thumbnails for OPDS. They look way better with Mantano. - * Add language in OPDS feed (shown in Mantano for example). - * Update metadata on downloaded epub. Disabled by default (check config item cops_update_epub-metadata). - * New Catalan translation provided by David Ciscar Presas. - * Add a permalink to books, that way direct link to books can be shared. Reported by mcister and Tyler J. Wagner. - * Add checkconfig.php that should allow to better detect the configuration problem (page in english only for now). - * Fix some plural strings / some missing title. Reported by David Ciscar Presas. - * Add an hint about the OPDS catalog in the HTML catalog. - -0.2.3 - 20121205 - * Add a .htaccess to make it easier to use with Apache - * Fix a typo in book download. Reported by jillmess - * Update localization (thanks to Calibre2Opds) - * Add some missing information from Calibre (language, rating for now). Reported by mcister - * Upgrade Fancybox to 2.1.3 - - -0.2.2 - 20121020 - * Changed JQuery URL to https (thanks to Dan Greve for the patch) - * Added paging to both OPDS and HTML catalog (use new config item cops_max_item_per_page) - * lots of code refactoring - * Authors are now splitted by first letter, this is the new default. You can go back to the old way with the config item cops_author_split_first_letter (reported by Northguy) - * Fix the link to books starting by special characters (reported by vinpel) - * Upgrade to Fancyapps 2.1.0. I had to adapt the CSS so maybe it'll display better in PRS-T1 - * Add an about box on the HTML catalog which show the current version - -0.2.1 - 20120916 - * Fix one last error (hopefully) in link generation (thanks to gaspine) - * Add Sony PRS-T1 to the list of E-Ink device (thanks to Northguy) - * Fix another HTML special characters problem (thanks to NeilBryant) - * Add an ugly config parameter to allow search in non-compliant OPDS reader (thanks to Don Caruana and David Lee) - -0.2.0 - 20120722 - * Fix all rewriting rule I forgot to change it in last release - * Fix
in book comment (thanks to jillmess) - * Fix cover zoom in HTML catalog (you can also navigate through cover with keyboard) - * Simplify Fancybox transition for e-Ink devices (for now Kobo and Kindle) - -0.1.1 - 20120702 - * A lot of bug fixes in HTML catalog - * Fixed the book comment in OPDS (broken in some rare case) - * Fixed handling of HTML reserved characters - * Changed book OPDS id to use an UUID (thanks to ilovejedd for the bug report) - * Add new config item for the default timezone (thanks to gaspine) - * Better handling of missing covers - * Should support every book format supported by Calibre (thanks to Artem) - * URL rewriting is off by default for the HTML catalog - * Add some documentation about URL rewriting (thanks to gaspine and Christophe) - * Tested and ready to use with PHP5.4 - -0.1.0 - 20120605 - * Add localization support (thanks to Calibre2Opds) - * Hopefully fixed an issue with & in comment - * HTML catalog is in the sources with no support (WIP) - -0.0.4 - 20120523 - * More code refactoring to simplify code. - * Changed OPDS Page id to match Calibre2Opds - * Add icons to author, serie, tags and recent items (there is config item to disable it) - * Fixed author URL - * Added publishing date (works on Mantano) - * Added Tags support - -0.0.3 - 20120507 - * Fixed many things blocking opensearch from working - * There was a bug introduced in 0.0.2 - * The URL can't be relative for Mantano reader, so I added a configuration item. - * I continued the refactoring to bring HTML to COPS - * Thumbnails have bigger size (I'll add a configuration item later) - * Add headers to help caching image and thumbnail to the browser - * - -0.0.2 - 20120411 - * Add support for MOBI and PDF - * Major refactoring to prepare something nice for the future ;) - * Add a config item to make use of X-Sendfile instead of X-Accel-Redirect if needed - -0.0.1 - 20120302 - * First public release - \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 000000000..c3c74cef6 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,350 @@ +# Change Log for COPS + +1.3.3 - 20230327 Update npm asset dependencies + * Fix link to typeahead.css for bootstrap2 templates + * Move simonpioli/sortelements dev-master to resources (last updated in 2012) + * Switch from bower-asset/dot 1.1.3 to npm-asset/dot 1.1.3 + * Switch from bower-asset/jquery 1.12.4 to npm-asset/jquery 1.12.4 + * Switch from bower-asset/jquery-cookie 1.4.1 to npm-asset/js-cookie 2.2.1 + * Switch from bower-asset/normalize.css 7.0.0 to npm-asset/normalize.css 8.0.1 + * Switch from rsms/js-lru dev-v2 to npm-asset/lru-fast 0.2.2 + +1.3.2 - 20230325 Improve tests and security + * Merge branch 'master' of https://github.com/peltos/cops - see @peltos + +1.3.1 - 20230325 Update epub-loader resources + * Merge commit 'refs/pull/424/head' of https://github.com/seblucas/cops - see seblucas/cops#424 from @marsender + +1.3.0 - 20230324 Add bootstrap2 templates + * Merge branch 'master' of https://github.com/SenorSmartyPants/cops - see seblucas/cops#497 and earlier from @SenorSmartyPants + +1.2.3 - 20230324 Add fixes for PHP 8.2 + +1.2.2 - 20230324 Update fetch.php to lower memory consumption + * Merge commit 'refs/pull/518/head' of https://github.com/seblucas/cops - see seblucas/cops#518 from @allandanton + +1.2.1 - 20230321 Add phpstan baseline + fixes + +1.2.0 - 20230319 Migration to PHP 8.x + +1.1.3 - 20190624 + * Fixed an error with PHP > 7.2.X where create_function is deprecated, also fixed another error with PHP 7.3.X. Thanks to Turkish for the report. + * Fixed the view button when URL Rewriting is enabled. + * Fixed an error in epubreader with headers. thanks to worstje for the report. + * Added a real logo for COPS. Thanks to horus68 for doing all the work ;). + * Added a proper translation for `_CLEAR_` text. Was reported for many year :(. + * Added Galician translation. Thanks to Sadrarin Highland. + * Added Afrikaan translation. Thanks to PetrusVermaak. + * Updated Spanish, Basque, Italian, Dutch, French, Portuguese, Romanian, Russian, Swedish, Turkish. Thanks to the translators and horus68. + * Upgraded to latest phpmailer 5.2.27 and bootstrap 3.4.1. + +1.1.2 - 20180626 + * Fixed the download of Kepub with recent firmware from Kobo. Thanks to ospring for the report. + * Fixed the cache headers. Thanks to CgX for the fix. + * Added Bulgarian, Indonesian, Chinese (China and Taywan) translation. Check Transifex for the authors. + * Added an open button to use automatically your prefered reader. Thanks to ttan. + * Updated Hungarian, Ukranian, Polish, Spanish and Swedish translations. Check Transifex for the authors. + * Updated a lot of documentation and checkconfig.php to better help users. + * Upgraded to latest jQuery 1.12.X, Normalise 7.0, PHP Mailer 5.2.26, Font Awesome Free 5.0.13. + +1.1.1 - 20170502 + * Fixed the handling of user specific configuration files. Thanks to marioscube, chadberg for the diagnostic / fix and Neil for the PR. + * Changed the cog on the upper right to a magnifying glass icon. Thanks to horus68. + * Added test on travis on PHP 5.4. + * Added a way to specify the secure SMTP port. Thanks to ubupl. + +1.1.0 - 20170402 + * Upgraded to PHPMailer 5.2.21. + * Merged a huge PR that clean most of COPS source code. Thanks to Markus Birth for his work and his patience. + * Updated German, Greek, Italian, Polish, Romanian, Russian, Turkish translations. Check Transifex for the authors. + * Fixed a bad external dependency in login.html causing problem with HTTPS. Thanks to polytan02. + * Fixed minor gui nitpick. + * Added automatic redirection to the OPDS feed for many new Android apps (see #309). Thanks to horus68. + * Added a configuration item to set the mail subject. + +1.0.1 - 20161015 + * Fixed some type of custom column showing id instead of text - Thanks to Mike Schwörer. + * Fixed the redirection to the OPDS catalog for Moon+ Reader. + * Fixed the mail character encoding, now in UTF-8. + * Fixed checkconfig.php to avoid sending content before headers. Thanks to Luke Stevenson. + * Fixed server side rendering with custom columns. + * Moved /icons to /images (Apache issues). Thanks to CgX. + +1.0.0 - 20160708 + * Updated the OPDS icons to better looking ones. Thanks to Horus68. + * Updated the README.md. + * Updated Brazillian, French, Hungarian, Portuguese, Russian translations. + * Added support of language and country code. This allow to have proper Brazil Portuguese and Portugal Portuguese. + * Added Korean translation. Thanks to Jin, Heonkyu. + * Added Romanian translation. Thanks to mtzro2003. + * Added Greek translation. Thanks to George Litos. + * Added Turkish Translation. Thanks to Yunus Emre Deligöz. + * Added Serbian Translation. Thanks to Dalibor Vinkić. + * Added the transliteration of search text. You can enable it with $config ['cops_normalized_search']. Thanks to George Litos. + * Added Ebookdroid, Chunky and AlReader in the know OPDS clients. Thanks to Mike Ferenduros and Horus68. + * Added some mime types for audio books. + * Added the rewrite rule for IIS. + * Added a now parameter to set the style ($config['cops_style']). Thanks to Pablo Santiago Blum de Aguiar. + * Added a directory cache ($config['cops_thumbnail_cache_directory']) to store the resized thumbnails (should help on slow NAS). Thanks to O2 Graphics. + * Added support of all kind of custom columns (see configuration file). Thanks to Mike Schwörer. + * Fixed COPS so that it's completely embedded (no external resources to download needed anymore). + * Fixed a Reflected XSS vulnerability. + * Fixed the tag filters with Bootstrap. Thanks to Klaus Broelemann. + * Fixed some COPS path errors with reverse proxy. Thanks to Benjamin Kitt. + * Fixed the publication date (wasn't working for date before 1901). + * Fixed the download file name (replace + by %20 to be RFC compliant). + + +1.0.0RC3 - 20141229 + * Fixed server side render with Bootstrap template (a proper unit test was also added). + * Upgraded to latest doT-php, Typeahead 0.10.5, jquery-cookie 1.4.1, JQuery 1.11.1 + * Fixed book count with custom columns. + * Updated Catalan, Dutch, French and Russian translations. + * Added AZW3 to the format that can be sent to Kindle (by mail). + * Fixed $config['cops_thumbnail_handling'] with bootstrap template. + * Added Hungarian translation. Thanks to harunibn. + * Added Ukrainian translation. Thanks to Anatoliy Zavalinich + * Added full PHP password check (without any need from specific webserver configuration). Thanks to Mark Bond. + * Added new IOS7 style with default template. Thanks to an anonymous source ;). + * Fixed display of authors names for books with more than one author. + * Added PHP version to checkconfig.php (will help debugging for me). + * Added a configuration item ($config['cops_template']) to change the default template. Thanks to Shin. + * Added a configuration item ($config['cops_language']) to force COPS language. Thanks to Sandy Pleyte. + * Added a trick to have user based configuration, check https://github.com/seblucas/cops/wiki/User-based-config for more information. Thanks to Sandy Pleyte. + * Changed the default sort order on books by author page to show books in a series before all other books. + + +1.0.0RC2 - 20140731 + * Updated Italian, Spanish, Portuguese, Norwegian translations. + * Added Polish translation. Thanks to macak_pl. + * Added Haitian Creole translation. Thanks to Ian Macdonald & Jacinta. + * Added Basque translation. Thanks to Turutarena. + * Upgraded to JQuery 1.11.0, Magnific Popup 0.9.9, Normalize 3.0.1, Typeahead 0.10.2 + * Fixed search with accentuated characters on Internet Explorer. + * Author can now be searched by sort or by name (Carroll, Lewis or Lewis Carroll will work). + * Added a new bootstrap user interface. + * Added correct mimetype for *.ibooks. Reported by Flowney. + * Added an empty line at the end of .htaccess to make it easier to modify. Reported by Mariosipad. + * Modified the README and checkconfig.php to check for php5-json. Reported by Mariosipad. + * Handled properly the cancelling of a mail. Reported by coach0742. + * Added an ugly hack to try to fix bad rendering with Kindle. Please report if it's better or not. + +1.0.0RC1 - 20140404 + * Updated English, Spanish, German, Italian, Portuguese, Dutch translation files. Huge thanks to all to the translators. + * Added Swedish translation. Thanks to Bo Rosén. + * Added Czech translation. Thanks to Zdenek Hadrava. + * Added a lot of refactoring to simplify the code. + * Added a lot of new unit tests. + * Fixed a caching bug causing problems with IE. + * Added an embedded Epub Reader based on Monocle. Thanks to all the beta testers. + * Cleaned up a lot of stuff to prepare for bootstrap template. Note to all CSS hackers, the stylesheets are now in templates/default/styles. + * Fixed the charset of most of the pages. Thanks to edent. + * Added a new category : ratings. Thanks to Michael. + * Fixed the URL rewriting in the OPDS stream, should fix file naming with FBReader. Reported by Rassie. + * Fixed a confusion between author's name and author's sort. Reported by At_Libitum. + * Fixed the style of the tag filters to show that they're clickable. Thanks to cycojesus. + * Replaced | by space in author name. + +0.9.0 - 20131231 + * Add a lot of unit testing. I hope it will limit the risks of regression. + * Added a "smart / autocomplete" search. + * Updated the way locales are handled. Should be easier to add new languages. + * Fixed display of Cyrillic characters. + * Upgraded doT to version 1.0.1, Magnific-Popup to 0.9.8, Normalize.css to 2.1.3, Jquery-cookie to 1.4.0. + * Fixed OPDS stream validity. Reported by Didier. + * Added a new check in checkconfig.php to detect case problem between the actual path and the path stored in Calibre database. Try checkconfig.php?full=1. Reported by Ruud. + * Fixed the display of the rating stars with Chrome. Thanks to At_Libitum. + * Added a new parameter ($config['cops_titles_split_first_letter']) to avoid splitting the books by first letter. Thanks to At_Libitum. + * Fixed non compliant OPDS search (for Stanza, Moon+ Reader, ...). Reported by At_Libitum. + * Fixed the redirection in case the Calibre database is not found. Reported by At_Libitum + * Changed .htaccess to allow the use of password protected catalogs with Sony's eReader (PRS-TX). Thanks to Ruud for the beta testing. + * Updated Chinese, German, Norwegian, Portuguese, Russian translations. Huge thanks to all the translators. + * Fixed a small problem : If a book had no summary the cover could be cut. + * Fix COPS on Internet Explorer 9. Reported by At_Libitum. + * Added publishers in home categories / search / autocomplete search. + * Added a new configuration item ($config ['cops_ignored_categories']) to ignore some categories (author, tag, publisher, ...) in home screen and searches. It's also available in the "Customize UI" page. + * Updated .htaccess to allow downloading books with a password protected COPS on a Sony PRS-TX. Reported by Ruud. + * Changed the default search to search by categories also (should help with OPDS). Thanks to At_Libitum. + * Fixed the tag filtering in the HTML catalog when two tags starts by the same word. Reported by Tyler. + +0.6.2 - 20130913 + * Added server side rendering for devices like PRS-TX / Kindle / Cybook. Thanks to all the testers. + * Added a configuration item to tweak how thumbnail are handled. + * Fixed the click on cog on IOS. Thanks to sb domo. + * Added dashboard icons / standalone mode for IOS. Thanks to sb domo. + * Fixed a regression about custom favicon.ico. Thanks to Tyler. + * Fixed another regression about COPS's version in the about box. Reported by Ian. + * Upgraded Magnific Popup to v0.9.5. + * Added a style for IPhone. Thanks to sb domo. + * Added Portuguese translation. Thanks to Pablo Aguiar. + * Fixed rendering on Internet Explorer < 9.0. + +0.6.1 - 20130730 + * Properly close the lightbox when clicking in a link. Reported by le_. + * Fix the book by languages list when the language is not found in the resources. Reported by le_. + * Fix the string for Portuguese. Reported by le_. + * Add again the series Index in the book list. Reported by fatzgenfatz. + +0.6.0 - 20130724 + * COPS HTML catalog now use templated client side rendering. You can build your own template if you want. Should be a lot faster. + * Fancybox has been replaced by Magnific Popup, it seems faster. + * Added a way to send book by mail (to send to Kindle or to send to your friends). + * Added expires instruction in .htaccess (won't crash if you haven't enabled mod_expires). + * Upgrade to JQuery 1.10.2. + * Changed the way thumbnails are handled to offer greater visual quality (especially on high pixel density devices : Retina, Nexus, ...). + * Changed all icon by a vectorial font (again better visual quality). + * Added a way to filter books by tags. + * Added a login page (login.html) to allow access to a password protected COPS on a Kobo ereader (that does not support basic auth). + * Fixed cookie expiry date. + * Added a default web.config for IIS installation. + * The eink style doesn't use shadow anymore. + * Fixed the link to the series in book detail. + +0.5.0 - 20130605 + * Upgrade COPS UI to HTML5 / CSS3 to hopefully make it prettier. Most of the code was contributed by Thomas Severinsen. + * Add the number of books in each databases (when multiple database is enabled). + * Add Norwegian Bokmål strings. Thanks to Rune Mathisen for the pull request. + * Add a split by language of catalog. Thanks to Puiu Ionut for the pull request. + * You can now change the theme and fancybox use on all your devices (You have to enable cookies). + * Add an eink theme. Thanks to Gregory Bodin for the code. + +0.4.0 - 20130507 + * Add multiple database support. Check the documentation of $config['calibre_directory'] in config-default.php to see how to enable it. + * Include jquery library in COPS's repository to be sure that COPS will work on LAN (without Internet access). + * Prepare the switch to HTML5. Thanks to Thomas Severinsen for most of the code. + * Update the locale strings to be more strict with plurals. Thanks to Tobias Ausländer for the code. + * If Fancybox is not enabled ($config['cops_use_fancyapps'] = "0") then it's not used at all (even in the about box). + * Fix book comments if it contains UTF8 characters. Reported by Alain. + * Link to the book permalink was not working correctly in some cases. Reported by celta. + * Moved some external resources to a resources directory. + * Add chinese translation. Thanks to wogong for the pull request. + +0.3.4 - 20130327 + * Hopefully fix metadata update. Beware you should remove the directory php-epub-meta if you have one. Thanks to Mario for his time. + * Fix two warnings. Reported by Goner and Mario. + +0.3.3 - 20130323 + * Fix catalog if book summary contains bad HTML again :(. + * Upgrade to Fancybox 2.4.0 and JQuery 1.9.1. + * Search is now dependant on the page you're in. For now if you're on author page it'll look for author name. + * Update checkconfig to check if the database provided comes from Calibre. + * Update to latest php-epub-meta should fix the metadata update with Epub. + * Fix OPDS catalog with Ibis Reader. It didn't like empty language. + +0.3.2 - 20130303 + * Add dutch translation. Provided by Northguy. + * Fix an ugly bug introduced in 0.3.1. Reported by mariosipad. + * Small fixes/enhancement to the update metadata tools : + * The book's name is Author - Title.epub + * Add the Calibre uuid so that the book is automatically recognised by Calibre. + * Update the cover + * Fix display of the HTML catalog on Kobo's browser. + * Enable kepub.epub download with cover fix (enable with $config['cops_provide_kepub']). + * Hopefully fix browsing with PRS-T1. Thanks to Northguy. + * Hopefully fix the OPDS catalog when the summary is full of HTML crap. + * Merged 3 patches from Tyler J. Wagner : + * Detect empty publication date set in Calibre to avoid having (0101) as publication year. + * Don't print "Languages" if there are none defined. + * Don't print the tag string if there's no tags. + * If an OPDS client try to access index.php it will be automatically redirected to feed.php. + * Move the search & sort tool box to a new line (also fix a w3c error). + + +0.3.1 - 20130127 + * Add Facets to the OPDS catalog (check config item cops_books_filter). + So far the only OPDS client that support facets are Mantano Reader and Bluefire + * Fix book sort in some list. Patch provided by Tyler J. Wagner. + * Update .htaccess to check if Xsendfile is available. Thanks to Gaspine for the patch. + * Add basic support of custom columns. Check the following config item : cops_calibre_custom_column + * Usage of X-Accel-Redirect / X-Sendfile is not necessary anymore. Warning all Nginx users + who wants to still use X-Accel-Redirect must add + $config['cops_x_accel_redirect'] = "X-Accel-Redirect" in their config_local.php + * Fix COPS on IIS / Windows. Reported by Kevnancy. + * Simplified config_default.php + * Add a new config_local.php.example with the minimal configuration item to change. + + +0.3.0 - 20130106 + * Add a config item to avoid using Fancyapps (pop-ups). Reported by mcister and Northguy. + * Update documentation of .htaccess. Thanks to Stephane. + * Add a config item to specify a custom icon. Based on a patch by Tyler J. Wagner. + * Better handling of content type for book. Reported by Morg. + * Upped the size of thumbnails for OPDS. They look way better with Mantano. + * Add language in OPDS feed (shown in Mantano for example). + * Update metadata on downloaded epub. Disabled by default (check config item cops_update_epub-metadata). + * New Catalan translation provided by David Ciscar Presas. + * Add a permalink to books, that way direct link to books can be shared. Reported by mcister and Tyler J. Wagner. + * Add checkconfig.php that should allow to better detect the configuration problem (page in english only for now). + * Fix some plural strings / some missing title. Reported by David Ciscar Presas. + * Add an hint about the OPDS catalog in the HTML catalog. + +0.2.3 - 20121205 + * Add a .htaccess to make it easier to use with Apache + * Fix a typo in book download. Reported by jillmess + * Update localization (thanks to Calibre2Opds) + * Add some missing information from Calibre (language, rating for now). Reported by mcister + * Upgrade Fancybox to 2.1.3 + + +0.2.2 - 20121020 + * Changed JQuery URL to https (thanks to Dan Greve for the patch) + * Added paging to both OPDS and HTML catalog (use new config item cops_max_item_per_page) + * lots of code refactoring + * Authors are now splitted by first letter, this is the new default. You can go back to the old way with the config item cops_author_split_first_letter (reported by Northguy) + * Fix the link to books starting by special characters (reported by vinpel) + * Upgrade to Fancyapps 2.1.0. I had to adapt the CSS so maybe it'll display better in PRS-T1 + * Add an about box on the HTML catalog which show the current version + +0.2.1 - 20120916 + * Fix one last error (hopefully) in link generation (thanks to gaspine) + * Add Sony PRS-T1 to the list of E-Ink device (thanks to Northguy) + * Fix another HTML special characters problem (thanks to NeilBryant) + * Add an ugly config parameter to allow search in non-compliant OPDS reader (thanks to Don Caruana and David Lee) + +0.2.0 - 20120722 + * Fix all rewriting rule I forgot to change it in last release + * Fix
in book comment (thanks to jillmess) + * Fix cover zoom in HTML catalog (you can also navigate through cover with keyboard) + * Simplify Fancybox transition for e-Ink devices (for now Kobo and Kindle) + +0.1.1 - 20120702 + * A lot of bug fixes in HTML catalog + * Fixed the book comment in OPDS (broken in some rare case) + * Fixed handling of HTML reserved characters + * Changed book OPDS id to use an UUID (thanks to ilovejedd for the bug report) + * Add new config item for the default timezone (thanks to gaspine) + * Better handling of missing covers + * Should support every book format supported by Calibre (thanks to Artem) + * URL rewriting is off by default for the HTML catalog + * Add some documentation about URL rewriting (thanks to gaspine and Christophe) + * Tested and ready to use with PHP5.4 + +0.1.0 - 20120605 + * Add localization support (thanks to Calibre2Opds) + * Hopefully fixed an issue with & in comment + * HTML catalog is in the sources with no support (WIP) + +0.0.4 - 20120523 + * More code refactoring to simplify code. + * Changed OPDS Page id to match Calibre2Opds + * Add icons to author, serie, tags and recent items (there is config item to disable it) + * Fixed author URL + * Added publishing date (works on Mantano) + * Added Tags support + +0.0.3 - 20120507 + * Fixed many things blocking opensearch from working + * There was a bug introduced in 0.0.2 + * The URL can't be relative for Mantano reader, so I added a configuration item. + * I continued the refactoring to bring HTML to COPS + * Thumbnails have bigger size (I'll add a configuration item later) + * Add headers to help caching image and thumbnail to the browser + * + +0.0.2 - 20120411 + * Add support for MOBI and PDF + * Major refactoring to prepare something nice for the future ;) + * Add a config item to make use of X-Sendfile instead of X-Accel-Redirect if needed + +0.0.1 - 20120302 + * First public release diff --git a/OPDS_renderer.php b/OPDS_renderer.php deleted file mode 100644 index a8da8a3b5..000000000 --- a/OPDS_renderer.php +++ /dev/null @@ -1,260 +0,0 @@ - - */ - -require_once ("base.php"); - -class OPDSRenderer -{ - const PAGE_OPENSEARCH = "8"; - const PAGE_OPENSEARCH_QUERY = "9"; - - private $xmlStream = NULL; - private $updated = NULL; - - private function getUpdatedTime () { - if (is_null ($this->updated)) { - $this->updated = time(); - } - return date (DATE_ATOM, $this->updated); - } - - private function getXmlStream () { - if (is_null ($this->xmlStream)) { - $this->xmlStream = new XMLWriter(); - $this->xmlStream->openMemory(); - $this->xmlStream->setIndent (true); - } - return $this->xmlStream; - } - - public function getOpenSearch () { - global $config; - $xml = new XMLWriter (); - $xml->openMemory (); - $xml->setIndent (true); - $xml->startDocument('1.0','UTF-8'); - $xml->startElement ("OpenSearchDescription"); - $xml->writeAttribute ("xmlns", "http://a9.com/-/spec/opensearch/1.1/"); - $xml->startElement ("ShortName"); - $xml->text ("My catalog"); - $xml->endElement (); - $xml->startElement ("Description"); - $xml->text ("Search for ebooks"); - $xml->endElement (); - $xml->startElement ("InputEncoding"); - $xml->text ("UTF-8"); - $xml->endElement (); - $xml->startElement ("OutputEncoding"); - $xml->text ("UTF-8"); - $xml->endElement (); - $xml->startElement ("Image"); - $xml->writeAttribute ("type", "image/x-icon"); - $xml->writeAttribute ("width", "16"); - $xml->writeAttribute ("height", "16"); - $xml->text ($config['cops_icon']); - $xml->endElement (); - $xml->startElement ("Url"); - $xml->writeAttribute ("type", 'application/atom+xml'); - $xml->writeAttribute ("template", $config['cops_full_url'] . 'feed.php?query={searchTerms}'); - $xml->endElement (); - $xml->startElement ("Query"); - $xml->writeAttribute ("role", "example"); - $xml->writeAttribute ("searchTerms", "robot"); - $xml->endElement (); - $xml->endElement (); - $xml->endDocument(); - return $xml->outputMemory(true); - } - - private function startXmlDocument ($page) { - global $config; - self::getXmlStream ()->startDocument('1.0','UTF-8'); - self::getXmlStream ()->startElement ("feed"); - self::getXmlStream ()->writeAttribute ("xmlns", "http://www.w3.org/2005/Atom"); - self::getXmlStream ()->writeAttribute ("xmlns:xhtml", "http://www.w3.org/1999/xhtml"); - self::getXmlStream ()->writeAttribute ("xmlns:opds", "http://opds-spec.org/2010/catalog"); - self::getXmlStream ()->writeAttribute ("xmlns:opensearch", "http://a9.com/-/spec/opensearch/1.1/"); - self::getXmlStream ()->writeAttribute ("xmlns:dcterms", "http://purl.org/dc/terms/"); - self::getXmlStream ()->startElement ("title"); - self::getXmlStream ()->text ($page->title); - self::getXmlStream ()->endElement (); - if ($page->subtitle != "") - { - self::getXmlStream ()->startElement ("subtitle"); - self::getXmlStream ()->text ($page->subtitle); - self::getXmlStream ()->endElement (); - } - self::getXmlStream ()->startElement ("id"); - if ($page->idPage) - { - self::getXmlStream ()->text ($page->idPage); - } - else - { - self::getXmlStream ()->text ($_SERVER['REQUEST_URI']); - } - self::getXmlStream ()->endElement (); - self::getXmlStream ()->startElement ("updated"); - self::getXmlStream ()->text (self::getUpdatedTime ()); - self::getXmlStream ()->endElement (); - self::getXmlStream ()->startElement ("icon"); - self::getXmlStream ()->text ($page->favicon); - self::getXmlStream ()->endElement (); - self::getXmlStream ()->startElement ("author"); - self::getXmlStream ()->startElement ("name"); - self::getXmlStream ()->text (utf8_encode ("Sbastien Lucas")); - self::getXmlStream ()->endElement (); - self::getXmlStream ()->startElement ("uri"); - self::getXmlStream ()->text ("http://blog.slucas.fr"); - self::getXmlStream ()->endElement (); - self::getXmlStream ()->startElement ("email"); - self::getXmlStream ()->text ("sebastien@slucas.fr"); - self::getXmlStream ()->endElement (); - self::getXmlStream ()->endElement (); - $link = new LinkNavigation ("", "start", "Home"); - self::renderLink ($link); - $link = new LinkNavigation ("?" . $_SERVER['QUERY_STRING'], "self"); - self::renderLink ($link); - if ($config['cops_generate_invalid_opds_stream'] == 0 || preg_match("/(MantanoReader|FBReader)/", $_SERVER['HTTP_USER_AGENT'])) { - // Good and compliant way of handling search - $link = new Link ("feed.php?page=" . self::PAGE_OPENSEARCH, "application/opensearchdescription+xml", "search", "Search here"); - } - else - { - // Bad way, will be removed when OPDS client are fixed - $link = new Link ($config['cops_full_url'] . 'feed.php?query={searchTerms}', "application/atom+xml", "search", "Search here"); - } - self::renderLink ($link); - if ($page->containsBook () && !is_null ($config['cops_books_filter']) && count ($config['cops_books_filter']) > 0) { - $Urlfilter = getURLParam ("tag", ""); - foreach ($config['cops_books_filter'] as $lib => $filter) { - $link = new LinkFacet ("?" . addURLParameter ($_SERVER['QUERY_STRING'], "tag", $filter), $lib, localize ("tagword.title"), $filter == $Urlfilter); - self::renderLink ($link); - } - } - } - - private function endXmlDocument () { - self::getXmlStream ()->endElement (); - self::getXmlStream ()->endDocument (); - return self::getXmlStream ()->outputMemory(true); - } - - private function renderLink ($link) { - self::getXmlStream ()->startElement ("link"); - self::getXmlStream ()->writeAttribute ("href", $link->href); - self::getXmlStream ()->writeAttribute ("type", $link->type); - if (!is_null ($link->rel)) { - self::getXmlStream ()->writeAttribute ("rel", $link->rel); - } - if (!is_null ($link->title)) { - self::getXmlStream ()->writeAttribute ("title", $link->title); - } - if (!is_null ($link->facetGroup)) { - self::getXmlStream ()->writeAttribute ("opds:facetGroup", $link->facetGroup); - } - if ($link->activeFacet) { - self::getXmlStream ()->writeAttribute ("opds:activeFacet", "true"); - } - self::getXmlStream ()->endElement (); - } - - - private function renderEntry ($entry) { - self::getXmlStream ()->startElement ("title"); - self::getXmlStream ()->text ($entry->title); - self::getXmlStream ()->endElement (); - self::getXmlStream ()->startElement ("updated"); - self::getXmlStream ()->text (self::getUpdatedTime ()); - self::getXmlStream ()->endElement (); - self::getXmlStream ()->startElement ("id"); - self::getXmlStream ()->text ($entry->id); - self::getXmlStream ()->endElement (); - self::getXmlStream ()->startElement ("content"); - self::getXmlStream ()->writeAttribute ("type", $entry->contentType); - if ($entry->contentType == "text") { - self::getXmlStream ()->text ($entry->content); - } else { - self::getXmlStream ()->writeRaw ($entry->content); - } - self::getXmlStream ()->endElement (); - foreach ($entry->linkArray as $link) { - self::renderLink ($link); - } - - if (get_class ($entry) != "EntryBook") { - return; - } - - foreach ($entry->book->getAuthors () as $author) { - self::getXmlStream ()->startElement ("author"); - self::getXmlStream ()->startElement ("name"); - self::getXmlStream ()->text ($author->name); - self::getXmlStream ()->endElement (); - self::getXmlStream ()->startElement ("uri"); - self::getXmlStream ()->text ("feed.php" . $author->getUri ()); - self::getXmlStream ()->endElement (); - self::getXmlStream ()->endElement (); - } - foreach ($entry->book->getTags () as $category) { - self::getXmlStream ()->startElement ("category"); - self::getXmlStream ()->writeAttribute ("term", $category->name); - self::getXmlStream ()->writeAttribute ("label", $category->name); - self::getXmlStream ()->endElement (); - } - if ($entry->book->getPubDate () != "") { - self::getXmlStream ()->startElement ("dcterms:issued"); - self::getXmlStream ()->text (date ("Y-m-d", $entry->book->pubdate)); - self::getXmlStream ()->endElement (); - self::getXmlStream ()->startElement ("published"); - self::getXmlStream ()->text (date ("Y-m-d", $entry->book->pubdate) . "T08:08:08Z"); - self::getXmlStream ()->endElement (); - } - - $lang = $entry->book->getLanguages (); - if (!is_null ($lang)) { - self::getXmlStream ()->startElement ("dcterms:language"); - self::getXmlStream ()->text ($lang); - self::getXmlStream ()->endElement (); - } - - } - - public function render ($page) { - global $config; - self::startXmlDocument ($page); - if ($page->isPaginated ()) - { - self::getXmlStream ()->startElement ("opensearch:totalResults"); - self::getXmlStream ()->text ($page->totalNumber); - self::getXmlStream ()->endElement (); - self::getXmlStream ()->startElement ("opensearch:itemsPerPage"); - self::getXmlStream ()->text ($config['cops_max_item_per_page']); - self::getXmlStream ()->endElement (); - self::getXmlStream ()->startElement ("opensearch:startIndex"); - self::getXmlStream ()->text (($page->n - 1) * $config['cops_max_item_per_page'] + 1); - self::getXmlStream ()->endElement (); - $prevLink = $page->getPrevLink (); - $nextLink = $page->getNextLink (); - if (!is_null ($prevLink)) { - self::renderLink ($prevLink); - } - if (!is_null ($nextLink)) { - self::renderLink ($nextLink); - } - } - foreach ($page->entryArray as $entry) { - self::getXmlStream ()->startElement ("entry"); - self::renderEntry ($entry); - self::getXmlStream ()->endElement (); - } - return self::endXmlDocument (); - } -} - -?> diff --git a/README b/README deleted file mode 100644 index ef898c755..000000000 --- a/README +++ /dev/null @@ -1,86 +0,0 @@ -= COPS = - -COPS stands for Calibre OPDS (and HTML) Php Server. - -COPS output is valid the unofficial OPDS validator : -http://opds-validator.appspot.com/ - -= Why ? = - -In my opinion Calibre is a marvelous tool but is too big and has too much -dependencies to be used for its content server. - -That's the main reason why I coded this OPDS server. I needed a simple -tool to be installed on a small server (Seagate Dockstar in my case). - -I initially thought of Calibre2OPDS but as it generate static file no -search was possible. - -Later I added an simple HTML catalog that should be usable on my Kobo. - -So COPS's main advantages are : - * No need for many dependencies. - * No need for a lot of CPU or RAM. - * Not much code. - * Search is available. - * With Dropbox / owncloud it's very easy to have an up to date OPDS server. - * It was fun to code. - -If you want to use the OPDS feed don't forget to specify feed.php at the end of your URL. - -= Prerequisites = - -1. PHP 5.3 or 5.4 with GD image processing & SQLite3 support. -2. A web server with PHP support. I only tested with various version of Nginx. - Other people reported it working with Apache and Cherokee. -3. The path to a calibre library (metadata.db, format, & cover files). - -On any Debian base Linux you can use : - aptitude install php5-gd php5-sqlite - -= Install = - -1. Extract the zip file to a folder in web space (visible to the web server). -2. If a first-time install, copy config_local.php.example to config_local.php -3. Edit config_local.php to match your config. -4. If needed add other configuration item from config_default.php - -If you choose to put your Calibre directory inside your web directory then you -will have to edit /etc/nginx/mime.types to add this line : -application/epub+zip epub; - -= Known problems = - -Not a lot ;) - -Please see https://github.com/seblucas/cops/issues for open issues - -= Need help = - -Please read https://github.com/seblucas/cops/wiki - -= Disclaimer = - -It's tested by me and many other users but there's still some little bugs around ;) - -= Credits = - - * All localization informations come from Calibre2OPDS (http://calibre2opds.com/) - * Locale message handling is inspired of http://www.mind-it.info/2010/02/22/a-simple-approach-to-localization-in-php/ - * str_format function come from http://tmont.com/blargh/2010/1/string-format-in-php - * All icons come from the package Web0 by naf1971 : http://naf1971.deviantart.com/art/Web0-182067054 - * Thanks to all testers - -External libraries used : - * JQuery : http://jquery.com/ - * Fancyapps : http://fancyapps.com/fancybox/ - * Php-epub-meta : https://github.com/splitbrain/php-epub-meta with some modification by me - https://github.com/seblucas/php-epub-meta - * TbsZip : http://www.tinybutstrong.com/apps/tbszip/tbszip_help.html - -= Copyright & License = - -COPS - 2012-2013 (c) Sbastien Lucas - -See COPYING and file headers for license info - diff --git a/README.md b/README.md index 8f30b32ec..0afb197e9 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,142 @@ -cops -==== +# COPS -Calibre OPDS (and HTML) PHP Server : light alternative to Calibre content server / Calibre2OPDS +COPS stands for Calibre OPDS (and HTML) Php Server. + +See : [COPS's home](http://blog.slucas.fr/en/oss/calibre-opds-php-server) for more details. + +Don't forget to check the [Wiki](https://github.com/seblucas/cops/wiki). + +[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/seblucas/cops/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/seblucas/cops/?branch=master) + +[![Code Coverage](https://scrutinizer-ci.com/g/seblucas/cops/badges/coverage.png?b=master)](https://scrutinizer-ci.com/g/seblucas/cops/?branch=master) + +[![Build Status / Scrutinizer](https://scrutinizer-ci.com/g/seblucas/cops/badges/build.png?b=master)](https://scrutinizer-ci.com/g/seblucas/cops/build-status/master) + +[![Build Status](https://travis-ci.org/seblucas/cops.svg?branch=master)](https://travis-ci.org/seblucas/cops) + +[![Selenium Test Status](https://saucelabs.com/browser-matrix/seblucas.svg)](https://saucelabs.com/u/seblucas) + +# Why ? + +In my opinion Calibre is a marvelous tool but is too big and has too much +dependencies to be used for its content server. + +That's the main reason why I coded this OPDS server. I needed a simple +tool to be installed on a small server (Seagate Dockstar in my case). + +I initially thought of Calibre2OPDS but as it generate static file no +search was possible. + +Later I added an simple HTML catalog that should be usable on my Kobo. + +So COPS's main advantages are : + * No need for many dependencies. + * No need for a lot of CPU or RAM. + * Not much code. + * Search is available. + * It was fun to code. + +If you want to use the OPDS feed don't forget to specify feed.php at the end of your URL. + +You just have to sync your Calibre directory to your COPS server the way you prefer (Dropbox, Bt Sync, Syncthing, use a directory shared with Nextcloud, ...). + +# Prerequisites (this fork) +1. PHP 7.4 or 8.X with GD image processing, Libxml, Intl, Json & SQLite3 support (PHP 8.1 or later recommended). + +See [CHANGELOG](CHANGELOG.md) for changes compared to upstream repository https://github.com/seblucas/cops from @seblucas + +# Prerequisites + +1. PHP 5.3, 5.4, 5.5, 5.6, 7.X or hhvm with GD image processing, Libxml, Intl, Json & SQLite3 support (PHP 5.6 or later recommended). +2. A web server with PHP support. I tested with various version of Nginx and Apache. + Other people reported it working with Apache and Cherokee. You can also use PHP embedded server (https://github.com/seblucas/cops/wiki/Howto---PhpEmbeddedServer) +3. The path to a calibre library (metadata.db, format, & cover files). + +On any Debian based Linux you can use : + `apt-get install php5-gd php5-sqlite php5-json php5-intl` + +If you use Debian Stretch : + `apt-get install php7.0-gd php7.0-sqlite3 php7.0-json php7.0-intl php7.0-xml php7.0-mbstring php7.0-zip` + +On Centos you may have to add : + yum install php-xml + +# Install a release (Easiest way) + +1. Extract the zip file you got from [the release page](https://github.com/seblucas/cops/releases) to a folder in web space (visible to the web server). +2. If you're doing a first-time install, copy config_local.php.example to config_local.php +3. Edit config_local.php to match your config. +4. If needed add other configuration item from config_default.php + +If you like Docker, you can also try this multiarch docker container from [linuxserver.io](https://hub.docker.com/r/linuxserver/cops/) It has builds for x64, armhf and arm64. + +# Install from sources + +```bash +git clone https://github.com/seblucas/cops.git # or download lastest zip see below +cd cops +wget https://getcomposer.org/composer.phar +php composer.phar global require "fxp/composer-asset-plugin:~1.1" +php composer.phar install --no-dev --optimize-autoloader +``` + +After that you can use the previous how-to starting at the second step. + +Note that instead of cloning you can also get [latest master as zip](https://github.com/seblucas/cops/archive/master.zip) + +Note that if your PHP version is lower that 5.6, then you may have to remove `composer.lock` before starting the last line. + +# Where to put my Calibre directory ? + +Long story short : ALWAYS outside of COPS's directory especially if COPS is installed on a VPS / Server. If you follow my advice then your data will be safe. + +If you choose to put your Calibre directory inside your web directory and use Nginx then you will have to edit /etc/nginx/mime.types to add these lines : + +``` +application/epub+zip epub; +application/x-mobipocket-ebook mobi prc azw; +``` + +# Known problems + +Not a lot, except for the bad quality of the code (first PHP project ever) ;) + +Please see https://github.com/seblucas/cops/issues for open issues + +# Need help + +Please read https://github.com/seblucas/cops/wiki and check the FAQ. + +# Contributing + +As you could see [here](https://github.com/seblucas/cops/graphs/contributors), I appreciate every contributions and there were a lot over time. So don't be shy and submit your Pull Requests. + +Note to translators : please prefer using [Transifex](https://github.com/seblucas/cops/wiki/Update-translations) instead of doing a PR. + +I only have one limit (I may have more but that one is the worse) : COPS' goal is to provide an alternative to Calibre's content server and not to replace Calibre entirely. So I will refuse any PR making changes to the database content. + +# Credits + + * Locale message handling is inspired of https://www.mind-it.info/2010/02/22/a-simple-approach-to-localization-in-php + * str_format function come from http://tmont.com/blargh/2010/1/string-format-in-php + * All icons come from Font Awesome : https://github.com/FortAwesome/Font-Awesome + * The unofficial OPDS validator : http://opds-validator.appspot.com/ + * Thanks to all testers, translators and contributors. + * Feed icons made by Freepik from Flaticon website licensed under Creative Commons BY 3.0 http://www.flaticon.com and http://www.freepik.com + * A huge thanks to Jetbrains for supporting COPS by providing a set of free licenses to their products for several years now! + +External libraries used : + * JQuery : http://jquery.com/ + * Magnific Popup : http://dimsemenov.com/plugins/magnific-popup/ + * Php-epub-meta : https://github.com/splitbrain/php-epub-meta with some modification by me (https://github.com/seblucas/php-epub-meta) + * TbsZip : http://www.tinybutstrong.com/apps/tbszip/tbszip_help.html + * DoT.js : http://olado.github.io/doT/index.html + * PHPMailer : https://github.com/PHPMailer/PHPMailer + * js-lru : https://github.com/rsms/js-lru + +# Copyright & License + +COPS - 2012-2019 (c) Sébastien Lucas + +See COPYING and file headers for license info -See : http://blog.slucas.fr/en/oss/calibre-opds-php-server diff --git a/about.html b/about.html index 2379a8702..19029c553 100644 --- a/about.html +++ b/about.html @@ -1,13 +1,26 @@ -

Authors

-

COPS is developped and maintained by Sébastien Lucas.

+
+

About COPS

+

Authors

+

COPS is developed and maintained by Sébastien Lucas.

-

See full history on Github to check all authors.
-COPS use some external librairies, check README for the details.

+

See full history on Github to check all authors.

+

COPS use some external libraries, check README for the details.

Copyright

-

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation.
-The complete content of license is provided in file COPYING within distribution and also available online.

+

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation.

+

The complete content of license is provided in file COPYING within distribution and also available online.

Contact

For more info please visit COPS Home Page

-

You can also check COPS's topic on MobileRead forum.

\ No newline at end of file + +

You can also check COPS's topic on MobileRead forum.

+ +

DISCLAIMER : COPS is an open source software free to install everywhere. So if you have questions about any books available with any installation of COPS, please ask the owner of the website and not COPS's maintainer.

+

Thanks

+

Thanks a lot to Kovid Goyal for Calibre.

+ +

And many thanks to all those who helped test COPS.

+ +

This Fork

+

See CHANGELOG on Github for details: https://github.com/mikespub-org/seblucas-cops

+
diff --git a/author.php b/author.php deleted file mode 100644 index d41bb846d..000000000 --- a/author.php +++ /dev/null @@ -1,102 +0,0 @@ - - */ - -require_once('base.php'); - -class Author extends Base { - const ALL_AUTHORS_ID = "calibre:authors"; - - const AUTHOR_COLUMNS = "authors.id as id, authors.name as name, authors.sort as sort, count(*) as count"; - const SQL_AUTHORS_BY_FIRST_LETTER = "select {0} from authors, books_authors_link where author = authors.id and upper (authors.sort) like ? group by authors.id, authors.name, authors.sort order by sort"; - const SQL_ALL_AUTHORS = "select {0} from authors, books_authors_link where author = authors.id group by authors.id, authors.name, authors.sort order by sort"; - - public $id; - public $name; - public $sort; - - public function __construct($pid, $pname) { - $this->id = $pid; - $this->name = $pname; - } - - public function getUri () { - return "?page=".parent::PAGE_AUTHOR_DETAIL."&id=$this->id"; - } - - public function getEntryId () { - return self::ALL_AUTHORS_ID.":".$this->id; - } - - public static function getEntryIdByLetter ($startingLetter) { - return self::ALL_AUTHORS_ID.":letter:".$startingLetter; - } - - public static function getCount() { - $nAuthors = parent::getDb ()->query('select count(*) from authors')->fetchColumn(); - $entry = new Entry (localize("authors.title"), self::ALL_AUTHORS_ID, - str_format (localize("authors.alphabetical"), $nAuthors), "text", - array ( new LinkNavigation ("?page=".parent::PAGE_ALL_AUTHORS))); - return $entry; - } - - public static function getAllAuthorsByFirstLetter() { - $result = parent::getDb ()->query('select substr (upper (sort), 1, 1) as title, count(*) as count -from authors -group by substr (upper (sort), 1, 1) -order by substr (upper (sort), 1, 1)'); - $entryArray = array(); - while ($post = $result->fetchObject ()) - { - array_push ($entryArray, new Entry ($post->title, Author::getEntryIdByLetter ($post->title), - str_format (localize("authorword", $post->count), $post->count), "text", - array ( new LinkNavigation ("?page=".parent::PAGE_AUTHORS_FIRST_LETTER."&id=". rawurlencode ($post->title))))); - } - return $entryArray; - } - - public static function getAuthorsByStartingLetter($letter) { - return self::getEntryArray (self::SQL_AUTHORS_BY_FIRST_LETTER, array ($letter . "%")); - } - - public static function getAllAuthors() { - return self::getEntryArray (self::SQL_ALL_AUTHORS, array ()); - } - - public static function getEntryArray ($query, $params) { - list ($totalNumber, $result) = parent::executeQuery ($query, self::AUTHOR_COLUMNS, "", $params, -1); - $entryArray = array(); - while ($post = $result->fetchObject ()) - { - $author = new Author ($post->id, $post->sort); - array_push ($entryArray, new Entry ($post->sort, $author->getEntryId (), - str_format (localize("bookword", $post->count), $post->count), "text", - array ( new LinkNavigation ($author->getUri ())))); - } - return $entryArray; - } - - public static function getAuthorById ($authorId) { - $result = parent::getDb ()->prepare('select sort from authors where id = ?'); - $result->execute (array ($authorId)); - return new Author ($authorId, $result->fetchColumn ()); - } - - public static function getAuthorByBookId ($bookId) { - $result = parent::getDb ()->prepare('select authors.id as id, authors.sort as sort -from authors, books_authors_link -where author = authors.id -and book = ?'); - $result->execute (array ($bookId)); - $authorArray = array (); - while ($post = $result->fetchObject ()) { - array_push ($authorArray, new Author ($post->id, $post->sort)); - } - return $authorArray; - } -} -?> \ No newline at end of file diff --git a/base.php b/base.php index 56503c60d..06402c9ad 100644 --- a/base.php +++ b/base.php @@ -3,576 +3,411 @@ * COPS (Calibre OPDS PHP Server) class file * * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) - * @author Sbastien Lucas + * @author Sébastien Lucas */ -define ("VERSION", "0.3.2"); +require 'config.php'; +/** @var array $config */ + +define('VERSION', '1.3.3'); +define('DB', 'db'); +define('TEMPLATE_DIR', 'templates/'); date_default_timezone_set($config['default_timezone']); - -function getURLParam ($name, $default = NULL) { - if (!empty ($_GET) && isset($_GET[$name])) { - return $_GET[$name]; - } - return $default; -} -function getUrlWithVersion ($url) { - return $url . "?v=" . VERSION; -} +const CONFIG_COPS_TEMPLATE = 'cops_template'; -function xml2xhtml($xml) { - return preg_replace_callback('#<(\w+)([^>]*)\s*/>#s', create_function('$m', ' - $xhtml_tags = array("br", "hr", "input", "frame", "img", "area", "link", "col", "base", "basefont", "param"); - return in_array($m[1], $xhtml_tags) ? "<$m[1]$m[2] />" : "<$m[1]$m[2]>"; - '), $xml); +function useServerSideRendering() +{ + global $config; + return preg_match('/' . $config['cops_server_side_render'] . '/', $_SERVER['HTTP_USER_AGENT']); } -function html2xhtml ($html) { - $doc = new DOMDocument(); - $doc->loadHTML($html); // Load the HTML - $output = utf8_decode($doc->saveXML($doc->documentElement)); // Transform to an Ansi xml stream - $output = xml2xhtml($output); // Fix the br / hr ... - if (preg_match ("/(.*)<\/body><\/html>/", $output, $matches)) { - $output = $matches [1]; // Remove +function serverSideRender($data) +{ + // Get the templates + $theme = getCurrentTemplate(); + $header = file_get_contents(TEMPLATE_DIR . $theme . '/header.html'); + $footer = file_get_contents(TEMPLATE_DIR . $theme . '/footer.html'); + $main = file_get_contents(TEMPLATE_DIR . $theme . '/main.html'); + $bookdetail = file_get_contents(TEMPLATE_DIR . $theme . '/bookdetail.html'); + $page = file_get_contents(TEMPLATE_DIR . $theme . '/page.html'); + + // Generate the function for the template + $template = new doT(); + $dot = $template->template($page, ['bookdetail' => $bookdetail, + 'header' => $header, + 'footer' => $footer, + 'main' => $main]); + // If there is a syntax error in the function created + // $dot will be equal to FALSE + if (!$dot) { + return false; } - return $output; + // Execute the template + if (!empty($data)) { + return $dot($data); + } + + return null; } -/** - * This method is a direct copy-paste from - * http://tmont.com/blargh/2010/1/string-format-in-php - */ -function str_format($format) { - $args = func_get_args(); - $format = array_shift($args); - - preg_match_all('/(?=\{)\{(\d+)\}(?!\})/', $format, $matches, PREG_OFFSET_CAPTURE); - $offset = 0; - foreach ($matches[1] as $data) { - $i = $data[0]; - $format = substr_replace($format, @$args[$i], $offset + $data[1] - 1, 2 + strlen($i)); - $offset += strlen(@$args[$i]) - 2 - strlen($i); +function getQueryString() +{ + if (isset($_SERVER['QUERY_STRING'])) { + return $_SERVER['QUERY_STRING']; } - - return $format; + return ""; } -/** - * This method is based on this page - * http://www.mind-it.info/2010/02/22/a-simple-approach-to-localization-in-php/ - */ -function localize($phrase, $count=-1) { - if ($count == 0) - $phrase .= ".none"; - if ($count == 1) - $phrase .= ".one"; - if ($count > 1) - $phrase .= ".many"; +function notFound() +{ + header($_SERVER['SERVER_PROTOCOL'].' 404 Not Found'); + header('Status: 404 Not Found'); - /* Static keyword is used to ensure the file is loaded only once */ - static $translations = NULL; - /* If no instance of $translations has occured load the language file */ - if (is_null($translations)) { - $lang = "en"; - if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) - { - $lang = substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2); - } - $lang_file_en = NULL; - $lang_file = 'lang/Localization_' . $lang . '.json'; - if (!file_exists($lang_file)) { - $lang_file = 'lang/' . 'Localization_en.json'; - } - elseif ($lang != "en") { - $lang_file_en = 'lang/' . 'Localization_en.json'; - } - $lang_file_content = file_get_contents($lang_file); - /* Load the language file as a JSON object and transform it into an associative array */ - $translations = json_decode($lang_file_content, true); - if ($lang_file_en) - { - $lang_file_content = file_get_contents($lang_file_en); - $translations_en = json_decode($lang_file_content, true); - $translations = array_merge ($translations_en, $translations); + $_SERVER['REDIRECT_STATUS'] = 404; +} + +$urlParams = []; +function initURLParam() +{ + global $urlParams; + if (!empty($_GET)) { + foreach ($_GET as $name => $value) { + $urlParams[$name] = $_GET[$name]; } } - return $translations[$phrase]; } -function addURLParameter($urlParams, $paramName, $paramValue) { - $params = array(); - parse_str($urlParams, $params); - if (empty ($paramValue)) { - unset ($params[$paramName]); - } else { - $params[$paramName] = $paramValue; +function getURLParam($name, $default = null) +{ + global $urlParams; + if (!empty($urlParams) && isset($urlParams[$name]) && $urlParams[$name] != '') { + return $urlParams[$name]; } - return http_build_query($params); + return $default; +} + +function setURLParam($name, $value) +{ + global $urlParams; + $urlParams[$name] = $value; } -class Link +function getCurrentOption($option) { - const OPDS_THUMBNAIL_TYPE = "http://opds-spec.org/image/thumbnail"; - const OPDS_IMAGE_TYPE = "http://opds-spec.org/image"; - const OPDS_ACQUISITION_TYPE = "http://opds-spec.org/acquisition"; - const OPDS_NAVIGATION_TYPE = "application/atom+xml;profile=opds-catalog;kind=navigation"; - const OPDS_PAGING_TYPE = "application/atom+xml;profile=opds-catalog;kind=acquisition"; - - public $href; - public $type; - public $rel; - public $title; - public $facetGroup; - public $activeFacet; - - public function __construct($phref, $ptype, $prel = NULL, $ptitle = NULL, $pfacetGroup = NULL, $pactiveFacet = FALSE) { - $this->href = $phref; - $this->type = $ptype; - $this->rel = $prel; - $this->title = $ptitle; - $this->facetGroup = $pfacetGroup; - $this->activeFacet = $pactiveFacet; + global $config; + if (isset($_COOKIE[$option])) { + if (isset($config ['cops_' . $option]) && is_array($config ['cops_' . $option])) { + return explode(',', $_COOKIE[$option]); + } elseif (!preg_match('/[^A-Za-z0-9\-_]/', $_COOKIE[$option])) { + return $_COOKIE[$option]; + } } - - public function hrefXhtml () { - return str_replace ("&", "&", $this->href); + if (isset($config ['cops_' . $option])) { + return $config ['cops_' . $option]; } + + return ''; } -class LinkNavigation extends Link +function getCurrentCss() { - public function __construct($phref, $prel = NULL, $ptitle = NULL) { - parent::__construct ($phref, Link::OPDS_NAVIGATION_TYPE, $prel, $ptitle); - $this->href = $_SERVER["SCRIPT_NAME"] . $this->href; + global $config; + $style = getCurrentOption('style'); + if (!preg_match('/[^A-Za-z0-9\-_]/', $style)) { + return TEMPLATE_DIR . getCurrentTemplate() . '/styles/style-' . getCurrentOption('style') . '.css'; } + return 'templates/' . $config[CONFIG_COPS_TEMPLATE] . '/styles/style-' . $config[CONFIG_COPS_TEMPLATE] . '.css'; } -class LinkFacet extends Link +function getCurrentTemplate() { - public function __construct($phref, $ptitle = NULL, $pfacetGroup = NULL, $pactiveFacet = FALSE) { - parent::__construct ($phref, Link::OPDS_PAGING_TYPE, "http://opds-spec.org/facet", $ptitle, $pfacetGroup, $pactiveFacet); - $this->href = $_SERVER["SCRIPT_NAME"] . $this->href; + global $config; + $template = getCurrentOption('template'); + if (!preg_match('/[^A-Za-z0-9\-_]/', $template)) { + return $template; } + return $config[CONFIG_COPS_TEMPLATE]; } -class Entry +function getUrlWithVersion($url) { - public $title; - public $id; - public $content; - public $contentType; - public $linkArray; - public $localUpdated; - private static $updated = NULL; - - public static $icons = array( - Author::ALL_AUTHORS_ID => 'images/author.png', - Serie::ALL_SERIES_ID => 'images/serie.png', - Book::ALL_RECENT_BOOKS_ID => 'images/recent.png', - Tag::ALL_TAGS_ID => 'images/tag.png', - CustomColumn::ALL_CUSTOMS_ID => 'images/tag.png', - "calibre:books$" => 'images/allbook.png', - "calibre:books:letter" => 'images/allbook.png' - ); - - public function getUpdatedTime () { - if (!is_null ($this->localUpdated)) { - return date (DATE_ATOM, $this->localUpdated); - } - if (is_null (self::$updated)) { - self::$updated = time(); - } - return date (DATE_ATOM, self::$updated); - } - - public function __construct($ptitle, $pid, $pcontent, $pcontentType, $plinkArray) { - global $config; - $this->title = $ptitle; - $this->id = $pid; - $this->content = $pcontent; - $this->contentType = $pcontentType; - $this->linkArray = $plinkArray; - - if ($config['cops_show_icons'] == 1) - { - foreach (self::$icons as $reg => $image) - { - if (preg_match ("/" . $reg . "/", $pid)) { - array_push ($this->linkArray, new Link (getUrlWithVersion ($image), "image/png", Link::OPDS_THUMBNAIL_TYPE)); - break; - } - } - } - } + return $url . '?v=' . VERSION; } -class EntryBook extends Entry +function xml2xhtml($xml) { - public $book; - - public function __construct($ptitle, $pid, $pcontent, $pcontentType, $plinkArray, $pbook) { - parent::__construct ($ptitle, $pid, $pcontent, $pcontentType, $plinkArray); - $this->book = $pbook; - $this->localUpdated = $pbook->timestamp; - } - - public function getCoverThumbnail () { - foreach ($this->linkArray as $link) { - if ($link->rel == Link::OPDS_THUMBNAIL_TYPE) - return $link->hrefXhtml (); + return preg_replace_callback('#<(\w+)([^>]*)\s*/>#s', function ($m) { + $xhtml_tags = ['br', 'hr', 'input', 'frame', 'img', 'area', 'link', 'col', 'base', 'basefont', 'param']; + if (in_array($m[1], $xhtml_tags)) { + return '<' . $m[1] . $m[2] . ' />'; + } else { + return '<' . $m[1] . $m[2] . '>'; } - return null; - } - - public function getCover () { - foreach ($this->linkArray as $link) { - if ($link->rel == Link::OPDS_IMAGE_TYPE) - return $link->hrefXhtml (); - } - return null; - } + }, $xml); } -class Page +function display_xml_error($error) { - public $title; - public $subtitle = ""; - public $idPage; - public $idGet; - public $query; - public $favicon; - public $n; - public $totalNumber = -1; - public $entryArray = array(); - - public static function getPage ($pageId, $id, $query, $n) - { - switch ($pageId) { - case Base::PAGE_ALL_AUTHORS : - return new PageAllAuthors ($id, $query, $n); - case Base::PAGE_AUTHORS_FIRST_LETTER : - return new PageAllAuthorsLetter ($id, $query, $n); - case Base::PAGE_AUTHOR_DETAIL : - return new PageAuthorDetail ($id, $query, $n); - case Base::PAGE_ALL_TAGS : - return new PageAllTags ($id, $query, $n); - case Base::PAGE_TAG_DETAIL : - return new PageTagDetail ($id, $query, $n); - case Base::PAGE_ALL_CUSTOMS : - return new PageAllCustoms ($id, $query, $n); - case Base::PAGE_CUSTOM_DETAIL : - return new PageCustomDetail ($id, $query, $n); - case Base::PAGE_ALL_SERIES : - return new PageAllSeries ($id, $query, $n); - case Base::PAGE_ALL_BOOKS : - return new PageAllBooks ($id, $query, $n); - case Base::PAGE_ALL_BOOKS_LETTER: - return new PageAllBooksLetter ($id, $query, $n); - case Base::PAGE_ALL_RECENT_BOOKS : - return new PageRecentBooks ($id, $query, $n); - case Base::PAGE_SERIE_DETAIL : - return new PageSerieDetail ($id, $query, $n); - case Base::PAGE_OPENSEARCH_QUERY : - return new PageQueryResult ($id, $query, $n); - case Base::PAGE_BOOK_DETAIL : - return new PageBookDetail ($id, $query, $n); - default: - $page = new Page ($id, $query, $n); - $page->idPage = "cops:catalog"; - return $page; - } - } - - public function __construct($pid, $pquery, $pn) { - global $config; - - $this->idGet = $pid; - $this->query = $pquery; - $this->n = $pn; - $this->favicon = $config['cops_icon']; - } - - public function InitializeContent () - { - global $config; - $this->title = $config['cops_title_default']; - $this->subtitle = $config['cops_subtitle_default']; - array_push ($this->entryArray, Author::getCount()); - array_push ($this->entryArray, Serie::getCount()); - array_push ($this->entryArray, Tag::getCount()); - foreach ($config['cops_calibre_custom_column'] as $lookup) { - $customId = CustomColumn::getCustomId ($lookup); - if (!is_null ($customId)) { - array_push ($this->entryArray, CustomColumn::getCount($customId)); - } - } - $this->entryArray = array_merge ($this->entryArray, Book::getCount()); - } - - public function isPaginated () - { - global $config; - return ($config['cops_max_item_per_page'] != -1 && - $this->totalNumber != -1 && - $this->totalNumber > $config['cops_max_item_per_page']); - } - - public function getNextLink () - { - global $config; - $currentUrl = $_SERVER['QUERY_STRING']; - $currentUrl = preg_replace ("/\&n=.*?$/", "", "?" . $_SERVER['QUERY_STRING']); - if (($this->n) * $config['cops_max_item_per_page'] < $this->totalNumber) { - return new LinkNavigation ($currentUrl . "&n=" . ($this->n + 1), "next", "Page suivante"); - } - return NULL; - } - - public function getPrevLink () - { - global $config; - $currentUrl = $_SERVER['QUERY_STRING']; - $currentUrl = preg_replace ("/\&n=.*?$/", "", "?" . $_SERVER['QUERY_STRING']); - if ($this->n > 1) { - return new LinkNavigation ($currentUrl . "&n=" . ($this->n - 1), "previous", "Page precedente"); - } - return NULL; - } - - public function getMaxPage () - { - global $config; - return ceil ($this->totalNumber / $config['cops_max_item_per_page']); + $return = ''; + $return .= str_repeat('-', $error->column) . "^\n"; + + switch ($error->level) { + case LIBXML_ERR_WARNING: + $return .= 'Warning ' . $error->code . ': '; + break; + case LIBXML_ERR_ERROR: + $return .= 'Error ' . $error->code . ': '; + break; + case LIBXML_ERR_FATAL: + $return .= 'Fatal Error ' . $error->code . ': '; + break; } - - public function containsBook () - { - if (count ($this->entryArray) == 0) return false; - if (get_class ($this->entryArray [0]) == "EntryBook") return true; - return false; + + $return .= trim($error->message) . + "\n Line: " . $error->line . + "\n Column: " . $error->column; + + if ($error->file) { + $return .= "\n File: " . $error->file; } + return "$return\n\n--------------------------------------------\n\n"; } -class PageAllAuthors extends Page +function are_libxml_errors_ok() { - public function InitializeContent () - { - global $config; - - $this->title = localize("authors.title"); - if ($config['cops_author_split_first_letter'] == 1) { - $this->entryArray = Author::getAllAuthorsByFirstLetter(); - } - else { - $this->entryArray = Author::getAllAuthors(); + $errors = libxml_get_errors(); + + foreach ($errors as $error) { + if ($error->code == 801) { + return false; } - $this->idPage = Author::ALL_AUTHORS_ID; } + return true; } -class PageAllAuthorsLetter extends Page +function html2xhtml($html) { - public function InitializeContent () - { - global $config; - - $this->idPage = Author::getEntryIdByLetter ($this->idGet); - $this->entryArray = Author::getAuthorsByStartingLetter ($this->idGet); - $this->title = str_format (localize ("splitByLetter.letter"), str_format (localize ("authorword", count ($this->entryArray)), count ($this->entryArray)), $this->idGet); + $doc = new DOMDocument(); + libxml_use_internal_errors(true); + + $doc->loadHTML('' . + $html . ''); // Load the HTML + $output = $doc->saveXML($doc->documentElement); // Transform to an Ansi xml stream + $output = xml2xhtml($output); + if (preg_match('#(.*)#ms', $output, $matches)) { + $output = $matches [1]; // Remove } -} + /* + // In case of error with summary, use it to debug + $errors = libxml_get_errors(); -class PageAuthorDetail extends Page -{ - public function InitializeContent () - { - $author = Author::getAuthorById ($this->idGet); - $this->idPage = $author->getEntryId (); - $this->title = $author->name; - list ($this->entryArray, $this->totalNumber) = Book::getBooksByAuthor ($this->idGet, $this->n); + foreach ($errors as $error) { + $output .= display_xml_error($error); } -} + */ -class PageAllTags extends Page -{ - public function InitializeContent () - { - $this->title = localize("tags.title"); - $this->entryArray = Tag::getAllTags(); - $this->idPage = Tag::ALL_TAGS_ID; + if (!are_libxml_errors_ok()) { + $output = 'HTML code not valid.'; } + + libxml_use_internal_errors(false); + return $output; } -class PageCustomDetail extends Page +/** + * This method is a direct copy-paste from + * http://tmont.com/blargh/2010/1/string-format-in-php + */ +function str_format($format) { - public function InitializeContent () - { - $customId = getURLParam ("custom", NULL); - $custom = CustomColumn::getCustomById ($customId, $this->idGet); - $this->idPage = $custom->getEntryId (); - $this->title = $custom->name; - list ($this->entryArray, $this->totalNumber) = Book::getBooksByCustom ($customId, $this->idGet, $this->n); + $args = func_get_args(); + $format = array_shift($args); + + preg_match_all('/(?=\{)\{(\d+)\}(?!\})/', $format, $matches, PREG_OFFSET_CAPTURE); + $offset = 0; + foreach ($matches[1] as $data) { + $i = $data[0]; + $format = substr_replace($format, @$args[(int)$i], $offset + $data[1] - 1, 2 + strlen($i)); + $offset += strlen(@$args[(int)$i]) - 2 - strlen($i); } + + return $format; } -class PageAllCustoms extends Page +/** + * Get all accepted languages from the browser and put them in a sorted array + * languages id are normalized : fr-fr -> fr_FR + * @return array of languages + */ +function getAcceptLanguages() { - public function InitializeContent () - { - $customId = getURLParam ("custom", NULL); - $this->title = CustomColumn::getAllTitle ($customId); - $this->entryArray = CustomColumn::getAllCustoms($customId); - $this->idPage = CustomColumn::getAllCustomsId ($customId); + $langs = []; + + if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) { + // break up string into pieces (languages and q factors) + $accept = $_SERVER['HTTP_ACCEPT_LANGUAGE']; + if (preg_match('/^(\w{2})-\w{2}$/', $accept, $matches)) { + // Special fix for IE11 which send fr-FR and nothing else + $accept = $accept . ',' . $matches[1] . ';q=0.8'; + } + preg_match_all('/([a-z]{1,8}(-[a-z]{1,8})?)\s*(;\s*q\s*=\s*(1|0\.[0-9]+))?/i', $accept, $lang_parse); + + if (count($lang_parse[1])) { + $langs = []; + foreach ($lang_parse[1] as $lang) { + // Format the language code (not standard among browsers) + if (strlen($lang) == 5) { + $lang = str_replace('-', '_', $lang); + $splitted = preg_split('/_/', $lang); + $lang = $splitted[0] . '_' . strtoupper($splitted[1]); + } + array_push($langs, $lang); + } + // create a list like "en" => 0.8 + $langs = array_combine($langs, $lang_parse[4]); + + // set default to 1 for any without q factor + foreach ($langs as $lang => $val) { + if ($val === '') { + $langs[$lang] = 1; + } + } + + // sort list based on value + arsort($langs, SORT_NUMERIC); + } } + + return $langs; } -class PageTagDetail extends Page +/** + * Find the best translation file possible based on the accepted languages + * @return array of language and language file + */ +function getLangAndTranslationFile() { - public function InitializeContent () - { - $tag = Tag::getTagById ($this->idGet); - $this->idPage = $tag->getEntryId (); - $this->title = $tag->name; - list ($this->entryArray, $this->totalNumber) = Book::getBooksByTag ($this->idGet, $this->n); + global $config; + $langs = []; + $lang = 'en'; + if (!empty($config['cops_language'])) { + $lang = $config['cops_language']; + } elseif (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) { + $langs = getAcceptLanguages(); + } + //echo var_dump($langs); + $lang_file = null; + foreach ($langs as $language => $val) { + $temp_file = dirname(__FILE__). '/lang/Localization_' . $language . '.json'; + if (file_exists($temp_file)) { + $lang = $language; + $lang_file = $temp_file; + break; + } } + if (empty($lang_file)) { + $lang_file = dirname(__FILE__). '/lang/Localization_' . $lang . '.json'; + } + return [$lang, $lang_file]; } -class PageAllSeries extends Page +/** + * This method is based on this page + * http://www.mind-it.info/2010/02/22/a-simple-approach-to-localization-in-php/ + */ +function localize($phrase, $count=-1, $reset=false) { - public function InitializeContent () - { - $this->title = localize("series.title"); - $this->entryArray = Serie::getAllSeries(); - $this->idPage = Serie::ALL_SERIES_ID; + global $config; + if ($count == 0) { + $phrase .= '.none'; + } + if ($count == 1) { + $phrase .= '.one'; + } + if ($count > 1) { + $phrase .= '.many'; } -} -class PageSerieDetail extends Page -{ - public function InitializeContent () - { - $serie = Serie::getSerieById ($this->idGet); - $this->title = $serie->name; - list ($this->entryArray, $this->totalNumber) = Book::getBooksBySeries ($this->idGet, $this->n); - $this->idPage = $serie->getEntryId (); + /* Static keyword is used to ensure the file is loaded only once */ + static $translations = null; + if ($reset) { + $translations = null; } -} + /* If no instance of $translations has occured load the language file */ + if (is_null($translations)) { + $lang_file_en = null; + [$lang, $lang_file] = getLangAndTranslationFile(); + if ($lang != 'en') { + $lang_file_en = dirname(__FILE__). '/lang/' . 'Localization_en.json'; + } -class PageAllBooks extends Page -{ - public function InitializeContent () - { - $this->title = localize ("allbooks.title"); - $this->entryArray = Book::getAllBooks (); - $this->idPage = Book::ALL_BOOKS_ID; + $lang_file_content = file_get_contents($lang_file); + /* Load the language file as a JSON object and transform it into an associative array */ + $translations = json_decode($lang_file_content, true); + + /* Clean the array of all unfinished translations */ + foreach (array_keys($translations) as $key) { + if (preg_match('/^##TODO##/', $key)) { + unset($translations [$key]); + } + } + if (!is_null($lang_file_en)) { + $lang_file_content = file_get_contents($lang_file_en); + $translations_en = json_decode($lang_file_content, true); + $translations = array_merge($translations_en, $translations); + } } + if (array_key_exists($phrase, $translations)) { + return $translations[$phrase]; + } + return $phrase; } -class PageAllBooksLetter extends Page +function addURLParameter($urlParams, $paramName, $paramValue) { - public function InitializeContent () - { - list ($this->entryArray, $this->totalNumber) = Book::getBooksByStartingLetter ($this->idGet, $this->n); - $this->idPage = Book::getEntryIdByLetter ($this->idGet); - - $count = $this->totalNumber; - if ($count == -1) - $count = count ($this->entryArray); - - $this->title = str_format (localize ("splitByLetter.letter"), str_format (localize ("bookword", $count), $count), $this->idGet); + if (empty($urlParams)) { + $urlParams = ''; + } + $start = ''; + if (preg_match('#^\?(.*)#', $urlParams, $matches)) { + $start = '?'; + $urlParams = $matches[1]; + } + $params = []; + parse_str($urlParams, $params); + if (empty($paramValue) && strval($paramValue) !== "0") { + unset($params[$paramName]); + } else { + $params[$paramName] = $paramValue; } + return $start . http_build_query($params); } -class PageRecentBooks extends Page +function useNormAndUp() { - public function InitializeContent () - { - $this->title = localize ("recent.title"); - $this->entryArray = Book::getAllRecentBooks (); - $this->idPage = Book::ALL_RECENT_BOOKS_ID; - } + global $config; + return $config ['cops_normalized_search'] == '1'; } -class PageQueryResult extends Page +function normalizeUtf8String($s) { - public function InitializeContent () - { - $this->title = "Search result for query *" . $this->query . "*"; // TODO I18N - list ($this->entryArray, $this->totalNumber) = Book::getBooksByQuery ($this->query, $this->n); - } + include_once 'transliteration.php'; + return _transliteration_process($s); } -class PageBookDetail extends Page +function normAndUp($s) { - public function InitializeContent () - { - $book = Book::getBookById ($this->idGet); - $this->title = $book->title; - } + return mb_strtoupper(normalizeUtf8String($s), 'UTF-8'); } -abstract class Base +function dd($m, $e = false) { - const PAGE_INDEX = "index"; - const PAGE_ALL_AUTHORS = "1"; - const PAGE_AUTHORS_FIRST_LETTER = "2"; - const PAGE_AUTHOR_DETAIL = "3"; - const PAGE_ALL_BOOKS = "4"; - const PAGE_ALL_BOOKS_LETTER = "5"; - const PAGE_ALL_SERIES = "6"; - const PAGE_SERIE_DETAIL = "7"; - const PAGE_OPENSEARCH = "8"; - const PAGE_OPENSEARCH_QUERY = "9"; - const PAGE_ALL_RECENT_BOOKS = "10"; - const PAGE_ALL_TAGS = "11"; - const PAGE_TAG_DETAIL = "12"; - const PAGE_BOOK_DETAIL = "13"; - const PAGE_ALL_CUSTOMS = "14"; - const PAGE_CUSTOM_DETAIL = "15"; - - const COMPATIBILITY_XML_ALDIKO = "aldiko"; - - private static $db = NULL; - - public static function getDbFileName () { - global $config; - return $config['calibre_directory'] .'metadata.db'; + echo '
';
+    print_r($m);
+    echo '
'; + if ($e) { + exit; } - - public static function getDb () { - global $config; - if (is_null (self::$db)) { - try { - self::$db = new PDO('sqlite:'. self::getDbFileName ()); - } catch (Exception $e) { - header("location: checkconfig.php?err=1"); - exit(); - } - } - return self::$db; - } - - public static function executeQuery($query, $columns, $filter, $params, $n) { - global $config; - $totalResult = -1; - - if ($config['cops_max_item_per_page'] != -1 && $n != -1) - { - // First check total number of results - $result = self::getDb ()->prepare (str_format ($query, "count(*)", $filter)); - $result->execute ($params); - $totalResult = $result->fetchColumn (); - - // Next modify the query and params - $query .= " limit ?, ?"; - array_push ($params, ($n - 1) * $config['cops_max_item_per_page'], $config['cops_max_item_per_page']); - } - - $result = self::getDb ()->prepare(str_format ($query, $columns, $filter)); - $result->execute ($params); - return array ($totalResult, $result); - } - } -?> \ No newline at end of file diff --git a/book.php b/book.php deleted file mode 100644 index e870a580b..000000000 --- a/book.php +++ /dev/null @@ -1,496 +0,0 @@ - - */ - -require_once('base.php'); -require_once('serie.php'); -require_once('author.php'); -require_once('tag.php'); -require_once ("customcolumn.php"); -require_once('data.php'); -require_once('php-epub-meta/epub.php'); - -// Silly thing because PHP forbid string concatenation in class const -define ('SQL_BOOKS_LEFT_JOIN', "left outer join comments on comments.book = books.id - left outer join books_ratings_link on books_ratings_link.book = books.id - left outer join ratings on books_ratings_link.rating = ratings.id "); -define ('SQL_BOOKS_BY_FIRST_LETTER', "select {0} from books " . SQL_BOOKS_LEFT_JOIN . " - where upper (books.sort) like ? order by books.sort"); -define ('SQL_BOOKS_BY_AUTHOR', "select {0} from books_authors_link, books " . SQL_BOOKS_LEFT_JOIN . " - where books_authors_link.book = books.id and author = ? {1} order by pubdate"); -define ('SQL_BOOKS_BY_SERIE', "select {0} from books_series_link, books " . SQL_BOOKS_LEFT_JOIN . " - where books_series_link.book = books.id and series = ? {1} order by series_index"); -define ('SQL_BOOKS_BY_TAG', "select {0} from books_tags_link, books " . SQL_BOOKS_LEFT_JOIN . " - where books_tags_link.book = books.id and tag = ? {1} order by sort"); -define ('SQL_BOOKS_BY_CUSTOM', "select {0} from {2}, books " . SQL_BOOKS_LEFT_JOIN . " - where {2}.book = books.id and {2}.{3} = ? {1} order by sort"); -define ('SQL_BOOKS_QUERY', "select {0} from books " . SQL_BOOKS_LEFT_JOIN . " - where (exists (select null from authors, books_authors_link where book = books.id and author = authors.id and authors.name like ?) or title like ?) {1} order by books.sort"); -define ('SQL_BOOKS_RECENT', "select {0} from books " . SQL_BOOKS_LEFT_JOIN . " - where 1=1 {1} order by timestamp desc limit "); - -class Book extends Base { - const ALL_BOOKS_UUID = "urn:uuid"; - const ALL_BOOKS_ID = "calibre:books"; - const ALL_RECENT_BOOKS_ID = "calibre:recentbooks"; - const BOOK_COLUMNS = "books.id as id, books.title as title, text as comment, path, timestamp, pubdate, series_index, uuid, has_cover, ratings.rating"; - - const SQL_BOOKS_LEFT_JOIN = SQL_BOOKS_LEFT_JOIN; - const SQL_BOOKS_BY_FIRST_LETTER = SQL_BOOKS_BY_FIRST_LETTER; - const SQL_BOOKS_BY_AUTHOR = SQL_BOOKS_BY_AUTHOR; - const SQL_BOOKS_BY_SERIE = SQL_BOOKS_BY_SERIE; - const SQL_BOOKS_BY_TAG = SQL_BOOKS_BY_TAG; - const SQL_BOOKS_BY_CUSTOM = SQL_BOOKS_BY_CUSTOM; - const SQL_BOOKS_QUERY = SQL_BOOKS_QUERY; - const SQL_BOOKS_RECENT = SQL_BOOKS_RECENT; - - public $id; - public $title; - public $timestamp; - public $pubdate; - public $path; - public $uuid; - public $hasCover; - public $relativePath; - public $seriesIndex; - public $comment; - public $rating; - public $datas = NULL; - public $authors = NULL; - public $serie = NULL; - public $tags = NULL; - public $format = array (); - - - public function __construct($line) { - global $config; - $this->id = $line->id; - $this->title = $line->title; - $this->timestamp = strtotime ($line->timestamp); - $this->pubdate = strtotime ($line->pubdate); - $this->path = $config['calibre_directory'] . $line->path; - $this->relativePath = $line->path; - $this->seriesIndex = $line->series_index; - $this->comment = $line->comment; - $this->uuid = $line->uuid; - $this->hasCover = $line->has_cover; - if (!file_exists ($this->getFilePath ("jpg"))) { - // double check - $this->hasCover = 0; - } - $this->rating = $line->rating; - } - - public function getEntryId () { - return self::ALL_BOOKS_UUID.":".$this->uuid; - } - - public static function getEntryIdByLetter ($startingLetter) { - return self::ALL_BOOKS_ID.":letter:".$startingLetter; - } - - public function getUri () { - return "?page=".parent::PAGE_BOOK_DETAIL."&id=$this->id"; - } - - public function getDetailUrl () { - global $config; - if ($config['cops_use_fancyapps'] == 0) { - return 'index.php' . $this->getUri (); - } else { - return 'bookdetail.php?id=' . $this->id; - } - } - - public function getTitle () { - return $this->title; - } - - public function getAuthors () { - if (is_null ($this->authors)) { - $this->authors = Author::getAuthorByBookId ($this->id); - } - return $this->authors; - } - - public function getFilterString () { - $filter = getURLParam ("tag", NULL); - if (empty ($filter)) return ""; - - $exists = true; - if (preg_match ("/^!(.*)$/", $filter, $matches)) { - $exists = false; - $filter = $matches[1]; - } - - $result = "exists (select null from books_tags_link, tags where books_tags_link.book = books.id and books_tags_link.tag = tags.id and tags.name = '" . $filter . "')"; - - if (!$exists) { - $result = "not " . $result; - } - - return "and " . $result; - } - - public function getAuthorsName () { - $authorList = null; - foreach ($this->getAuthors () as $author) { - if ($authorList) { - $authorList = $authorList . ", " . $author->name; - } - else - { - $authorList = $author->name; - } - } - return $authorList; - } - - public function getSerie () { - if (is_null ($this->serie)) { - $this->serie = Serie::getSerieByBookId ($this->id); - } - return $this->serie; - } - - public function getLanguages () { - $lang = array (); - $result = parent::getDb ()->prepare('select languages.lang_code - from books_languages_link, languages - where books_languages_link.lang_code = languages.id - and book = ? - order by item_order'); - $result->execute (array ($this->id)); - while ($post = $result->fetchObject ()) - { - array_push ($lang, $post->lang_code); - } - return implode (", ", $lang); - } - - public function getTags () { - if (is_null ($this->tags)) { - $this->tags = array (); - - $result = parent::getDb ()->prepare('select tags.id as id, name - from books_tags_link, tags - where tag = tags.id - and book = ? - order by name'); - $result->execute (array ($this->id)); - while ($post = $result->fetchObject ()) - { - array_push ($this->tags, new Tag ($post->id, $post->name)); - } - } - return $this->tags; - } - - public function getDatas () - { - if (is_null ($this->datas)) { - $this->datas = array (); - - $result = parent::getDb ()->prepare('select id, format, name - from data where book = ?'); - $result->execute (array ($this->id)); - - while ($post = $result->fetchObject ()) - { - array_push ($this->datas, new Data ($post, $this)); - } - } - return $this->datas; - } - - public function getDataById ($idData) - { - foreach ($this->getDatas () as $data) { - if ($data->id == $idData) { - return $data; - } - } - return NULL; - } - - - public function getTagsName () { - $tagList = null; - foreach ($this->getTags () as $tag) { - if ($tagList) { - $tagList = $tagList . ", " . $tag->name; - } - else - { - $tagList = $tag->name; - } - } - return $tagList; - } - - public function getRating () { - if (is_null ($this->rating) || $this->rating == 0) { - return ""; - } - $retour = ""; - for ($i = 0; $i < $this->rating / 2; $i++) { - $retour .= "★"; - } - for ($i = 0; $i < 5 - $this->rating / 2; $i++) { - $retour .= "☆"; - } - return $retour; - } - - public function getPubDate () { - if (is_null ($this->pubdate) || ($this->pubdate <= -58979923200)) { - return ""; - } - else { - return date ("Y", $this->pubdate); - } - } - - public function getComment ($withSerie = true) { - $addition = ""; - $se = $this->getSerie (); - if (!is_null ($se) && $withSerie) { - $addition = $addition . "" . localize("content.series") . "" . str_format (localize ("content.series.data"), $this->seriesIndex, htmlspecialchars ($se->name)) . "
\n"; - } - if (preg_match ("/<\/(div|p|a|span)>/", $this->comment)) - { - return $addition . html2xhtml ($this->comment); - } - else - { - return $addition . htmlspecialchars ($this->comment); - } - } - - public function getDataFormat ($format) { - foreach ($this->getDatas () as $data) - { - if ($data->format == $format) - { - return $data; - } - } - return NULL; - } - - public function getFilePath ($extension, $idData = NULL, $relative = false) - { - $file = NULL; - if ($extension == "jpg") - { - $file = "cover.jpg"; - } - else - { - $data = $this->getDataById ($idData); - $file = $data->name . "." . strtolower ($data->format); - } - - if ($relative) - { - return $this->relativePath."/".$file; - } - else - { - return $this->path."/".$file; - } - } - - public function getUpdatedEpub ($idData) - { - global $config; - $data = $this->getDataById ($idData); - - try - { - $epub = new EPub ($data->getLocalPath ()); - - $epub->Title ($this->title); - $authorArray = array (); - foreach ($this->getAuthors() as $author) { - $authorArray [$author->sort] = $author->name; - } - $epub->Authors ($authorArray); - $epub->Language ($this->getLanguages ()); - $epub->Description ($this->getComment (false)); - $epub->Subjects ($this->getTagsName ()); - $epub->Cover2 ($this->getFilePath ("jpg"), "image/jpeg"); - $epub->Calibre ($this->uuid); - $se = $this->getSerie (); - if (!is_null ($se)) { - $epub->Serie ($se->name); - $epub->SerieIndex ($this->seriesIndex); - } - if ($config['cops_provide_kepub'] == "1" && preg_match("/Kobo/", $_SERVER['HTTP_USER_AGENT'])) { - $epub->updateForKepub (); - } - $epub->download ($data->getUpdatedFilenameEpub ()); - } - catch (Exception $e) - { - echo "Exception : " . $e->getMessage(); - } - } - - public function getLinkArray () - { - global $config; - $linkArray = array(); - - if ($this->hasCover) - { - array_push ($linkArray, Data::getLink ($this, "jpg", "image/jpeg", Link::OPDS_IMAGE_TYPE, "cover.jpg", NULL)); - $height = "50"; - if (preg_match ('/feed.php/', $_SERVER["SCRIPT_NAME"])) { - $height = $config['cops_opds_thumbnail_height']; - } - else - { - $height = $config['cops_html_thumbnail_height']; - } - array_push ($linkArray, new Link ("fetch.php?id=$this->id&height=" . $height, "image/jpeg", Link::OPDS_THUMBNAIL_TYPE)); - } - - foreach ($this->getDatas () as $data) - { - if ($data->isKnownType ()) - { - array_push ($linkArray, $data->getDataLink (Link::OPDS_ACQUISITION_TYPE, "Download")); - } - } - - foreach ($this->getAuthors () as $author) { - array_push ($linkArray, new LinkNavigation ($author->getUri (), "related", str_format (localize ("bookentry.author"), localize ("splitByLetter.book.other"), $author->name))); - } - - $serie = $this->getSerie (); - if (!is_null ($serie)) { - array_push ($linkArray, new LinkNavigation ($serie->getUri (), "related", str_format (localize ("content.series.data"), $this->seriesIndex, $serie->name))); - } - - return $linkArray; - } - - - public function getEntry () { - return new EntryBook ($this->getTitle (), $this->getEntryId (), - $this->getComment (), "text/html", - $this->getLinkArray (), $this); - } - - public static function getCount() { - global $config; - $nBooks = parent::getDb ()->query('select count(*) from books')->fetchColumn(); - $result = array(); - $entry = new Entry (localize ("allbooks.title"), - self::ALL_BOOKS_ID, - str_format (localize ("allbooks.alphabetical"), $nBooks), "text", - array ( new LinkNavigation ("?page=".parent::PAGE_ALL_BOOKS))); - array_push ($result, $entry); - $entry = new Entry (localize ("recent.title"), - self::ALL_RECENT_BOOKS_ID, - str_format (localize ("recent.list"), $config['cops_recentbooks_limit']), "text", - array ( new LinkNavigation ("?page=".parent::PAGE_ALL_RECENT_BOOKS))); - array_push ($result, $entry); - return $result; - } - - public static function getBooksByAuthor($authorId, $n) { - return self::getEntryArray (self::SQL_BOOKS_BY_AUTHOR, array ($authorId), $n); - } - - - public static function getBooksBySeries($serieId, $n) { - return self::getEntryArray (self::SQL_BOOKS_BY_SERIE, array ($serieId), $n); - } - - public static function getBooksByTag($tagId, $n) { - return self::getEntryArray (self::SQL_BOOKS_BY_TAG, array ($tagId), $n); - } - - public static function getBooksByCustom($customId, $id, $n) { - $query = str_format (self::SQL_BOOKS_BY_CUSTOM, "{0}", "{1}", CustomColumn::getTableLinkName ($customId), CustomColumn::getTableLinkColumn ($customId)); - return self::getEntryArray ($query, array ($id), $n); - } - - public static function getBookById($bookId) { - $result = parent::getDb ()->prepare('select ' . self::BOOK_COLUMNS . ' -from books ' . self::SQL_BOOKS_LEFT_JOIN . ' -where books.id = ?'); - $result->execute (array ($bookId)); - while ($post = $result->fetchObject ()) - { - $book = new Book ($post); - return $book; - } - return NULL; - } - - public static function getBookByDataId($dataId) { - $result = parent::getDb ()->prepare('select ' . self::BOOK_COLUMNS . ', data.name, data.format -from data, books ' . self::SQL_BOOKS_LEFT_JOIN . ' -where data.book = books.id and data.id = ?'); - $result->execute (array ($dataId)); - while ($post = $result->fetchObject ()) - { - $book = new Book ($post); - $data = new Data ($post, $book); - $data->id = $dataId; - $book->datas = array ($data); - return $book; - } - return NULL; - } - - public static function getBooksByQuery($query, $n) { - return self::getEntryArray (self::SQL_BOOKS_QUERY, array ("%" . $query . "%", "%" . $query . "%"), $n); - } - - public static function getAllBooks() { - $result = parent::getDb ()->query("select substr (upper (sort), 1, 1) as title, count(*) as count -from books -group by substr (upper (sort), 1, 1) -order by substr (upper (sort), 1, 1)"); - $entryArray = array(); - while ($post = $result->fetchObject ()) - { - array_push ($entryArray, new Entry ($post->title, Book::getEntryIdByLetter ($post->title), - str_format (localize("bookword", $post->count), $post->count), "text", - array ( new LinkNavigation ("?page=".parent::PAGE_ALL_BOOKS_LETTER."&id=". rawurlencode ($post->title))))); - } - return $entryArray; - } - - public static function getBooksByStartingLetter($letter, $n) { - return self::getEntryArray (self::SQL_BOOKS_BY_FIRST_LETTER, array ($letter . "%"), $n); - } - - public static function getEntryArray ($query, $params, $n) { - list ($totalNumber, $result) = parent::executeQuery ($query, self::BOOK_COLUMNS, self::getFilterString (), $params, $n); - $entryArray = array(); - while ($post = $result->fetchObject ()) - { - $book = new Book ($post); - array_push ($entryArray, $book->getEntry ()); - } - return array ($entryArray, $totalNumber); - } - - - public static function getAllRecentBooks() { - global $config; - list ($entryArray, $totalNumber) = self::getEntryArray (self::SQL_BOOKS_RECENT . $config['cops_recentbooks_limit'], array (), -1); - return $entryArray; - } - -} -?> \ No newline at end of file diff --git a/bookdetail.php b/bookdetail.php deleted file mode 100644 index 4cb77b35a..000000000 --- a/bookdetail.php +++ /dev/null @@ -1,108 +0,0 @@ - - * - */ - -require_once ("config.php"); -require_once ("book.php"); - -$book = Book::getBookById($_GET["id"]); -$authors = $book->getAuthors (); -$tags = $book->getTags (); -$serie = $book->getSerie (); -$book->getLinkArray (); - -?> - -
- - \ No newline at end of file diff --git a/build.xml b/build.xml new file mode 100644 index 000000000..5ae12a728 --- /dev/null +++ b/build.xml @@ -0,0 +1,100 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/checkconfig.php b/checkconfig.php index a71ee3281..bd826ca09 100644 --- a/checkconfig.php +++ b/checkconfig.php @@ -1,114 +1,263 @@ + + + * @author Sébastien Lucas * */ - - require_once ("config.php"); - require_once ("base.php"); - - header ("Content-Type:application/xhtml+xml"); - - $err = getURLParam ("err", -1); - $error = NULL; - switch ($err) { - case 1 : - $error = "Database error"; - break; - } + +require_once dirname(__FILE__) . '/config.php'; +require_once dirname(__FILE__) . '/base.php'; +/** @var array $config */ + +initURLParam(); + +$err = getURLParam('err', -1); +$full = getURLParam('full'); +$error = null; +switch ($err) { + case 1: + $error = 'Database error'; + break; +} ?> - - - - - + + COPS Configuration Check - " media="screen" /> +
-
+
-

COPS Configuration Check

+

COPS Configuration Check

-
-
+ -
+
-
-
You've been redirected because COPS is not configured properly
-
-
+ if (!is_null($error)) { + ?> +
+

You've been redirected because COPS is not configured properly

+

+
-
-
Check if GD is properly installed and loaded
-
- -
-
-
-
Check if Sqlite is properly installed and loaded
-
- -
-
- -
-
Check if Calibre database file exists and is readable
-
- +
+

Check if PHP version is correct

+

+ = 50300) { + echo 'OK (' . PHP_VERSION . ')'; + } else { + echo 'Please install PHP >= 5.3 (' . PHP_VERSION . ')'; + } + } else { + echo 'Please install PHP >= 5.3'; + } +?> +

+
+
+

Check if GD is properly installed and loaded

+

+ +

+
+
+

Check if Sqlite is properly installed and loaded

+

+ +

+
+
+

Check if libxml is properly installed and loaded

+

+ +

+
+
+

Check if Json is properly installed and loaded

+

+ +

+
+
+

Check if mbstring is properly installed and loaded

+

+ +

+
+
+

Check if intl is properly installed and loaded

+

+ +

+
+
+

Check if Normalizer class is properly installed and loaded

+

+ +

+
+
+

Check if the rendering will be done on client side or server side

+

+ +

+
+ $database) { + ?> +
+

Check if Calibre database path is not an URL

+

+ +

+
+
+

Check if Calibre database file exists and is readable

+

+ -
  • Value of \$config['calibre_directory'] in config_local.php
  • -
  • Value of open_basedir in your php.ini
  • +
  • Value of $config[\'calibre_directory\'] in config_local.php (Does it end with a \'/\'?)
  • +
  • Value of open_basedir in your php.ini
  • The access rights of the Calibre Database
  • -
  • Synology users please read this
  • -"; +
  • Synology users please read this
  • +
  • Note that hosting your Calibre Library in /home is almost impossible due to access rights restriction
  • +'; + } + ?> +

    +
    + +
    +

    Check if Calibre database file can be opened with PHP

    +

    + +

    +
    +
    +

    Check if Calibre database file contains at least some of the needed tables

    +

    + query('select count(*) FROM sqlite_master WHERE type="table" AND name in ("books", "authors", "tags", "series")')->fetchColumn(); + if ($count == 4) { + echo $name . ' OK'; + } else { + echo $name . ' Not all Calibre tables were found. Are you sure you\'re using the correct database.'; } - ?> -

    -
    -
    -
    Check if Calibre database file can be opened with PHP
    -
    - + + + +
    +

    Check if all Calibre books are found

    +

    + prepare('select books.path || "/" || data.name || "." || lower (format) as fullpath from data join books on data.book = books.id'); + $result->execute(); + while ($post = $result->fetchObject()) { + if (!is_file(Base::getDbDirectory($i) . $post->fullpath)) { + echo '

    ' . Base::getDbDirectory($i) . $post->fullpath . '

    '; + } } + } catch (Exception $e) { + echo $name . ' If the file is readable, check your php configuration. Exception detail : ' . $e; + } ?> -

    -
    -
    + + + + +
    - diff --git a/composer-dl.sh b/composer-dl.sh new file mode 100755 index 000000000..36eec7d54 --- /dev/null +++ b/composer-dl.sh @@ -0,0 +1,18 @@ +#!/bin/sh +# https://getcomposer.org/ +if [ -x `which wget` ]; then + echo "wget found." + wget -q https://getcomposer.org/installer -O - | php -- --version=1.10.26 +elif [ -x `which curl` ]; then + echo "curl found." + curl -sS https://getcomposer.org/installer | php -- --version=1.10.26 +else + echo "Please install wget or curl to download Composer." +fi + +if [ -f "./composer.phar" ]; then + chmod a+x ./composer.phar + + # Install support for bower and NPM packages + ./composer.phar global require "fxp/composer-asset-plugin:~1.1" +fi diff --git a/composer.json b/composer.json new file mode 100644 index 000000000..2224acffd --- /dev/null +++ b/composer.json @@ -0,0 +1,42 @@ +{ + "name": "seblucas/cops", + "description": "Calibre OPDS (and HTML) PHP Server : web-based light alternative to Calibre content server / Calibre2OPDS to serve ebooks (epub, mobi, pdf, ...)", + "license": "GPL-2.0-or-later", + "require": { + "ext-gd": "*", + "ext-xml": "*", + "ext-xmlwriter": "*", + "ext-intl": "*", + "ext-json": "*", + "ext-pdo_sqlite": "*", + "ext-mbstring": "*", + "dimsemenov/magnific-popup": "~1.1", + "phpmailer/phpmailer": "~6.8", + "twbs/bootstrap": "~3.4", + "npm-asset/jquery": "~1.12", + "npm-asset/js-cookie": "~2.2", + "npm-asset/normalize.css": "~8.0", + "twitter/typeahead.js": "~0.11", + "npm-asset/dot": "~1.1", + "npm-asset/lru-fast": "~0.2" + }, + "require-dev": { + "phpunit/phpunit": "~9.5", + "sauce/sausage": "~0.18", + "phing/phing": "~2.17" + }, + "autoload": { + "classmap": ["lib/", "resources/"] + }, + "repositories": [ + { + "type": "composer", + "url": "https://asset-packagist.org" + } + ], + "config": { + "allow-plugins": { + "sauce/sausage-installer": false + } + } +} diff --git a/composer.lock b/composer.lock new file mode 100644 index 000000000..4125665d5 --- /dev/null +++ b/composer.lock @@ -0,0 +1,3357 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "b2ca6b35ee2005dda8cd69665844f957", + "packages": [ + { + "name": "dimsemenov/magnific-popup", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/dimsemenov/Magnific-Popup.git", + "reference": "6b7a8088783cbce01034414c1fd2d8e1889093ae" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dimsemenov/Magnific-Popup/zipball/6b7a8088783cbce01034414c1fd2d8e1889093ae", + "reference": "6b7a8088783cbce01034414c1fd2d8e1889093ae", + "shasum": "" + }, + "type": "library", + "notification-url": "https://packagist.org/downloads/", + "description": "Light and responsive lightbox script with focus on performance.", + "homepage": "http://dimsemenov.com/plugins/magnific-popup/", + "support": { + "issues": "https://github.com/dimsemenov/Magnific-Popup/issues", + "source": "https://github.com/dimsemenov/Magnific-Popup/tree/1.1.0" + }, + "time": "2016-02-20T09:06:30+00:00" + }, + { + "name": "npm-asset/dot", + "version": "1.1.3", + "dist": { + "type": "tar", + "url": "https://registry.npmjs.org/dot/-/dot-1.1.3.tgz" + }, + "type": "npm-asset", + "license": [ + "MIT" + ] + }, + { + "name": "npm-asset/jquery", + "version": "1.12.4", + "dist": { + "type": "tar", + "url": "https://registry.npmjs.org/jquery/-/jquery-1.12.4.tgz" + }, + "type": "npm-asset", + "license": [ + "MIT" + ] + }, + { + "name": "npm-asset/js-cookie", + "version": "2.2.1", + "dist": { + "type": "tar", + "url": "https://registry.npmjs.org/js-cookie/-/js-cookie-2.2.1.tgz" + }, + "type": "npm-asset", + "license": [ + "MIT" + ] + }, + { + "name": "npm-asset/lru-fast", + "version": "0.2.2", + "dist": { + "type": "tar", + "url": "https://registry.npmjs.org/lru-fast/-/lru-fast-0.2.2.tgz" + }, + "type": "npm-asset", + "license": [ + "MIT" + ] + }, + { + "name": "npm-asset/normalize.css", + "version": "8.0.1", + "dist": { + "type": "tar", + "url": "https://registry.npmjs.org/normalize.css/-/normalize.css-8.0.1.tgz" + }, + "type": "npm-asset", + "license": [ + "MIT" + ] + }, + { + "name": "phpmailer/phpmailer", + "version": "v6.8.0", + "source": { + "type": "git", + "url": "https://github.com/PHPMailer/PHPMailer.git", + "reference": "df16b615e371d81fb79e506277faea67a1be18f1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/df16b615e371d81fb79e506277faea67a1be18f1", + "reference": "df16b615e371d81fb79e506277faea67a1be18f1", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "ext-filter": "*", + "ext-hash": "*", + "php": ">=5.5.0" + }, + "require-dev": { + "dealerdirect/phpcodesniffer-composer-installer": "^0.7.2", + "doctrine/annotations": "^1.2.6 || ^1.13.3", + "php-parallel-lint/php-console-highlighter": "^1.0.0", + "php-parallel-lint/php-parallel-lint": "^1.3.2", + "phpcompatibility/php-compatibility": "^9.3.5", + "roave/security-advisories": "dev-latest", + "squizlabs/php_codesniffer": "^3.7.1", + "yoast/phpunit-polyfills": "^1.0.4" + }, + "suggest": { + "ext-mbstring": "Needed to send email in multibyte encoding charset or decode encoded addresses", + "ext-openssl": "Needed for secure SMTP sending and DKIM signing", + "greew/oauth2-azure-provider": "Needed for Microsoft Azure XOAUTH2 authentication", + "hayageek/oauth2-yahoo": "Needed for Yahoo XOAUTH2 authentication", + "league/oauth2-google": "Needed for Google XOAUTH2 authentication", + "psr/log": "For optional PSR-3 debug logging", + "symfony/polyfill-mbstring": "To support UTF-8 if the Mbstring PHP extension is not enabled (^1.2)", + "thenetworg/oauth2-azure": "Needed for Microsoft XOAUTH2 authentication" + }, + "type": "library", + "autoload": { + "psr-4": { + "PHPMailer\\PHPMailer\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-2.1-only" + ], + "authors": [ + { + "name": "Marcus Bointon", + "email": "phpmailer@synchromedia.co.uk" + }, + { + "name": "Jim Jagielski", + "email": "jimjag@gmail.com" + }, + { + "name": "Andy Prevost", + "email": "codeworxtech@users.sourceforge.net" + }, + { + "name": "Brent R. Matzelle" + } + ], + "description": "PHPMailer is a full-featured email creation and transfer class for PHP", + "support": { + "issues": "https://github.com/PHPMailer/PHPMailer/issues", + "source": "https://github.com/PHPMailer/PHPMailer/tree/v6.8.0" + }, + "funding": [ + { + "url": "https://github.com/Synchro", + "type": "github" + } + ], + "time": "2023-03-06T14:43:22+00:00" + }, + { + "name": "twbs/bootstrap", + "version": "v3.4.1", + "source": { + "type": "git", + "url": "https://github.com/twbs/bootstrap.git", + "reference": "68b0d231a13201eb14acd3dc84e51543d16e5f7e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/twbs/bootstrap/zipball/68b0d231a13201eb14acd3dc84e51543d16e5f7e", + "reference": "68b0d231a13201eb14acd3dc84e51543d16e5f7e", + "shasum": "" + }, + "replace": { + "twitter/bootstrap": "self.version" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.4.x-dev" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jacob Thornton", + "email": "jacobthornton@gmail.com" + }, + { + "name": "Mark Otto", + "email": "markdotto@gmail.com" + } + ], + "description": "The most popular front-end framework for developing responsive, mobile first projects on the web.", + "homepage": "https://getbootstrap.com/", + "keywords": [ + "JS", + "css", + "framework", + "front-end", + "less", + "mobile-first", + "responsive", + "web" + ], + "support": { + "issues": "https://github.com/twbs/bootstrap/issues", + "source": "https://github.com/twbs/bootstrap/tree/v3.4.1" + }, + "time": "2019-02-13T15:55:38+00:00" + }, + { + "name": "twitter/typeahead.js", + "version": "v0.11.1", + "source": { + "type": "git", + "url": "https://github.com/twitter/typeahead.js.git", + "reference": "588440f66559714280628a4f9799f0c4eb880a4a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/twitter/typeahead.js/zipball/588440f66559714280628a4f9799f0c4eb880a4a", + "reference": "588440f66559714280628a4f9799f0c4eb880a4a", + "shasum": "" + }, + "type": "library", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Twitter Inc.", + "homepage": "https://twitter.com/twitteross" + } + ], + "description": "fast and fully-featured autocomplete library", + "homepage": "http://twitter.github.com/typeahead.js", + "keywords": [ + "autocomplete", + "typeahead" + ], + "support": { + "issues": "https://github.com/twitter/typeahead.js/issues", + "source": "https://github.com/twitter/typeahead.js/tree/v0.11.1" + }, + "time": "2015-04-27T04:02:14+00:00" + } + ], + "packages-dev": [ + { + "name": "appium/php-client", + "version": "v0.3.0", + "source": { + "type": "git", + "url": "https://github.com/appium/php-client.git", + "reference": "3ae7666b198913952a407893a22d962280089dbe" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/appium/php-client/zipball/3ae7666b198913952a407893a22d962280089dbe", + "reference": "3ae7666b198913952a407893a22d962280089dbe", + "shasum": "" + }, + "require": { + "php": ">=5.3.0", + "phpunit/phpunit-selenium": ">=1.3.3" + }, + "type": "appium-php", + "autoload": { + "classmap": [ + "PHPUnit/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "include-path": [ + "" + ], + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Isaac Murchie", + "email": "isaac@saucelabs.com", + "homepage": "http://www.saucelabs.com", + "role": "Lead" + } + ], + "description": "PHP client for Selenium 3.0/Appium 1.0", + "homepage": "http://github.com/appium/appium-php", + "keywords": [ + "appium", + "phpunit", + "selenium" + ], + "support": { + "email": "help@saucelabs.com", + "irc": "irc://irc.freenode.org/saucelabs", + "issues": "https://github.com/appium/php-client/issues", + "source": "https://github.com/appium/php-client/tree/v0.3.0" + }, + "time": "2017-07-13T17:42:27+00:00" + }, + { + "name": "brianium/paratest", + "version": "v6.9.1", + "source": { + "type": "git", + "url": "https://github.com/paratestphp/paratest.git", + "reference": "51691208db882922c55d6c465be3e7d95028c449" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/paratestphp/paratest/zipball/51691208db882922c55d6c465be3e7d95028c449", + "reference": "51691208db882922c55d6c465be3e7d95028c449", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-pcre": "*", + "ext-reflection": "*", + "ext-simplexml": "*", + "fidry/cpu-core-counter": "^0.4.1 || ^0.5.1", + "jean85/pretty-package-versions": "^2.0.5", + "php": "^7.3 || ^8.0", + "phpunit/php-code-coverage": "^9.2.25", + "phpunit/php-file-iterator": "^3.0.6", + "phpunit/php-timer": "^5.0.3", + "phpunit/phpunit": "^9.6.4", + "sebastian/environment": "^5.1.5", + "symfony/console": "^5.4.21 || ^6.2.7", + "symfony/process": "^5.4.21 || ^6.2.7" + }, + "require-dev": { + "doctrine/coding-standard": "^10.0.0", + "ext-pcov": "*", + "ext-posix": "*", + "infection/infection": "^0.26.19", + "squizlabs/php_codesniffer": "^3.7.2", + "symfony/filesystem": "^5.4.21 || ^6.2.7", + "vimeo/psalm": "^5.7.7" + }, + "bin": [ + "bin/paratest", + "bin/paratest.bat", + "bin/paratest_for_phpstorm" + ], + "type": "library", + "autoload": { + "psr-4": { + "ParaTest\\": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Brian Scaturro", + "email": "scaturrob@gmail.com", + "role": "Developer" + }, + { + "name": "Filippo Tessarotto", + "email": "zoeslam@gmail.com", + "role": "Developer" + } + ], + "description": "Parallel testing for PHP", + "homepage": "https://github.com/paratestphp/paratest", + "keywords": [ + "concurrent", + "parallel", + "phpunit", + "testing" + ], + "support": { + "issues": "https://github.com/paratestphp/paratest/issues", + "source": "https://github.com/paratestphp/paratest/tree/v6.9.1" + }, + "funding": [ + { + "url": "https://github.com/sponsors/Slamdunk", + "type": "github" + }, + { + "url": "https://paypal.me/filippotessarotto", + "type": "paypal" + } + ], + "time": "2023-03-03T09:35:17+00:00" + }, + { + "name": "doctrine/instantiator", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/instantiator.git", + "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/c6222283fa3f4ac679f8b9ced9a4e23f163e80d0", + "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0", + "shasum": "" + }, + "require": { + "php": "^8.1" + }, + "require-dev": { + "doctrine/coding-standard": "^11", + "ext-pdo": "*", + "ext-phar": "*", + "phpbench/phpbench": "^1.2", + "phpstan/phpstan": "^1.9.4", + "phpstan/phpstan-phpunit": "^1.3", + "phpunit/phpunit": "^9.5.27", + "vimeo/psalm": "^5.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com", + "homepage": "https://ocramius.github.io/" + } + ], + "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", + "homepage": "https://www.doctrine-project.org/projects/instantiator.html", + "keywords": [ + "constructor", + "instantiate" + ], + "support": { + "issues": "https://github.com/doctrine/instantiator/issues", + "source": "https://github.com/doctrine/instantiator/tree/2.0.0" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator", + "type": "tidelift" + } + ], + "time": "2022-12-30T00:23:10+00:00" + }, + { + "name": "fidry/cpu-core-counter", + "version": "0.5.1", + "source": { + "type": "git", + "url": "https://github.com/theofidry/cpu-core-counter.git", + "reference": "b58e5a3933e541dc286cc91fc4f3898bbc6f1623" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/theofidry/cpu-core-counter/zipball/b58e5a3933e541dc286cc91fc4f3898bbc6f1623", + "reference": "b58e5a3933e541dc286cc91fc4f3898bbc6f1623", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "require-dev": { + "fidry/makefile": "^0.2.0", + "phpstan/extension-installer": "^1.2.0", + "phpstan/phpstan": "^1.9.2", + "phpstan/phpstan-deprecation-rules": "^1.0.0", + "phpstan/phpstan-phpunit": "^1.2.2", + "phpstan/phpstan-strict-rules": "^1.4.4", + "phpunit/phpunit": "^9.5.26 || ^8.5.31", + "theofidry/php-cs-fixer-config": "^1.0", + "webmozarts/strict-phpunit": "^7.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "Fidry\\CpuCoreCounter\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Théo FIDRY", + "email": "theo.fidry@gmail.com" + } + ], + "description": "Tiny utility to get the number of CPU cores.", + "keywords": [ + "CPU", + "core" + ], + "support": { + "issues": "https://github.com/theofidry/cpu-core-counter/issues", + "source": "https://github.com/theofidry/cpu-core-counter/tree/0.5.1" + }, + "funding": [ + { + "url": "https://github.com/theofidry", + "type": "github" + } + ], + "time": "2022-12-24T12:35:10+00:00" + }, + { + "name": "jean85/pretty-package-versions", + "version": "2.0.5", + "source": { + "type": "git", + "url": "https://github.com/Jean85/pretty-package-versions.git", + "reference": "ae547e455a3d8babd07b96966b17d7fd21d9c6af" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Jean85/pretty-package-versions/zipball/ae547e455a3d8babd07b96966b17d7fd21d9c6af", + "reference": "ae547e455a3d8babd07b96966b17d7fd21d9c6af", + "shasum": "" + }, + "require": { + "composer-runtime-api": "^2.0.0", + "php": "^7.1|^8.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^2.17", + "jean85/composer-provided-replaced-stub-package": "^1.0", + "phpstan/phpstan": "^0.12.66", + "phpunit/phpunit": "^7.5|^8.5|^9.4", + "vimeo/psalm": "^4.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Jean85\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Alessandro Lai", + "email": "alessandro.lai85@gmail.com" + } + ], + "description": "A library to get pretty versions strings of installed dependencies", + "keywords": [ + "composer", + "package", + "release", + "versions" + ], + "support": { + "issues": "https://github.com/Jean85/pretty-package-versions/issues", + "source": "https://github.com/Jean85/pretty-package-versions/tree/2.0.5" + }, + "time": "2021-10-08T21:21:46+00:00" + }, + { + "name": "myclabs/deep-copy", + "version": "1.11.1", + "source": { + "type": "git", + "url": "https://github.com/myclabs/DeepCopy.git", + "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", + "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "conflict": { + "doctrine/collections": "<1.6.8", + "doctrine/common": "<2.13.3 || >=3,<3.2.2" + }, + "require-dev": { + "doctrine/collections": "^1.6.8", + "doctrine/common": "^2.13.3 || ^3.2.2", + "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" + }, + "type": "library", + "autoload": { + "files": [ + "src/DeepCopy/deep_copy.php" + ], + "psr-4": { + "DeepCopy\\": "src/DeepCopy/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Create deep copies (clones) of your objects", + "keywords": [ + "clone", + "copy", + "duplicate", + "object", + "object graph" + ], + "support": { + "issues": "https://github.com/myclabs/DeepCopy/issues", + "source": "https://github.com/myclabs/DeepCopy/tree/1.11.1" + }, + "funding": [ + { + "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", + "type": "tidelift" + } + ], + "time": "2023-03-08T13:26:56+00:00" + }, + { + "name": "nikic/php-parser", + "version": "v4.15.4", + "source": { + "type": "git", + "url": "https://github.com/nikic/PHP-Parser.git", + "reference": "6bb5176bc4af8bcb7d926f88718db9b96a2d4290" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/6bb5176bc4af8bcb7d926f88718db9b96a2d4290", + "reference": "6bb5176bc4af8bcb7d926f88718db9b96a2d4290", + "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" + ], + "support": { + "issues": "https://github.com/nikic/PHP-Parser/issues", + "source": "https://github.com/nikic/PHP-Parser/tree/v4.15.4" + }, + "time": "2023-03-05T19:49:14+00:00" + }, + { + "name": "phar-io/manifest", + "version": "2.0.3", + "source": { + "type": "git", + "url": "https://github.com/phar-io/manifest.git", + "reference": "97803eca37d319dfa7826cc2437fc020857acb53" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/97803eca37d319dfa7826cc2437fc020857acb53", + "reference": "97803eca37d319dfa7826cc2437fc020857acb53", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-phar": "*", + "ext-xmlwriter": "*", + "phar-io/version": "^3.0.1", + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", + "support": { + "issues": "https://github.com/phar-io/manifest/issues", + "source": "https://github.com/phar-io/manifest/tree/2.0.3" + }, + "time": "2021-07-20T11:28:43+00:00" + }, + { + "name": "phar-io/version", + "version": "3.2.1", + "source": { + "type": "git", + "url": "https://github.com/phar-io/version.git", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Library for handling version information and constraints", + "support": { + "issues": "https://github.com/phar-io/version/issues", + "source": "https://github.com/phar-io/version/tree/3.2.1" + }, + "time": "2022-02-21T01:04:05+00:00" + }, + { + "name": "phing/phing", + "version": "2.17.4", + "source": { + "type": "git", + "url": "https://github.com/phingofficial/phing.git", + "reference": "9f3bc8c72e65452686dcf64497e02a082f138908" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phingofficial/phing/zipball/9f3bc8c72e65452686dcf64497e02a082f138908", + "reference": "9f3bc8c72e65452686dcf64497e02a082f138908", + "shasum": "" + }, + "require": { + "php": ">=5.2.0" + }, + "require-dev": { + "ext-pdo_sqlite": "*", + "mikey179/vfsstream": "^1.6", + "pdepend/pdepend": "2.x", + "pear/archive_tar": "1.4.x", + "pear/http_request2": "dev-trunk", + "pear/net_growl": "dev-trunk", + "pear/pear-core-minimal": "1.10.1", + "pear/versioncontrol_git": "@dev", + "pear/versioncontrol_svn": "~0.5", + "phpdocumentor/phpdocumentor": "2.x", + "phploc/phploc": "~2.0.6", + "phpmd/phpmd": "~2.2", + "phpunit/phpunit": ">=3.7", + "sebastian/git": "~1.0", + "sebastian/phpcpd": "2.x", + "siad007/versioncontrol_hg": "^1.0", + "simpletest/simpletest": "^1.1", + "squizlabs/php_codesniffer": "~2.2", + "symfony/yaml": "^2.8 || ^3.1 || ^4.0" + }, + "suggest": { + "pdepend/pdepend": "PHP version of JDepend", + "pear/archive_tar": "Tar file management class", + "pear/versioncontrol_git": "A library that provides OO interface to handle Git repository", + "pear/versioncontrol_svn": "A simple OO-style interface for Subversion, the free/open-source version control system", + "phpdocumentor/phpdocumentor": "Documentation Generator for PHP", + "phploc/phploc": "A tool for quickly measuring the size of a PHP project", + "phpmd/phpmd": "PHP version of PMD tool", + "phpunit/php-code-coverage": "Library that provides collection, processing, and rendering functionality for PHP code coverage information", + "phpunit/phpunit": "The PHP Unit Testing Framework", + "sebastian/phpcpd": "Copy/Paste Detector (CPD) for PHP code", + "siad007/versioncontrol_hg": "A library for interfacing with Mercurial repositories.", + "tedivm/jshrink": "Javascript Minifier built in PHP" + }, + "bin": [ + "bin/phing" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.16.x-dev" + } + }, + "autoload": { + "classmap": [ + "classes/phing/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "include-path": [ + "classes" + ], + "license": [ + "LGPL-3.0-only" + ], + "authors": [ + { + "name": "Michiel Rook", + "email": "mrook@php.net" + }, + { + "name": "Phing Community", + "homepage": "https://www.phing.info/trac/wiki/Development/Contributors" + } + ], + "description": "PHing Is Not GNU make; it's a PHP project build system or build tool based on Apache Ant.", + "homepage": "https://www.phing.info/", + "keywords": [ + "build", + "phing", + "task", + "tool" + ], + "support": { + "irc": "irc://irc.freenode.net/phing", + "issues": "https://www.phing.info/trac/report", + "source": "https://github.com/phingofficial/phing/tree/2.17.4" + }, + "funding": [ + { + "url": "https://github.com/mrook", + "type": "github" + }, + { + "url": "https://github.com/siad007", + "type": "github" + }, + { + "url": "https://www.patreon.com/michielrook", + "type": "patreon" + } + ], + "time": "2022-07-08T09:07:07+00:00" + }, + { + "name": "phpunit/php-code-coverage", + "version": "9.2.26", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "443bc6912c9bd5b409254a40f4b0f4ced7c80ea1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/443bc6912c9bd5b409254a40f4b0f4ced7c80ea1", + "reference": "443bc6912c9bd5b409254a40f4b0f4ced7c80ea1", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-libxml": "*", + "ext-xmlwriter": "*", + "nikic/php-parser": "^4.15", + "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.3", + "sebastian/version": "^3.0.1", + "theseer/tokenizer": "^1.2.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "suggest": { + "ext-pcov": "PHP extension that provides line coverage", + "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "9.2-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 that provides collection, processing, and rendering functionality for PHP code coverage information.", + "homepage": "https://github.com/sebastianbergmann/php-code-coverage", + "keywords": [ + "coverage", + "testing", + "xunit" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.26" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-03-06T12:58:08+00:00" + }, + { + "name": "phpunit/php-file-iterator", + "version": "3.0.6", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", + "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.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": "FilterIterator implementation that filters files based on a list of suffixes.", + "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", + "keywords": [ + "filesystem", + "iterator" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0.6" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2021-12-02T12:48:52+00:00" + }, + { + "name": "phpunit/php-invoker", + "version": "3.1.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-invoker.git", + "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/5a10147d0aaf65b58940a0b72f71c9ac0423cc67", + "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "ext-pcntl": "*", + "phpunit/phpunit": "^9.3" + }, + "suggest": { + "ext-pcntl": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1-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": "Invoke callables with a timeout", + "homepage": "https://github.com/sebastianbergmann/php-invoker/", + "keywords": [ + "process" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-invoker/issues", + "source": "https://github.com/sebastianbergmann/php-invoker/tree/3.1.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T05:58:55+00:00" + }, + { + "name": "phpunit/php-text-template", + "version": "2.0.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", + "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", + "shasum": "" + }, + "require": { + "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": "Simple template engine.", + "homepage": "https://github.com/sebastianbergmann/php-text-template/", + "keywords": [ + "template" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-text-template/issues", + "source": "https://github.com/sebastianbergmann/php-text-template/tree/2.0.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T05:33:50+00:00" + }, + { + "name": "phpunit/php-timer", + "version": "5.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", + "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.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": "Utility class for timing", + "homepage": "https://github.com/sebastianbergmann/php-timer/", + "keywords": [ + "timer" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-timer/issues", + "source": "https://github.com/sebastianbergmann/php-timer/tree/5.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T13:16:10+00:00" + }, + { + "name": "phpunit/phpunit", + "version": "9.6.5", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "86e761949019ae83f49240b2f2123fb5ab3b2fc5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/86e761949019ae83f49240b2f2123fb5ab3b2fc5", + "reference": "86e761949019ae83f49240b2f2123fb5ab3b2fc5", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.3.1 || ^2", + "ext-dom": "*", + "ext-json": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-xml": "*", + "ext-xmlwriter": "*", + "myclabs/deep-copy": "^1.10.1", + "phar-io/manifest": "^2.0.3", + "phar-io/version": "^3.0.2", + "php": ">=7.3", + "phpunit/php-code-coverage": "^9.2.13", + "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.8", + "sebastian/diff": "^4.0.3", + "sebastian/environment": "^5.1.3", + "sebastian/exporter": "^4.0.5", + "sebastian/global-state": "^5.0.1", + "sebastian/object-enumerator": "^4.0.3", + "sebastian/resource-operations": "^3.0.3", + "sebastian/type": "^3.2", + "sebastian/version": "^3.0.2" + }, + "suggest": { + "ext-soap": "To be able to generate mocks based on WSDL files", + "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" + }, + "bin": [ + "phpunit" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "9.6-dev" + } + }, + "autoload": { + "files": [ + "src/Framework/Assert/Functions.php" + ], + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "The PHP Unit Testing framework.", + "homepage": "https://phpunit.de/", + "keywords": [ + "phpunit", + "testing", + "xunit" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/phpunit/issues", + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.5" + }, + "funding": [ + { + "url": "https://phpunit.de/sponsors.html", + "type": "custom" + }, + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", + "type": "tidelift" + } + ], + "time": "2023-03-09T06:34:10+00:00" + }, + { + "name": "phpunit/phpunit-selenium", + "version": "9.0.1", + "source": { + "type": "git", + "url": "https://github.com/giorgiosironi/phpunit-selenium.git", + "reference": "41711edd4dfcc5a0db2f8a22da6d2ddc908da741" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/giorgiosironi/phpunit-selenium/zipball/41711edd4dfcc5a0db2f8a22da6d2ddc908da741", + "reference": "41711edd4dfcc5a0db2f8a22da6d2ddc908da741", + "shasum": "" + }, + "require": { + "ext-curl": "*", + "php": ">=7.3", + "phpunit/phpunit": ">=9.0,<10.0" + }, + "require-dev": { + "phing/phing": "2.*" + }, + "type": "library", + "autoload": { + "classmap": [ + "PHPUnit/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "include-path": [ + "" + ], + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Giorgio Sironi", + "email": "info@giorgiosironi.com", + "role": "developer" + }, + { + "name": "Ivan Kurnosov", + "email": "zerkms@zerkms.com", + "role": "developer" + }, + { + "name": "Paul Briton", + "role": "developer" + }, + { + "name": "Patrik Štrba", + "role": "developer" + }, + { + "name": "Petr Kotek", + "role": "developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "original developer" + } + ], + "description": "Selenium Server integration for PHPUnit", + "homepage": "https://github.com/giorgiosironi/phpunit-selenium", + "keywords": [ + "phpunit", + "selenium", + "testing", + "xunit" + ], + "support": { + "issues": "https://github.com/giorgiosironi/phpunit-selenium/issues", + "source": "https://github.com/giorgiosironi/phpunit-selenium/tree/9.0.1" + }, + "time": "2020-12-08T19:49:55+00:00" + }, + { + "name": "psr/container", + "version": "2.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "shasum": "" + }, + "require": { + "php": ">=7.4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", + "keywords": [ + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" + ], + "support": { + "issues": "https://github.com/php-fig/container/issues", + "source": "https://github.com/php-fig/container/tree/2.0.2" + }, + "time": "2021-11-05T16:47:00+00:00" + }, + { + "name": "sauce/sausage", + "version": "0.18.0", + "source": { + "type": "git", + "url": "https://github.com/jlipps/sausage.git", + "reference": "d189444a6eb85b3a846330d944575426812dc460" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/jlipps/sausage/zipball/d189444a6eb85b3a846330d944575426812dc460", + "reference": "d189444a6eb85b3a846330d944575426812dc460", + "shasum": "" + }, + "require": { + "appium/php-client": ">=0.1.0", + "brianium/paratest": ">=0.12.1", + "php": ">=5.4.0", + "phpunit/phpunit-selenium": ">=1.4.1", + "sauce/sausage-installer": ">=0.1.0" + }, + "require-dev": { + "phpunit/phpunit": ">=4.5.1" + }, + "suggest": { + "sauce/connect": ">=3.1" + }, + "bin": [ + "bin/sauce_config" + ], + "type": "sauce-sausage", + "autoload": { + "psr-0": { + "Sauce": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Jonathan Lipps", + "email": "jlipps@saucelabs.com", + "homepage": "http://www.saucelabs.com", + "role": "Lead" + } + ], + "description": "PHP version of the Sauce Labs API", + "homepage": "http://github.com/jlipps/sausage", + "keywords": [ + "Sauce", + "SauceLabs", + "api", + "appium", + "phpunit", + "selenium", + "testing" + ], + "support": { + "email": "help@saucelabs.com", + "irc": "irc://irc.freenode.org/saucelabs", + "issues": "https://github.com/jlipps/sausage/issues", + "source": "https://github.com/jlipps/sausage/tree/0.18.0" + }, + "time": "2019-06-19T21:12:38+00:00" + }, + { + "name": "sauce/sausage-installer", + "version": "v0.1.0", + "source": { + "type": "git", + "url": "https://github.com/jlipps/sausage-installer.git", + "reference": "5435cadb3ef1cec77218814af3c121b3556a5444" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/jlipps/sausage-installer/zipball/5435cadb3ef1cec77218814af3c121b3556a5444", + "reference": "5435cadb3ef1cec77218814af3c121b3556a5444", + "shasum": "" + }, + "type": "composer-installer", + "extra": { + "class": "Sauce\\Composer\\SausageInstaller" + }, + "autoload": { + "psr-0": { + "Sauce": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Jonathan Lipps", + "email": "jlipps@saucelabs.com", + "homepage": "http://www.saucelabs.com", + "role": "Lead" + } + ], + "homepage": "http://github.com/jlipps/sausage-installer", + "support": { + "issues": "https://github.com/jlipps/sausage-installer/issues", + "source": "https://github.com/jlipps/sausage-installer/tree/v0.1.0" + }, + "time": "2012-09-28T18:41:38+00:00" + }, + { + "name": "sebastian/cli-parser", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/cli-parser.git", + "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/442e7c7e687e42adc03470c7b668bc4b2402c0b2", + "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2", + "shasum": "" + }, + "require": { + "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 parsing CLI options", + "homepage": "https://github.com/sebastianbergmann/cli-parser", + "support": { + "issues": "https://github.com/sebastianbergmann/cli-parser/issues", + "source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T06:08:49+00:00" + }, + { + "name": "sebastian/code-unit", + "version": "1.0.8", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit.git", + "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/1fc9f64c0927627ef78ba436c9b17d967e68e120", + "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120", + "shasum": "" + }, + "require": { + "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": "Collection of value objects that represent the PHP code units", + "homepage": "https://github.com/sebastianbergmann/code-unit", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit/issues", + "source": "https://github.com/sebastianbergmann/code-unit/tree/1.0.8" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T13:08:54+00:00" + }, + { + "name": "sebastian/code-unit-reverse-lookup", + "version": "2.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", + "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", + "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", + "shasum": "" + }, + "require": { + "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" + } + ], + "description": "Looks up which function or method a line of code belongs to", + "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", + "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/2.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T05:30:19+00:00" + }, + { + "name": "sebastian/comparator", + "version": "4.0.8", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "fa0f136dd2334583309d32b62544682ee972b51a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/fa0f136dd2334583309d32b62544682ee972b51a", + "reference": "fa0f136dd2334583309d32b62544682ee972b51a", + "shasum": "" + }, + "require": { + "php": ">=7.3", + "sebastian/diff": "^4.0", + "sebastian/exporter": "^4.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + } + ], + "description": "Provides the functionality to compare PHP values for equality", + "homepage": "https://github.com/sebastianbergmann/comparator", + "keywords": [ + "comparator", + "compare", + "equality" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/comparator/issues", + "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.8" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2022-09-14T12:41:17+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", + "support": { + "issues": "https://github.com/sebastianbergmann/complexity/issues", + "source": "https://github.com/sebastianbergmann/complexity/tree/2.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T15:52:27+00:00" + }, + { + "name": "sebastian/diff", + "version": "4.0.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/3461e3fccc7cfdfc2720be910d3bd73c69be590d", + "reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3", + "symfony/process": "^4.2 || ^5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + } + ], + "description": "Diff implementation", + "homepage": "https://github.com/sebastianbergmann/diff", + "keywords": [ + "diff", + "udiff", + "unidiff", + "unified diff" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/diff/issues", + "source": "https://github.com/sebastianbergmann/diff/tree/4.0.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T13:10:38+00:00" + }, + { + "name": "sebastian/environment", + "version": "5.1.5", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", + "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "suggest": { + "ext-posix": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides functionality to handle HHVM/PHP environments", + "homepage": "http://www.github.com/sebastianbergmann/environment", + "keywords": [ + "Xdebug", + "environment", + "hhvm" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/environment/issues", + "source": "https://github.com/sebastianbergmann/environment/tree/5.1.5" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:03:51+00:00" + }, + { + "name": "sebastian/exporter", + "version": "4.0.5", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d", + "reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d", + "shasum": "" + }, + "require": { + "php": ">=7.3", + "sebastian/recursion-context": "^4.0" + }, + "require-dev": { + "ext-mbstring": "*", + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Provides the functionality to export PHP variables for visualization", + "homepage": "https://www.github.com/sebastianbergmann/exporter", + "keywords": [ + "export", + "exporter" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/exporter/issues", + "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.5" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2022-09-14T06:03:37+00:00" + }, + { + "name": "sebastian/global-state", + "version": "5.0.5", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/0ca8db5a5fc9c8646244e629625ac486fa286bf2", + "reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2", + "shasum": "" + }, + "require": { + "php": ">=7.3", + "sebastian/object-reflector": "^2.0", + "sebastian/recursion-context": "^4.0" + }, + "require-dev": { + "ext-dom": "*", + "phpunit/phpunit": "^9.3" + }, + "suggest": { + "ext-uopz": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Snapshotting of global state", + "homepage": "http://www.github.com/sebastianbergmann/global-state", + "keywords": [ + "global state" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/global-state/issues", + "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.5" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2022-02-14T08:28:10+00:00" + }, + { + "name": "sebastian/lines-of-code", + "version": "1.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/lines-of-code.git", + "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/c1c2e997aa3146983ed888ad08b15470a2e22ecc", + "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc", + "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", + "support": { + "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", + "source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-11-28T06:42:11+00:00" + }, + { + "name": "sebastian/object-enumerator", + "version": "4.0.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-enumerator.git", + "reference": "5c9eeac41b290a3712d88851518825ad78f45c71" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/5c9eeac41b290a3712d88851518825ad78f45c71", + "reference": "5c9eeac41b290a3712d88851518825ad78f45c71", + "shasum": "" + }, + "require": { + "php": ">=7.3", + "sebastian/object-reflector": "^2.0", + "sebastian/recursion-context": "^4.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Traverses array structures and object graphs to enumerate all referenced objects", + "homepage": "https://github.com/sebastianbergmann/object-enumerator/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", + "source": "https://github.com/sebastianbergmann/object-enumerator/tree/4.0.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T13:12:34+00:00" + }, + { + "name": "sebastian/object-reflector", + "version": "2.0.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-reflector.git", + "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", + "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", + "shasum": "" + }, + "require": { + "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" + } + ], + "description": "Allows reflection of object attributes, including inherited and non-public ones", + "homepage": "https://github.com/sebastianbergmann/object-reflector/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-reflector/issues", + "source": "https://github.com/sebastianbergmann/object-reflector/tree/2.0.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T13:14:26+00:00" + }, + { + "name": "sebastian/recursion-context", + "version": "4.0.5", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", + "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides functionality to recursively process PHP variables", + "homepage": "https://github.com/sebastianbergmann/recursion-context", + "support": { + "issues": "https://github.com/sebastianbergmann/recursion-context/issues", + "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.5" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:07:39+00:00" + }, + { + "name": "sebastian/resource-operations", + "version": "3.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/resource-operations.git", + "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", + "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides a list of PHP built-in functions that operate on resources", + "homepage": "https://www.github.com/sebastianbergmann/resource-operations", + "support": { + "issues": "https://github.com/sebastianbergmann/resource-operations/issues", + "source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T06:45:17+00:00" + }, + { + "name": "sebastian/type", + "version": "3.2.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/type.git", + "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", + "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.2-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": "Collection of value objects that represent the types of the PHP type system", + "homepage": "https://github.com/sebastianbergmann/type", + "support": { + "issues": "https://github.com/sebastianbergmann/type/issues", + "source": "https://github.com/sebastianbergmann/type/tree/3.2.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:13:03+00:00" + }, + { + "name": "sebastian/version", + "version": "3.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "c6c1022351a901512170118436c764e473f6de8c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c6c1022351a901512170118436c764e473f6de8c", + "reference": "c6c1022351a901512170118436c764e473f6de8c", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.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 that helps with managing the version number of Git-hosted PHP projects", + "homepage": "https://github.com/sebastianbergmann/version", + "support": { + "issues": "https://github.com/sebastianbergmann/version/issues", + "source": "https://github.com/sebastianbergmann/version/tree/3.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T06:39:44+00:00" + }, + { + "name": "symfony/console", + "version": "v6.2.7", + "source": { + "type": "git", + "url": "https://github.com/symfony/console.git", + "reference": "cbad09eb8925b6ad4fb721c7a179344dc4a19d45" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/console/zipball/cbad09eb8925b6ad4fb721c7a179344dc4a19d45", + "reference": "cbad09eb8925b6ad4fb721c7a179344dc4a19d45", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/polyfill-mbstring": "~1.0", + "symfony/service-contracts": "^1.1|^2|^3", + "symfony/string": "^5.4|^6.0" + }, + "conflict": { + "symfony/dependency-injection": "<5.4", + "symfony/dotenv": "<5.4", + "symfony/event-dispatcher": "<5.4", + "symfony/lock": "<5.4", + "symfony/process": "<5.4" + }, + "provide": { + "psr/log-implementation": "1.0|2.0|3.0" + }, + "require-dev": { + "psr/log": "^1|^2|^3", + "symfony/config": "^5.4|^6.0", + "symfony/dependency-injection": "^5.4|^6.0", + "symfony/event-dispatcher": "^5.4|^6.0", + "symfony/lock": "^5.4|^6.0", + "symfony/process": "^5.4|^6.0", + "symfony/var-dumper": "^5.4|^6.0" + }, + "suggest": { + "psr/log": "For using the console logger", + "symfony/event-dispatcher": "", + "symfony/lock": "", + "symfony/process": "" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Console\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Eases the creation of beautiful and testable command line interfaces", + "homepage": "https://symfony.com", + "keywords": [ + "cli", + "command line", + "console", + "terminal" + ], + "support": { + "source": "https://github.com/symfony/console/tree/v6.2.7" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-02-25T17:00:03+00:00" + }, + { + "name": "symfony/deprecation-contracts", + "version": "v3.2.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/deprecation-contracts.git", + "reference": "e2d1534420bd723d0ef5aec58a22c5fe60ce6f5e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/e2d1534420bd723d0ef5aec58a22c5fe60ce6f5e", + "reference": "e2d1534420bd723d0ef5aec58a22c5fe60ce6f5e", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.3-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "files": [ + "function.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "A generic function and convention to trigger deprecation notices", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.2.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-03-01T10:25:55+00:00" + }, + { + "name": "symfony/polyfill-ctype", + "version": "v1.27.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "5bbc823adecdae860bb64756d639ecfec17b050a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/5bbc823adecdae860bb64756d639ecfec17b050a", + "reference": "5bbc823adecdae860bb64756d639ecfec17b050a", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "provide": { + "ext-ctype": "*" + }, + "suggest": { + "ext-ctype": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.27-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Ctype\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for ctype functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "ctype", + "polyfill", + "portable" + ], + "support": { + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.27.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-11-03T14:55:06+00:00" + }, + { + "name": "symfony/polyfill-intl-grapheme", + "version": "v1.27.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-grapheme.git", + "reference": "511a08c03c1960e08a883f4cffcacd219b758354" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/511a08c03c1960e08a883f4cffcacd219b758354", + "reference": "511a08c03c1960e08a883f4cffcacd219b758354", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.27-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Grapheme\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's grapheme_* functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "grapheme", + "intl", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.27.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-11-03T14:55:06+00:00" + }, + { + "name": "symfony/polyfill-intl-normalizer", + "version": "v1.27.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-normalizer.git", + "reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/19bd1e4fcd5b91116f14d8533c57831ed00571b6", + "reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.27-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Normalizer\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's Normalizer class and related functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "intl", + "normalizer", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.27.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-11-03T14:55:06+00:00" + }, + { + "name": "symfony/polyfill-mbstring", + "version": "v1.27.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/8ad114f6b39e2c98a8b0e3bd907732c207c2b534", + "reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "provide": { + "ext-mbstring": "*" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.27-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.27.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-11-03T14:55:06+00:00" + }, + { + "name": "symfony/process", + "version": "v6.2.7", + "source": { + "type": "git", + "url": "https://github.com/symfony/process.git", + "reference": "680e8a2ea6b3f87aecc07a6a65a203ae573d1902" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/process/zipball/680e8a2ea6b3f87aecc07a6a65a203ae573d1902", + "reference": "680e8a2ea6b3f87aecc07a6a65a203ae573d1902", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Process\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Executes commands in sub-processes", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/process/tree/v6.2.7" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-02-24T10:42:00+00:00" + }, + { + "name": "symfony/service-contracts", + "version": "v3.2.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/service-contracts.git", + "reference": "a8c9cedf55f314f3a186041d19537303766df09a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/a8c9cedf55f314f3a186041d19537303766df09a", + "reference": "a8c9cedf55f314f3a186041d19537303766df09a", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/container": "^2.0" + }, + "conflict": { + "ext-psr": "<1.1|>=2" + }, + "suggest": { + "symfony/service-implementation": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.3-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Service\\": "" + }, + "exclude-from-classmap": [ + "/Test/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to writing services", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/service-contracts/tree/v3.2.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-03-01T10:32:47+00:00" + }, + { + "name": "symfony/string", + "version": "v6.2.7", + "source": { + "type": "git", + "url": "https://github.com/symfony/string.git", + "reference": "67b8c1eec78296b85dc1c7d9743830160218993d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/string/zipball/67b8c1eec78296b85dc1c7d9743830160218993d", + "reference": "67b8c1eec78296b85dc1c7d9743830160218993d", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-intl-grapheme": "~1.0", + "symfony/polyfill-intl-normalizer": "~1.0", + "symfony/polyfill-mbstring": "~1.0" + }, + "conflict": { + "symfony/translation-contracts": "<2.0" + }, + "require-dev": { + "symfony/error-handler": "^5.4|^6.0", + "symfony/http-client": "^5.4|^6.0", + "symfony/intl": "^6.2", + "symfony/translation-contracts": "^2.0|^3.0", + "symfony/var-exporter": "^5.4|^6.0" + }, + "type": "library", + "autoload": { + "files": [ + "Resources/functions.php" + ], + "psr-4": { + "Symfony\\Component\\String\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way", + "homepage": "https://symfony.com", + "keywords": [ + "grapheme", + "i18n", + "string", + "unicode", + "utf-8", + "utf8" + ], + "support": { + "source": "https://github.com/symfony/string/tree/v6.2.7" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-02-24T10:42:00+00:00" + }, + { + "name": "theseer/tokenizer", + "version": "1.2.1", + "source": { + "type": "git", + "url": "https://github.com/theseer/tokenizer.git", + "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/34a41e998c2183e22995f158c581e7b5e755ab9e", + "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": "^7.2 || ^8.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + } + ], + "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", + "support": { + "issues": "https://github.com/theseer/tokenizer/issues", + "source": "https://github.com/theseer/tokenizer/tree/1.2.1" + }, + "funding": [ + { + "url": "https://github.com/theseer", + "type": "github" + } + ], + "time": "2021-07-28T10:34:58+00:00" + } + ], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": { + "ext-gd": "*", + "ext-xml": "*", + "ext-xmlwriter": "*", + "ext-intl": "*", + "ext-json": "*", + "ext-pdo_sqlite": "*", + "ext-mbstring": "*" + }, + "platform-dev": [], + "plugin-api-version": "2.3.0" +} diff --git a/config.php b/config.php index 051943699..650f315e6 100644 --- a/config.php +++ b/config.php @@ -6,7 +6,24 @@ * @author Sébastien Lucas */ - require_once 'config_default.php'; - if (file_exists('config_local.php')) - require_once 'config_local.php'; -?> \ No newline at end of file +require_once dirname(__FILE__) . '/vendor/autoload.php'; +require dirname(__FILE__) . '/config_default.php'; +if (file_exists(dirname(__FILE__) . '/config_local.php') && (php_sapi_name() !== 'cli')) { + require dirname(__FILE__) . '/config_local.php'; +} +/** @var array $config */ + +$remote_user = array_key_exists('PHP_AUTH_USER', $_SERVER) ? $_SERVER['PHP_AUTH_USER'] : ''; +// Clean username, only allow a-z, A-Z, 0-9, -_ chars +$remote_user = preg_replace('/[^a-zA-Z0-9_-]/', '', $remote_user); +$user_config_file = 'config_local.' . $remote_user . '.php'; +if (file_exists(dirname(__FILE__) . '/' . $user_config_file) && (php_sapi_name() !== 'cli')) { + require dirname(__FILE__) . '/' . $user_config_file; +} +require_once 'verifyLogin.php'; +if (!verifyLogin()) { + header('WWW-Authenticate: Basic realm="COPS Authentication"'); + header('HTTP/1.0 401 Unauthorized'); + echo 'This site is password protected'; + exit; +} diff --git a/config_default.php b/config_default.php index 36d7a98e9..be01e8436 100644 --- a/config_default.php +++ b/config_default.php @@ -3,165 +3,344 @@ * COPS (Calibre OPDS PHP Server) class file * * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) - * @author Sbastien Lucas - */ - - if (!isset($config)) - $config = array(); - - /* - * The directory containing calibre's metadata.db file, with sub-directories - * containing all the formats. - * BEWARE : it has to end with a / - */ - $config['calibre_directory'] = './feedbook/'; - - /* - * SPECIFIC TO NGINX - * The internal directory set in nginx config file - * Leave empty if you don't know what you're doing - */ - $config['calibre_internal_directory'] = ''; - - /* - * Full URL prefix (with trailing /) - * usefull especially for Opensearch where a full URL is sometimes required - * For example Mantano requires it. - */ - $config['cops_full_url'] = ''; - - /* - * Number of recent books to show - */ - $config['cops_recentbooks_limit'] = '50'; - - /* - * Catalog's title - */ - $config['cops_title_default'] = "COPS"; - - /* - * Catalog's subtitle - */ - $config['cops_subtitle_default'] = ""; - - /* - * Wich header to use when downloading books outside the web directory - * Possible values are : - * X-Accel-Redirect : For Nginx - * X-Sendfile : For Lightttpd or Apache (with mod_xsendfile) - * No value (default) : Let PHP handle the download - */ - $config['cops_x_accel_redirect'] = ""; - - /* - * Height of thumbnail image for OPDS - */ - $config['cops_opds_thumbnail_height'] = "70"; - - /* - * Height of thumbnail image for HTML - */ - $config['cops_html_thumbnail_height'] = "70"; - - /* - * Icon for both OPDS and HTML catalog - * Note that this has to be a real icon (.ico) - */ - $config['cops_icon'] = "favicon.ico"; - - /* - * Show icon for authors, series, tags and books on OPDS feed - * 1 : enable - * 0 : disable - */ - $config['cops_show_icons'] = "1"; - - /* - * Default timezone - * Check following link for other timezones : - * http://www.php.net/manual/en/timezones.php - */ - $config['default_timezone'] = "Europe/Paris"; - - /* - * Prefered format for HTML catalog - * The two first will be displayed in book entries - * The other only appear in book detail - */ - $config['cops_prefered_format'] = array ("EPUB", "PDF", "MOBI", "CBR", "CBZ"); - - /* - * use URL rewriting for downloading of ebook in HTML catalog - * See README for more information - * 1 : enable - * 0 : disable - */ - $config['cops_use_url_rewriting'] = "0"; - - /* - * generate a invalid OPDS stream to allow bad OPDS client to use search - * Example of non compliant OPDS client : FBReader (was working in May 2012), Moon+ Reader - * Example of good OPDS client : Mantano - * 1 : enable support for non compliant OPDS client - * 0 : always generate valid OPDS code - */ - $config['cops_generate_invalid_opds_stream'] = "0"; - - /* - * Max number of items per page - * -1 unlimited - */ - $config['cops_max_item_per_page'] = "-1"; - - /* - * split authors by first letter - * 1 : Yes - * 0 : No - */ - $config['cops_author_split_first_letter'] = "1"; - - /* - * Enable of Fancyapps (for popups) - * 1 : Yes (enable) - * 0 : No - */ - $config['cops_use_fancyapps'] = "1"; - - /* - * Update Epub metadata before download - * 1 : Yes (enable) - * 0 : No - */ - $config['cops_update_epub-metadata'] = "0"; - - /* - * Filter on tags to book list - * Only works with the OPDS catalog for now - * Usage : array ("I only want to see books using the tag : Tag1" => "Tag1", - * "I only want to see books not using the tag : Tag1" => "!Tag1", - * "I want to see every books" => "", - * - * Example : array ("All" => "", "Unread" => "!Read", "Read" => "Read") - */ - $config['cops_books_filter'] = array (); - - /* - * Custom Columns to add as an array containing the lookup names - * configured in Calibre - * - * For example : array ("genre", "mycolumn"); - * - * Note that for now only the first, second and forth type of custom columns are supported - */ - $config['cops_calibre_custom_column'] = array (); - - /* - * Rename .epub to .kepub.epub if downloaded from a Kobo eReader - * The ebook will then be recognized a Kepub so with chaptered paging, statistics, ... - * You have to enable URL rewriting if you want to enable kepup.epub download - * 1 : Yes (enable) - * 0 : No - */ - $config['cops_provide_kepub'] = "0"; -?> \ No newline at end of file + * @author Sébastien Lucas + */ + +if (!isset($config)) { + $config = []; +} + +/* + * The directory containing calibre's metadata.db file, with sub-directories + * containing all the formats. + * BEWARE : it has to end with a / + * You can enable multiple database with this notation instead of a simple string : + * $config['calibre_directory'] = array ("My database name" => "/home/directory/calibre1/", "My other database name" => "/home/directory/calibre2/"); + */ +$config['calibre_directory'] = './'; + +/* + * SPECIFIC TO NGINX + * The internal directory set in nginx config file + * Leave empty if you don't know what you're doing + */ +$config['calibre_internal_directory'] = ''; + +/* + * Full URL prefix (with trailing /) + * useful especially for Opensearch where a full URL is often required + * For example Mantano, Aldiko and Marvin require it. + */ +$config['cops_full_url'] = ''; + +/* + * Number of recent books to show + */ +$config['cops_recentbooks_limit'] = '50'; + +/* + * Catalog's author name + */ +$config['cops_author_name'] = 'Sébastien Lucas'; + +/* + * Catalog's author uri + */ +$config['cops_author_uri'] = 'http://blog.slucas.fr'; + +/* + * Catalog's author email + */ +$config['cops_author_email'] = 'sebastien@slucas.fr'; + +/* + * Catalog's title + */ +$config['cops_title_default'] = 'COPS'; + +/* + * Catalog's subtitle + */ +$config['cops_subtitle_default'] = ''; + +/* + * Wich header to use when downloading books outside the web directory + * Possible values are : + * X-Accel-Redirect : For Nginx + * X-Sendfile : For Lightttpd or Apache (with mod_xsendfile) + * No value (default) : Let PHP handle the download + */ +$config['cops_x_accel_redirect'] = ''; + +/* + * Height of thumbnail image for OPDS + */ +$config['cops_opds_thumbnail_height'] = '164'; + +/* + * Height of thumbnail image for HTML + */ +$config['cops_html_thumbnail_height'] = '225'; + +/* + * Icon for both OPDS and HTML catalog + * Note that this has to be a real icon (.ico) + */ +$config['cops_icon'] = 'favicon.ico'; + +/* + * Show icon for authors, series, tags and books on OPDS feed + * 1 : enable + * 0 : disable + */ +$config['cops_show_icons'] = '1'; + +/* + * Default timezone + * Check following link for other timezones : + * http://www.php.net/manual/en/timezones.php + */ +$config['default_timezone'] = 'Europe/Paris'; + +/* + * Prefered format for HTML catalog + * The two first will be displayed in book entries + * The other only appear in book detail + */ +$config['cops_prefered_format'] = ['EPUB', 'PDF', 'AZW3', 'AZW', 'MOBI', 'CBR', 'CBZ']; + +/* + * Specify the ignored formats that will never display in COPS + */ +$config['cops_ignored_formats'] = []; + +/* + * use URL rewriting for downloading of ebook in HTML catalog + * See Github wiki for more information + * 1 : enable + * 0 : disable + */ +$config['cops_use_url_rewriting'] = '0'; + +/* + * generate a invalid OPDS stream to allow bad OPDS client to use search + * Example of non compliant OPDS client : Moon+ Reader + * Example of good OPDS client : Mantano, FBReader + * 1 : enable support for non compliant OPDS client + * 0 : always generate valid OPDS code + */ +$config['cops_generate_invalid_opds_stream'] = '0'; + +/* + * Max number of items per page + * -1 unlimited + */ +$config['cops_max_item_per_page'] = '48'; + +/* + * split authors by first letter + * 1 : Yes + * 0 : No + */ +$config['cops_author_split_first_letter'] = '1'; + +/* + * split titles by first letter + * 1 : Yes + * 0 : No + */ +$config['cops_titles_split_first_letter'] = '1'; + +/* + * Enable the Lightboxes (for popups) + * 1 : Yes (enable) + * 0 : No + */ +$config['cops_use_fancyapps'] = '1'; + +/* + * Update Epub metadata before download + * 1 : Yes (enable) + * 0 : No + */ +$config['cops_update_epub-metadata'] = '0'; + +/* + * Filter on tags to book list + * Only works with the OPDS catalog + * Usage : array ("I only want to see books using the tag : Tag1" => "Tag1", + * "I only want to see books not using the tag : Tag1" => "!Tag1", + * "I want to see every books" => "", + * + * Example : array ("All" => "", "Unread" => "!Read", "Read" => "Read") + */ +$config['cops_books_filter'] = []; + +/* + * Custom Columns for the index page + * to add as an array containing the lookup names configured in Calibre + * + * For example : array ("genre", "mycolumn"); + * + * Note that the composite custom columns are not supported + */ +$config['cops_calibre_custom_column'] = []; + +/* + * Custom Columns for the list representation + * to add as an array containing the lookup names configured in Calibre + * + * For example : array ("genre", "mycolumn"); + * + * Note that the composite custom columns are not supported + */ +$config['cops_calibre_custom_column_list'] = []; + +/* + * Custom Columns for the book preview panel + * to add as an array containing the lookup names configured in Calibre + * + * For example : array ("genre", "mycolumn"); + * + * Note that the composite custom columns are not supported + */ +$config['cops_calibre_custom_column_preview'] = []; + +/* + * Rename .epub to .kepub.epub if downloaded from a Kobo eReader + * The ebook will then be recognized a Kepub so with chaptered paging, statistics, ... + * You have to enable URL rewriting if you want to enable kepup.epub download + * 1 : Yes (enable) + * 0 : No + */ +$config['cops_provide_kepub'] = '0'; + +/* + * Enable and configure Send To Kindle (or Email) feature. + * + * Don't forget to authorize the sender email you configured in your Kindle's Approved Personal Document E-mail List. + * + * If you want to use a simple smtp server (provided by your ISP for example), you can configure it like that : + * $config['cops_mail_configuration'] = array( "smtp.host" => "smtp.free.fr", + * "smtp.username" => "", + * "smtp.password" => "", + * "smtp.secure" => "", + * "smtp.port" => "", // Not mandatory, if smtp.secure is set then defaults to 465 + * "address.from" => "cops@slucas.fr", + * "subject" => "Sent by COPS : " // Not mandatory + * ); + * + * For Gmail (ssl is mandatory) : + * $config['cops_mail_configuration'] = array( "smtp.host" => "smtp.gmail.com", + * "smtp.username" => "YOUR GMAIL ADRESS", + * "smtp.password" => "YOUR GMAIL PASSWORD", + * "smtp.secure" => "ssl", + * "address.from" => "cops@slucas.fr" + * ); + * + * For GMX (tls and 587 is mandatory) : + * $config['cops_mail_configuration'] = array( "smtp.host" => "mail.gmx.com", + * "smtp.username" => "YOUR GMX ADRESS", + * "smtp.password" => "YOUR GMX PASSWORD", + * "smtp.secure" => "tls", + * "smtp.port" => "587", + * "address.from" => "cops@slucas.fr" + * ); + */ +$config['cops_mail_configuration'] = null; + +/* + * Use filter in HTML catalog + * 1 : Yes (enable) + * 0 : No + */ +$config['cops_html_tag_filter'] = '0'; + +/* + * Thumbnails are generated on-the-fly so it can be problematic on servers with slow CPU (Raspberry Pi, Dockstar, Piratebox, ...). + * This configuration item allow to customize how thumbnail will be generated + * "" : Generate thumbnail (CPU hungry) + * "1" : always send the full size image (Network hungry) + * any url : Send a constant image as the thumbnail (you can try "images/bookcover.png") + */ +$config['cops_thumbnail_handling'] = ''; + +/* + * Directory to keep resized thumbnails: allow to resize thumbnails only on first access, then use this cache. + * $config['cops_thumbnail_handling'] must be "" + * "" : don't cache thumbnail + * "/tmp/cache/" (example) : will generate thumbnails in /tmp/cache/ + * BEWARE : it has to end with a / + */ +$config['cops_thumbnail_cache_directory'] = ''; + +/* + * Contains a list of user agent for browsers not compatible with client side rendering + * For now : Kindle, Sony PRS-T1, Sony PRS-T2, All Cybook devices (maybe a little extreme). + * This item is used as regular expression so "." will force server side rendering for all devices + */ +$config['cops_server_side_render'] = 'Kindle\/1\.0|Kindle\/2\.0|Kindle\/3\.0|EBRD1101|EBRD1201|cybook'; + +/* + * Specify the ignored categories for the home screen and with search + * Meaning that if you don't want to search in publishers or tags just add them from the list + * Only accepted values : + * - author + * - book + * - series + * - tag + * - publisher + * - rating + * - language + */ +$config ['cops_ignored_categories'] = []; + +/* + * If you use a Sony eReader or Aldiko you can't download ebooks if your catalog + * is password protected. A simple workaround is to leave fetch.php not protected (see .htaccess). + * But In that case your COPS installation is not completely safe. + * Setting this parameter to "1" ensure that nobody can access fetch.php before accessing + * index.php or feed.php first. + * BEWARE : Do not touch this if you're not using password, not using PRS-TX or not using Aldiko. + */ +$config ['cops_fetch_protect'] = '0'; + +/* + * WARNING NOT READY FOR PRODUCTION USE + * Make the search better (don't care about diacritics, uppercase should work on Cyrillic) but slower. + * 1 : Yes (enable) + * 0 : No + */ +$config ['cops_normalized_search'] = '0'; + +/* + * Enable PHP password protection (You can use if htpasswd is not possible for you) + * If possible prefer htpasswd ! + * array( "username" => "xxx", "password" => "secret") : Enable PHP password protection + * NULL : Disable PHP password protection (You can still use htpasswd) + */ +$config['cops_basic_authentication'] = null; + +/* + * Which template is used by default : + * 'default' + * 'bootstrap' + * 'bootstrap2' + */ +$config['cops_template'] = 'bootstrap2'; + +/* + * Which style is used by default : + * 'base' + * 'default' + * 'eink' (only available for the 'default' template) + * 'iphone' (only available for the 'default' template) + * 'iphone7' (only available for the 'default' template) + */ +$config['cops_style'] = 'default'; + +/* + * Set language code to force a language (see lang/ directory for available languages). + * When empty it will auto detect the language. + */ +$config['cops_language'] = ''; diff --git a/config_local.php.example b/config_local.php.example index 0e8b295d8..460389296 100644 --- a/config_local.php.example +++ b/config_local.php.example @@ -1,19 +1,28 @@ \ No newline at end of file + + /* + * Specify the ignored formats that will never display in COPS + */ + $config['cops_ignored_formats'] = ['ORIGINAL_EPUB', 'ORIGINAL_AZW3']; diff --git a/customcolumn.php b/customcolumn.php deleted file mode 100644 index 421804092..000000000 --- a/customcolumn.php +++ /dev/null @@ -1,109 +0,0 @@ - - */ - -require_once('base.php'); - -class CustomColumn extends Base { - const ALL_CUSTOMS_ID = "calibre:custom"; - - public $id; - public $name; - public $customId; - - public function __construct($pid, $pname, $pcustomId) { - $this->id = $pid; - $this->name = $pname; - $this->customId = $pcustomId; - } - - public function getUri () { - return "?page=".parent::PAGE_CUSTOM_DETAIL."&custom={$this->customId}&id={$this->id}"; - } - - public function getEntryId () { - return self::ALL_CUSTOMS_ID.":".$this->customId.":".$this->id; - } - - public static function getTableName ($customId) { - return "custom_column_{$customId}"; - } - - public static function getTableLinkName ($customId) { - return "books_custom_column_{$customId}_link"; - } - - public static function getTableLinkColumn ($customId) { - return "value"; - } - - public static function getAllCustomsId ($customId) { - return self::ALL_CUSTOMS_ID . ":" . $customId; - } - - public static function getUriAllCustoms ($customId) { - return "?page=" . parent::PAGE_ALL_CUSTOMS . "&custom={$customId}"; - } - - public static function getAllTitle ($customId) { - $result = parent::getDb ()->prepare('select name from custom_columns where id = ?'); - $result->execute (array ($customId)); - $post = $result->fetchObject (); - return $post->name; - } - - public static function getCustomId ($lookup) { - $result = parent::getDb ()->prepare('select id from custom_columns where label = ?'); - $result->execute (array ($lookup)); - if ($post = $result->fetchObject ()) { - return $post->id; - } - return NULL; - } - - public static function getCount($customId) { - $nCustoms = parent::getDb ()->query('select count(*) from ' . self::getTableName ($customId))->fetchColumn(); - $entry = new Entry (self::getAllTitle ($customId), self::getAllCustomsId ($customId), - str_format (localize("tags.alphabetical"), $nCustoms), "text", - array ( new LinkNavigation (self::getUriAllCustoms ($customId)))); - return $entry; - } - - public static function getCustomById ($customId, $id) { - $test = 'select id, value as name from ' . self::getTableName ($customId) . ' where id = ?'; - $result = parent::getDb ()->prepare('select id, value as name from ' . self::getTableName ($customId) . ' where id = ?'); - $result->execute (array ($id)); - if ($post = $result->fetchObject ()) { - return new CustomColumn ($post->id, $post->name, $customId); - } - return NULL; - } - - public static function getAllCustoms($customId) { - $test = str_format ("{0} - {1} - {2}", self::getTableName ($customId), self::getTableLinkName ($customId), self::getTableLinkColumn ($customId)); - $test = str_format ('select {0}.id as id, {0}.value as name, count(*) as count -from {0}, {1} -where {0}.id = {1}.{2} -group by {0}.id, {0}.value -order by {0}.value', self::getTableName ($customId), self::getTableLinkName ($customId), self::getTableLinkColumn ($customId)); - $result = parent::getDb ()->query(str_format ('select {0}.id as id, {0}.value as name, count(*) as count -from {0}, {1} -where {0}.id = {1}.{2} -group by {0}.id, {0}.value -order by {0}.value', self::getTableName ($customId), self::getTableLinkName ($customId), self::getTableLinkColumn ($customId))); - $entryArray = array(); - while ($post = $result->fetchObject ()) - { - $customColumn = new CustomColumn ($post->id, $post->name, $customId); - array_push ($entryArray, new Entry ($customColumn->name, $customColumn->getEntryId (), - str_format (localize("bookword", $post->count), $post->count), "text", - array ( new LinkNavigation ($customColumn->getUri ())))); - } - return $entryArray; - } -} -?> \ No newline at end of file diff --git a/data.php b/data.php deleted file mode 100644 index cdd05d559..000000000 --- a/data.php +++ /dev/null @@ -1,133 +0,0 @@ - - */ - -require_once('base.php'); - -class Data extends Base { - public $id; - public $name; - public $format; - public $realFormat; - public $extension; - public $book; - - public static $mimetypes = array( - 'azw' => 'application/x-mobipocket-ebook', - 'azw3' => 'application/x-mobipocket-ebook', - 'cbz' => 'application/x-cbz', - 'cbr' => 'application/x-cbr', - 'doc' => 'application/msword', - 'epub' => 'application/epub+zip', - 'fb2' => 'text/fb2+xml', - 'kobo' => 'application/x-koboreader-ebook', - 'mobi' => 'application/x-mobipocket-ebook', - 'lit' => 'application/x-ms-reader', - 'lrs' => 'text/x-sony-bbeb+xml', - 'lrf' => 'application/x-sony-bbeb', - 'lrx' => 'application/x-sony-bbeb', - 'ncx' => 'application/x-dtbncx+xml', - 'opf' => 'application/oebps-package+xml', - 'otf' => 'application/x-font-opentype', - 'pdb' => 'application/vnd.palm', - 'pdf' => 'application/pdf', - 'prc' => 'application/x-mobipocket-ebook', - 'rtf' => 'application/rtf', - 'svg' => 'image/svg+xml', - 'ttf' => 'application/x-font-truetype', - 'wmf' => 'image/wmf', - 'xhtml' => 'application/xhtml+xml', - 'xpgt' => 'application/adobe-page-template+xml', - 'zip' => 'application/zip' - ); - - public function __construct($post, $book = null) { - $this->id = $post->id; - $this->name = $post->name; - $this->format = $post->format; - $this->realFormat = str_replace ("ORIGINAL_", "", $post->format); - $this->extension = strtolower ($this->realFormat); - $this->book = $book; - } - - public function isKnownType () { - return array_key_exists ($this->extension, self::$mimetypes); - } - - public function getMimeType () { - if ($this->isKnownType ()) { - return self::$mimetypes [$this->extension]; - } else { - return "application/octet-stream"; - } - } - - public function getFilename () { - return $this->name . "." . strtolower ($this->format); - } - - public function getUpdatedFilename () { - return $this->book->getAuthorsName () . " - " . $this->book->title; - } - - public function getUpdatedFilenameEpub () { - return $this->getUpdatedFilename () . ".epub"; - } - - public function getUpdatedFilenameKepub () { - return $this->getUpdatedFilename () . ".kepub.epub"; - } - - public function getDataLink ($rel, $title = NULL) { - return self::getLink ($this->book, $this->extension, $this->getMimeType (), $rel, $this->getFilename (), $this->id, $title); - } - - public function getLocalPath () { - return $this->book->path . "/" . $this->getFilename (); - } - - public function getHtmlLink () { - global $config; - - if ($config['cops_use_url_rewriting'] == "1") - { - if ($config['cops_provide_kepub'] == "1" && preg_match("/Kobo/", $_SERVER['HTTP_USER_AGENT'])) { - return "download/" . $this->id . "/" . urlencode ($this->getUpdatedFilenameKepub ()); - } else { - return "download/" . $this->id . "/" . urlencode ($this->getFilename ()); - } - } - else - { - return str_replace ("&", "&", self::getLink ($this->book, $this->extension, $this->getMimeType (), NULL, $this->getFilename (), $this->id, NULL)->href); - } - } - - public static function getLink ($book, $type, $mime, $rel, $filename, $idData, $title = NULL) - { - global $config; - - $textData = ""; - if (!is_null ($idData)) - { - $textData = "&data=" . $idData; - } - - if (preg_match ('/^\//', $config['calibre_directory']) || // Linux / - preg_match ('/^\w\:/', $config['calibre_directory']) || // Windows X: - ($type == "epub" && $config['cops_update_epub-metadata'])) - { - if ($type != "jpg") $textData .= "&type=" . $type; - return new Link ("fetch.php?id=$book->id" . $textData, $mime, $rel, $title); - } - else - { - return new Link (str_replace('%2F','/',rawurlencode ($book->path."/".$filename)), $mime, $rel, $title); - } - } -} -?> \ No newline at end of file diff --git a/docker-compose-dev.yaml b/docker-compose-dev.yaml new file mode 100644 index 000000000..e6ca23113 --- /dev/null +++ b/docker-compose-dev.yaml @@ -0,0 +1,13 @@ +services: + dev: + image: mikespub/seblucas-cops:dev + build: + context: . + dockerfile: docker/Dockerfile.php82 + target: dev-envs + ports: + - '8080:80' + volumes: + - ./config_local.php:/app/config_local.php + - ./lib:/app/lib + - ./test:/app/test diff --git a/docker-compose.yaml b/docker-compose.yaml new file mode 100644 index 000000000..e30972f29 --- /dev/null +++ b/docker-compose.yaml @@ -0,0 +1,9 @@ +services: + web: + image: mikespub/seblucas-cops:web + build: + context: . + dockerfile: docker/Dockerfile.php82 + target: build + ports: + - '8080:80' diff --git a/docker/Dockerfile b/docker/Dockerfile new file mode 100644 index 000000000..38312b7b5 --- /dev/null +++ b/docker/Dockerfile @@ -0,0 +1,54 @@ +# syntax=docker/dockerfile:1 + +FROM ghcr.io/linuxserver/baseimage-alpine-nginx:3.17 + +# set version label +ARG BUILD_DATE +ARG VERSION +ARG COPS_RELEASE +LABEL build_version="Linuxserver.io version:- ${VERSION} Build-date:- ${BUILD_DATE}" +LABEL maintainer="chbmb" + +RUN \ + echo "**** install runtime packages ****" && \ + apk add --no-cache --upgrade \ + php81-ctype \ + php81-dom \ + php81-gd \ + php81-intl \ + php81-opcache \ + php81-phar \ + php81-pdo_sqlite \ + php81-zip && \ + echo "**** install cops ****" && \ + curl \ + -sS https://getcomposer.org/installer \ + | php -- --install-dir=/usr/bin --filename=composer --version=1.10.26 && \ + composer \ + global require "fxp/composer-asset-plugin:~1.1" && \ + if [ -z ${COPS_RELEASE+x} ]; then \ + COPS_RELEASE=$(curl -sX GET "https://api.github.com/repos/seblucas/cops/releases/latest" \ + | awk '/tag_name/{print $4;exit}' FS='[""]'); \ + fi && \ + curl -o \ + /tmp/cops.tar.gz -L \ + "https://github.com/seblucas/cops/archive/${COPS_RELEASE}.tar.gz" && \ + mkdir -p \ + /app/www/public && \ + tar xf /tmp/cops.tar.gz -C \ + /app/www/public --strip-components=1 && \ + cd /app/www/public && \ + composer \ + install --no-dev --optimize-autoloader && \ + sed -i 's|^[[:space:]]*return[[:space:]]@create_function[[:space:]]'\(''\''\$it'\'',[[:space:]]\$func'\)';| return function \(\$it\) use \(\$func\) \{\n return eval\(\$func\);\n \};|' vendor/seblucas/dot-php/doT.php && \ + echo "**** cleanup ****" && \ + rm -rf \ + /root/.composer \ + /tmp/* + +# add local files +COPY root/ / + +# ports and volumes +EXPOSE 80 443 +VOLUME /config diff --git a/docker/Dockerfile.php82 b/docker/Dockerfile.php82 new file mode 100644 index 000000000..873031157 --- /dev/null +++ b/docker/Dockerfile.php82 @@ -0,0 +1,8 @@ +FROM webdevops/php-nginx:8.2-alpine AS build +COPY . /app +RUN composer install --no-dev -o -d /app + +FROM build as dev-envs +RUN composer update -o -d /app +#RUN apk --no-cache add nodejs yarn +#RUN yarn diff --git a/epubfs.php b/epubfs.php new file mode 100644 index 000000000..16b5dce42 --- /dev/null +++ b/epubfs.php @@ -0,0 +1,87 @@ + + */ + +require_once dirname(__FILE__) . '/config.php'; +require_once dirname(__FILE__) . '/base.php'; +/** @var array $config */ + +initURLParam(); + +function getComponentContent($book, $component, $add) +{ + $data = $book->component($component); + + $callback = function ($m) use ($book, $component, $add) { + $method = $m[1]; + $path = $m[2]; + $end = ''; + if (preg_match('/^src\s*:/', $method)) { + $end = ')'; + } + if (preg_match('/^#/', $path)) { + return $method . "'" . $path . "'" . $end; + } + $hash = ''; + if (preg_match('/^(.+)#(.+)$/', $path, $matches)) { + $path = $matches[1]; + $hash = '#' . $matches[2]; + } + $comp = $book->getComponentName($component, $path); + if (!$comp) { + return $method . "'#'" . $end; + } + $out = $method . "'epubfs.php?" . $add . 'comp=' . $comp . $hash . "'" . $end; + if ($end) { + return $out; + } + return str_replace('&', '&', $out); + }; + + $data = preg_replace_callback("/(src=)[\"']([^:]*?)[\"']/", $callback, $data); + $data = preg_replace_callback("/(href=)[\"']([^:]*?)[\"']/", $callback, $data); + $data = preg_replace_callback("/(\@import\s+)[\"'](.*?)[\"'];/", $callback, $data); + $data = preg_replace_callback('/(src\s*:\s*url\()(.*?)\)/', $callback, $data); + + return $data; +} + +if (php_sapi_name() === 'cli') { + return; +} + +$idData = getURLParam('data', null); +$add = 'data=' . $idData . '&'; +if (!is_null(GetUrlParam(DB))) { + $add .= DB . '=' . GetUrlParam(DB) . '&'; +} +$myBook = Book::getBookByDataId($idData); + +$book = new EPub($myBook->getFilePath('EPUB', $idData)); + +$book->initSpineComponent(); + +if (!isset($_GET['comp'])) { + notFound(); + return; +} + +$component = $_GET['comp']; + +try { + $data = getComponentContent($book, $component, $add); + + $expires = 60*60*24*14; + header('Pragma: public'); + header('Cache-Control: maxage='.$expires); + header('Expires: ' . gmdate('D, d M Y H:i:s', time()+$expires) . ' GMT'); + header('Content-Type: ' . $book->componentContentType($component)); + echo $data; +} catch (Exception $e) { + error_log($e); + notFound(); +} diff --git a/epubreader.php b/epubreader.php new file mode 100644 index 000000000..0599ae7c3 --- /dev/null +++ b/epubreader.php @@ -0,0 +1,82 @@ + + + + */ + +require_once dirname(__FILE__) . '/config.php'; +require_once dirname(__FILE__) . '/base.php'; +/** @var array $config */ + +initURLParam(); + +$idData = (int)getURLParam('data', null); +$add = 'data=' . $idData . '&'; +if (!is_null(GetUrlParam(DB))) { + $add .= DB . '=' . GetUrlParam(DB) . '&'; +} +$myBook = Book::getBookByDataId($idData); + +$book = new EPub($myBook->getFilePath('EPUB', $idData)); +$book->initSpineComponent(); + +?> + + + + + COPS's Epub Reader + + + " media="screen" /> + " media="screen" /> + + + " media="screen" /> + + + +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + + diff --git a/fancybox/blank.gif b/fancybox/blank.gif deleted file mode 100644 index 35d42e808..000000000 Binary files a/fancybox/blank.gif and /dev/null differ diff --git a/fancybox/fancybox_loading.gif b/fancybox/fancybox_loading.gif deleted file mode 100644 index 01586176d..000000000 Binary files a/fancybox/fancybox_loading.gif and /dev/null differ diff --git a/fancybox/fancybox_overlay.png b/fancybox/fancybox_overlay.png deleted file mode 100644 index a4391396a..000000000 Binary files a/fancybox/fancybox_overlay.png and /dev/null differ diff --git a/fancybox/fancybox_sprite.png b/fancybox/fancybox_sprite.png deleted file mode 100644 index fd8d5ca56..000000000 Binary files a/fancybox/fancybox_sprite.png and /dev/null differ diff --git a/fancybox/helpers/fancybox_buttons.png b/fancybox/helpers/fancybox_buttons.png deleted file mode 100644 index 078720727..000000000 Binary files a/fancybox/helpers/fancybox_buttons.png and /dev/null differ diff --git a/fancybox/helpers/jquery.fancybox-buttons.css b/fancybox/helpers/jquery.fancybox-buttons.css deleted file mode 100644 index 9453b464d..000000000 --- a/fancybox/helpers/jquery.fancybox-buttons.css +++ /dev/null @@ -1,96 +0,0 @@ -#fancybox-buttons { - position: fixed; - left: 0; - width: 100%; - z-index: 8050; -} - -#fancybox-buttons.top { - top: 10px; -} - -#fancybox-buttons.bottom { - bottom: 10px; -} - -#fancybox-buttons ul { - display: block; - width: 166px; - height: 30px; - margin: 0 auto; - padding: 0; - list-style: none; - border: 1px solid #111; - border-radius: 3px; - -webkit-box-shadow: inset 0 0 0 1px rgba(255,255,255,.05); - -moz-box-shadow: inset 0 0 0 1px rgba(255,255,255,.05); - box-shadow: inset 0 0 0 1px rgba(255,255,255,.05); - background: rgb(50,50,50); - background: -moz-linear-gradient(top, rgb(68,68,68) 0%, rgb(52,52,52) 50%, rgb(41,41,41) 50%, rgb(51,51,51) 100%); - background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgb(68,68,68)), color-stop(50%,rgb(52,52,52)), color-stop(50%,rgb(41,41,41)), color-stop(100%,rgb(51,51,51))); - background: -webkit-linear-gradient(top, rgb(68,68,68) 0%,rgb(52,52,52) 50%,rgb(41,41,41) 50%,rgb(51,51,51) 100%); - background: -o-linear-gradient(top, rgb(68,68,68) 0%,rgb(52,52,52) 50%,rgb(41,41,41) 50%,rgb(51,51,51) 100%); - background: -ms-linear-gradient(top, rgb(68,68,68) 0%,rgb(52,52,52) 50%,rgb(41,41,41) 50%,rgb(51,51,51) 100%); - background: linear-gradient(top, rgb(68,68,68) 0%,rgb(52,52,52) 50%,rgb(41,41,41) 50%,rgb(51,51,51) 100%); - filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#444444', endColorstr='#222222',GradientType=0 ); -} - -#fancybox-buttons ul li { - float: left; - margin: 0; - padding: 0; -} - -#fancybox-buttons a { - display: block; - width: 30px; - height: 30px; - text-indent: -9999px; - background-image: url('fancybox_buttons.png'); - background-repeat: no-repeat; - outline: none; - opacity: 0.8; -} - -#fancybox-buttons a:hover { - opacity: 1; -} - -#fancybox-buttons a.btnPrev { - background-position: 5px 0; -} - -#fancybox-buttons a.btnNext { - background-position: -33px 0; - border-right: 1px solid #3e3e3e; -} - -#fancybox-buttons a.btnPlay { - background-position: 0 -30px; -} - -#fancybox-buttons a.btnPlayOn { - background-position: -30px -30px; -} - -#fancybox-buttons a.btnToggle { - background-position: 3px -60px; - border-left: 1px solid #111; - border-right: 1px solid #3e3e3e; - width: 35px -} - -#fancybox-buttons a.btnToggleOn { - background-position: -27px -60px; -} - -#fancybox-buttons a.btnClose { - border-left: 1px solid #111; - width: 35px; - background-position: -56px 0px; -} - -#fancybox-buttons a.btnDisabled { - opacity : 0.4; - cursor: default; -} \ No newline at end of file diff --git a/fancybox/helpers/jquery.fancybox-buttons.js b/fancybox/helpers/jquery.fancybox-buttons.js deleted file mode 100644 index 50baeca42..000000000 --- a/fancybox/helpers/jquery.fancybox-buttons.js +++ /dev/null @@ -1,121 +0,0 @@ - /*! - * Buttons helper for fancyBox - * version: 1.0.5 (Mon, 15 Oct 2012) - * @requires fancyBox v2.0 or later - * - * Usage: - * $(".fancybox").fancybox({ - * helpers : { - * buttons: { - * position : 'top' - * } - * } - * }); - * - */ -(function ($) { - //Shortcut for fancyBox object - var F = $.fancybox; - - //Add helper object - F.helpers.buttons = { - defaults : { - skipSingle : false, // disables if gallery contains single image - position : 'top', // 'top' or 'bottom' - tpl : '
    ' - }, - - list : null, - buttons: null, - - beforeLoad: function (opts, obj) { - //Remove self if gallery do not have at least two items - - if (opts.skipSingle && obj.group.length < 2) { - obj.helpers.buttons = false; - obj.closeBtn = true; - - return; - } - - //Increase top margin to give space for buttons - obj.margin[ opts.position === 'bottom' ? 2 : 0 ] += 30; - }, - - onPlayStart: function () { - if (this.buttons) { - this.buttons.play.attr('title', 'Pause slideshow').addClass('btnPlayOn'); - } - }, - - onPlayEnd: function () { - if (this.buttons) { - this.buttons.play.attr('title', 'Start slideshow').removeClass('btnPlayOn'); - } - }, - - afterShow: function (opts, obj) { - var buttons = this.buttons; - - if (!buttons) { - this.list = $(opts.tpl).addClass(opts.position).appendTo('body'); - - buttons = { - prev : this.list.find('.btnPrev').click( F.prev ), - next : this.list.find('.btnNext').click( F.next ), - play : this.list.find('.btnPlay').click( F.play ), - toggle : this.list.find('.btnToggle').click( F.toggle ) - } - } - - //Prev - if (obj.index > 0 || obj.loop) { - buttons.prev.removeClass('btnDisabled'); - } else { - buttons.prev.addClass('btnDisabled'); - } - - //Next / Play - if (obj.loop || obj.index < obj.group.length - 1) { - buttons.next.removeClass('btnDisabled'); - buttons.play.removeClass('btnDisabled'); - - } else { - buttons.next.addClass('btnDisabled'); - buttons.play.addClass('btnDisabled'); - } - - this.buttons = buttons; - - this.onUpdate(opts, obj); - }, - - onUpdate: function (opts, obj) { - var toggle; - - if (!this.buttons) { - return; - } - - toggle = this.buttons.toggle.removeClass('btnDisabled btnToggleOn'); - - //Size toggle button - if (obj.canShrink) { - toggle.addClass('btnToggleOn'); - - } else if (!obj.canExpand) { - toggle.addClass('btnDisabled'); - } - }, - - beforeClose: function () { - if (this.list) { - this.list.remove(); - } - - this.list = null; - this.buttons = null; - } - }; - -}(jQuery)); \ No newline at end of file diff --git a/fancybox/helpers/jquery.fancybox-media.js b/fancybox/helpers/jquery.fancybox-media.js deleted file mode 100644 index 4b5e78356..000000000 --- a/fancybox/helpers/jquery.fancybox-media.js +++ /dev/null @@ -1,196 +0,0 @@ -/*! - * Media helper for fancyBox - * version: 1.0.5 (Tue, 23 Oct 2012) - * @requires fancyBox v2.0 or later - * - * Usage: - * $(".fancybox").fancybox({ - * helpers : { - * media: true - * } - * }); - * - * Set custom URL parameters: - * $(".fancybox").fancybox({ - * helpers : { - * media: { - * youtube : { - * params : { - * autoplay : 0 - * } - * } - * } - * } - * }); - * - * Or: - * $(".fancybox").fancybox({, - * helpers : { - * media: true - * }, - * youtube : { - * autoplay: 0 - * } - * }); - * - * Supports: - * - * Youtube - * http://www.youtube.com/watch?v=opj24KnzrWo - * http://www.youtube.com/embed/opj24KnzrWo - * http://youtu.be/opj24KnzrWo - * Vimeo - * http://vimeo.com/40648169 - * http://vimeo.com/channels/staffpicks/38843628 - * http://vimeo.com/groups/surrealism/videos/36516384 - * http://player.vimeo.com/video/45074303 - * Metacafe - * http://www.metacafe.com/watch/7635964/dr_seuss_the_lorax_movie_trailer/ - * http://www.metacafe.com/watch/7635964/ - * Dailymotion - * http://www.dailymotion.com/video/xoytqh_dr-seuss-the-lorax-premiere_people - * Twitvid - * http://twitvid.com/QY7MD - * Twitpic - * http://twitpic.com/7p93st - * Instagram - * http://instagr.am/p/IejkuUGxQn/ - * http://instagram.com/p/IejkuUGxQn/ - * Google maps - * http://maps.google.com/maps?q=Eiffel+Tower,+Avenue+Gustave+Eiffel,+Paris,+France&t=h&z=17 - * http://maps.google.com/?ll=48.857995,2.294297&spn=0.007666,0.021136&t=m&z=16 - * http://maps.google.com/?ll=48.859463,2.292626&spn=0.000965,0.002642&t=m&z=19&layer=c&cbll=48.859524,2.292532&panoid=YJ0lq28OOy3VT2IqIuVY0g&cbp=12,151.58,,0,-15.56 - */ -(function ($) { - "use strict"; - - //Shortcut for fancyBox object - var F = $.fancybox, - format = function( url, rez, params ) { - params = params || ''; - - if ( $.type( params ) === "object" ) { - params = $.param(params, true); - } - - $.each(rez, function(key, value) { - url = url.replace( '$' + key, value || '' ); - }); - - if (params.length) { - url += ( url.indexOf('?') > 0 ? '&' : '?' ) + params; - } - - return url; - }; - - //Add helper object - F.helpers.media = { - defaults : { - youtube : { - matcher : /(youtube\.com|youtu\.be)\/(watch\?v=|v\/|u\/|embed\/?)?(videoseries\?list=(.*)|[\w-]{11}|\?listType=(.*)&list=(.*)).*/i, - params : { - autoplay : 1, - autohide : 1, - fs : 1, - rel : 0, - hd : 1, - wmode : 'opaque', - enablejsapi : 1 - }, - type : 'iframe', - url : '//www.youtube.com/embed/$3' - }, - vimeo : { - matcher : /(?:vimeo(?:pro)?.com)\/(?:[^\d]+)?(\d+)(?:.*)/, - params : { - autoplay : 1, - hd : 1, - show_title : 1, - show_byline : 1, - show_portrait : 0, - fullscreen : 1 - }, - type : 'iframe', - url : '//player.vimeo.com/video/$1' - }, - metacafe : { - matcher : /metacafe.com\/(?:watch|fplayer)\/([\w\-]{1,10})/, - params : { - autoPlay : 'yes' - }, - type : 'swf', - url : function( rez, params, obj ) { - obj.swf.flashVars = 'playerVars=' + $.param( params, true ); - - return '//www.metacafe.com/fplayer/' + rez[1] + '/.swf'; - } - }, - dailymotion : { - matcher : /dailymotion.com\/video\/(.*)\/?(.*)/, - params : { - additionalInfos : 0, - autoStart : 1 - }, - type : 'swf', - url : '//www.dailymotion.com/swf/video/$1' - }, - twitvid : { - matcher : /twitvid\.com\/([a-zA-Z0-9_\-\?\=]+)/i, - params : { - autoplay : 0 - }, - type : 'iframe', - url : '//www.twitvid.com/embed.php?guid=$1' - }, - twitpic : { - matcher : /twitpic\.com\/(?!(?:place|photos|events)\/)([a-zA-Z0-9\?\=\-]+)/i, - type : 'image', - url : '//twitpic.com/show/full/$1/' - }, - instagram : { - matcher : /(instagr\.am|instagram\.com)\/p\/([a-zA-Z0-9_\-]+)\/?/i, - type : 'image', - url : '//$1/p/$2/media/' - }, - google_maps : { - matcher : /maps\.google\.([a-z]{2,3}(\.[a-z]{2})?)\/(\?ll=|maps\?)(.*)/i, - type : 'iframe', - url : function( rez ) { - return '//maps.google.' + rez[1] + '/' + rez[3] + '' + rez[4] + '&output=' + (rez[4].indexOf('layer=c') > 0 ? 'svembed' : 'embed'); - } - } - }, - - beforeLoad : function(opts, obj) { - var url = obj.href || '', - type = false, - what, - item, - rez, - params; - - for (what in opts) { - item = opts[ what ]; - rez = url.match( item.matcher ); - - if (rez) { - type = item.type; - params = $.extend(true, {}, item.params, obj[ what ] || ($.isPlainObject(opts[ what ]) ? opts[ what ].params : null)); - - url = $.type( item.url ) === "function" ? item.url.call( this, rez, params, obj ) : format( item.url, rez, params ); - - break; - } - } - - if (type) { - obj.href = url; - obj.type = type; - - obj.autoHeight = false; - } - } - }; - -}(jQuery)); \ No newline at end of file diff --git a/fancybox/helpers/jquery.fancybox-thumbs.css b/fancybox/helpers/jquery.fancybox-thumbs.css deleted file mode 100644 index e40ae820b..000000000 --- a/fancybox/helpers/jquery.fancybox-thumbs.css +++ /dev/null @@ -1,54 +0,0 @@ -#fancybox-thumbs { - position: fixed; - left: 0; - width: 100%; - overflow: hidden; - z-index: 8050; -} - -#fancybox-thumbs.bottom { - bottom: 2px; -} - -#fancybox-thumbs.top { - top: 2px; -} - -#fancybox-thumbs ul { - position: relative; - list-style: none; - margin: 0; - padding: 0; -} - -#fancybox-thumbs ul li { - float: left; - padding: 1px; - opacity: 0.5; -} - -#fancybox-thumbs ul li.active { - opacity: 0.75; - padding: 0; - border: 1px solid #fff; -} - -#fancybox-thumbs ul li:hover { - opacity: 1; -} - -#fancybox-thumbs ul li a { - display: block; - position: relative; - overflow: hidden; - border: 1px solid #222; - background: #111; - outline: none; -} - -#fancybox-thumbs ul li img { - display: block; - position: relative; - border: 0; - padding: 0; -} \ No newline at end of file diff --git a/fancybox/helpers/jquery.fancybox-thumbs.js b/fancybox/helpers/jquery.fancybox-thumbs.js deleted file mode 100644 index 5db3d4ac2..000000000 --- a/fancybox/helpers/jquery.fancybox-thumbs.js +++ /dev/null @@ -1,162 +0,0 @@ - /*! - * Thumbnail helper for fancyBox - * version: 1.0.7 (Mon, 01 Oct 2012) - * @requires fancyBox v2.0 or later - * - * Usage: - * $(".fancybox").fancybox({ - * helpers : { - * thumbs: { - * width : 50, - * height : 50 - * } - * } - * }); - * - */ -(function ($) { - //Shortcut for fancyBox object - var F = $.fancybox; - - //Add helper object - F.helpers.thumbs = { - defaults : { - width : 50, // thumbnail width - height : 50, // thumbnail height - position : 'bottom', // 'top' or 'bottom' - source : function ( item ) { // function to obtain the URL of the thumbnail image - var href; - - if (item.element) { - href = $(item.element).find('img').attr('src'); - } - - if (!href && item.type === 'image' && item.href) { - href = item.href; - } - - return href; - } - }, - - wrap : null, - list : null, - width : 0, - - init: function (opts, obj) { - var that = this, - list, - thumbWidth = opts.width, - thumbHeight = opts.height, - thumbSource = opts.source; - - //Build list structure - list = ''; - - for (var n = 0; n < obj.group.length; n++) { - list += '
  • '; - } - - this.wrap = $('
    ').addClass(opts.position).appendTo('body'); - this.list = $('
      ' + list + '
    ').appendTo(this.wrap); - - //Load each thumbnail - $.each(obj.group, function (i) { - var href = thumbSource( obj.group[ i ] ); - - if (!href) { - return; - } - - $("").load(function () { - var width = this.width, - height = this.height, - widthRatio, heightRatio, parent; - - if (!that.list || !width || !height) { - return; - } - - //Calculate thumbnail width/height and center it - widthRatio = width / thumbWidth; - heightRatio = height / thumbHeight; - - parent = that.list.children().eq(i).find('a'); - - if (widthRatio >= 1 && heightRatio >= 1) { - if (widthRatio > heightRatio) { - width = Math.floor(width / heightRatio); - height = thumbHeight; - - } else { - width = thumbWidth; - height = Math.floor(height / widthRatio); - } - } - - $(this).css({ - width : width, - height : height, - top : Math.floor(thumbHeight / 2 - height / 2), - left : Math.floor(thumbWidth / 2 - width / 2) - }); - - parent.width(thumbWidth).height(thumbHeight); - - $(this).hide().appendTo(parent).fadeIn(300); - - }).attr('src', href); - }); - - //Set initial width - this.width = this.list.children().eq(0).outerWidth(true); - - this.list.width(this.width * (obj.group.length + 1)).css('left', Math.floor($(window).width() * 0.5 - (obj.index * this.width + this.width * 0.5))); - }, - - beforeLoad: function (opts, obj) { - //Remove self if gallery do not have at least two items - if (obj.group.length < 2) { - obj.helpers.thumbs = false; - - return; - } - - //Increase bottom margin to give space for thumbs - obj.margin[ opts.position === 'top' ? 0 : 2 ] += ((opts.height) + 15); - }, - - afterShow: function (opts, obj) { - //Check if exists and create or update list - if (this.list) { - this.onUpdate(opts, obj); - - } else { - this.init(opts, obj); - } - - //Set active element - this.list.children().removeClass('active').eq(obj.index).addClass('active'); - }, - - //Center list - onUpdate: function (opts, obj) { - if (this.list) { - this.list.stop(true).animate({ - 'left': Math.floor($(window).width() * 0.5 - (obj.index * this.width + this.width * 0.5)) - }, 150); - } - }, - - beforeClose: function () { - if (this.wrap) { - this.wrap.remove(); - } - - this.wrap = null; - this.list = null; - this.width = 0; - } - } - -}(jQuery)); \ No newline at end of file diff --git a/fancybox/jquery.fancybox.css b/fancybox/jquery.fancybox.css deleted file mode 100644 index d6ff8a17f..000000000 --- a/fancybox/jquery.fancybox.css +++ /dev/null @@ -1,249 +0,0 @@ -/*! fancyBox v2.1.3 fancyapps.com | fancyapps.com/fancybox/#license */ -.fancybox-wrap, -.fancybox-skin, -.fancybox-outer, -.fancybox-inner, -.fancybox-image, -.fancybox-wrap iframe, -.fancybox-wrap object, -.fancybox-nav, -.fancybox-nav span, -.fancybox-tmp -{ - padding: 0; - margin: 0; - border: 0; - outline: none; - vertical-align: top; -} - -.fancybox-wrap { - position: absolute; - top: 0; - left: 0; - z-index: 8020; -} - -.fancybox-skin { - position: relative; - background: #f9f9f9; - color: #444; - text-shadow: none; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; -} - -.fancybox-opened { - z-index: 8030; -} - -.fancybox-opened .fancybox-skin { - -webkit-box-shadow: 0 10px 25px rgba(0, 0, 0, 0.5); - -moz-box-shadow: 0 10px 25px rgba(0, 0, 0, 0.5); - box-shadow: 0 10px 25px rgba(0, 0, 0, 0.5); -} - -.fancybox-outer, .fancybox-inner { - position: relative; -} - -.fancybox-inner { - overflow: hidden; -} - -.fancybox-type-iframe .fancybox-inner { - -webkit-overflow-scrolling: touch; -} - -.fancybox-error { - color: #444; - font: 14px/20px "Helvetica Neue",Helvetica,Arial,sans-serif; - margin: 0; - padding: 15px; - white-space: nowrap; -} - -.fancybox-image, .fancybox-iframe { - display: block; - width: 100%; - height: 100%; -} - -.fancybox-image { - max-width: 100%; - max-height: 100%; -} - -#fancybox-loading, .fancybox-close, .fancybox-prev span, .fancybox-next span { - background-image: url('fancybox_sprite.png'); -} - -#fancybox-loading { - position: fixed; - top: 50%; - left: 50%; - margin-top: -22px; - margin-left: -22px; - background-position: 0 -108px; - opacity: 0.8; - cursor: pointer; - z-index: 8060; -} - -#fancybox-loading div { - width: 44px; - height: 44px; - background: url('fancybox_loading.gif') center center no-repeat; -} - -.fancybox-close { - position: absolute; - top: -18px; - right: -18px; - width: 36px; - height: 36px; - cursor: pointer; - z-index: 8040; -} - -.fancybox-nav { - position: absolute; - top: 0; - width: 40%; - height: 100%; - cursor: pointer; - text-decoration: none; - background: transparent url('blank.gif'); /* helps IE */ - -webkit-tap-highlight-color: rgba(0,0,0,0); - z-index: 8040; -} - -.fancybox-prev { - left: 0; -} - -.fancybox-next { - right: 0; -} - -.fancybox-nav span { - position: absolute; - top: 50%; - width: 36px; - height: 34px; - margin-top: -18px; - cursor: pointer; - z-index: 8040; - visibility: hidden; -} - -.fancybox-prev span { - left: 10px; - background-position: 0 -36px; -} - -.fancybox-next span { - right: 10px; - background-position: 0 -72px; -} - -.fancybox-nav:hover span { - visibility: visible; -} - -.fancybox-tmp { - position: absolute; - top: -99999px; - left: -99999px; - visibility: hidden; - max-width: 99999px; - max-height: 99999px; - overflow: visible !important; -} - -/* Overlay helper */ - -.fancybox-lock { - overflow: hidden; -} - -.fancybox-overlay { - position: absolute; - top: 0; - left: 0; - overflow: hidden; - display: none; - z-index: 8010; - background: url('fancybox_overlay.png'); -} - -.fancybox-overlay-fixed { - position: fixed; - bottom: 0; - right: 0; -} - -.fancybox-lock .fancybox-overlay { - overflow: auto; - overflow-y: scroll; -} - -/* Title helper */ - -.fancybox-title { - visibility: hidden; - font: normal 13px/20px "Helvetica Neue",Helvetica,Arial,sans-serif; - position: relative; - text-shadow: none; - z-index: 8050; -} - -.fancybox-opened .fancybox-title { - visibility: visible; -} - -.fancybox-title-float-wrap { - position: absolute; - bottom: 0; - right: 50%; - margin-bottom: -35px; - z-index: 8050; - text-align: center; -} - -.fancybox-title-float-wrap .child { - display: inline-block; - margin-right: -100%; - padding: 2px 20px; - background: transparent; /* Fallback for web browsers that doesn't support RGBa */ - background: rgba(0, 0, 0, 0.8); - -webkit-border-radius: 15px; - -moz-border-radius: 15px; - border-radius: 15px; - text-shadow: 0 1px 2px #222; - color: #FFF; - font-weight: bold; - line-height: 24px; - white-space: nowrap; -} - -.fancybox-title-outside-wrap { - position: relative; - margin-top: 10px; - color: #fff; -} - -.fancybox-title-inside-wrap { - padding-top: 10px; -} - -.fancybox-title-over-wrap { - position: absolute; - bottom: 0; - left: 0; - color: #fff; - padding: 10px; - background: #000; - background: rgba(0, 0, 0, .8); -} \ No newline at end of file diff --git a/fancybox/jquery.fancybox.pack.js b/fancybox/jquery.fancybox.pack.js deleted file mode 100644 index 088b5c6e7..000000000 --- a/fancybox/jquery.fancybox.pack.js +++ /dev/null @@ -1,45 +0,0 @@ -/*! fancyBox v2.1.3 fancyapps.com | fancyapps.com/fancybox/#license */ -(function(B,x,f,q){var r=f(B),m=f(x),b=f.fancybox=function(){b.open.apply(this,arguments)},u=null,n=x.createTouch!==q,s=function(a){return a&&a.hasOwnProperty&&a instanceof f},p=function(a){return a&&"string"===f.type(a)},E=function(a){return p(a)&&0
    ',image:'',iframe:'",error:'

    The requested content cannot be loaded.
    Please try again later.

    ',closeBtn:'',next:'',prev:''},openEffect:"fade",openSpeed:250,openEasing:"swing", -openOpacity:!0,openMethod:"zoomIn",closeEffect:"fade",closeSpeed:250,closeEasing:"swing",closeOpacity:!0,closeMethod:"zoomOut",nextEffect:"elastic",nextSpeed:250,nextEasing:"swing",nextMethod:"changeIn",prevEffect:"elastic",prevSpeed:250,prevEasing:"swing",prevMethod:"changeOut",helpers:{overlay:!0,title:!0},onCancel:f.noop,beforeLoad:f.noop,afterLoad:f.noop,beforeShow:f.noop,afterShow:f.noop,beforeChange:f.noop,beforeClose:f.noop,afterClose:f.noop},group:{},opts:{},previous:null,coming:null,current:null, -isActive:!1,isOpen:!1,isOpened:!1,wrap:null,skin:null,outer:null,inner:null,player:{timer:null,isActive:!1},ajaxLoad:null,imgPreload:null,transitions:{},helpers:{},open:function(a,d){if(a&&(f.isPlainObject(d)||(d={}),!1!==b.close(!0)))return f.isArray(a)||(a=s(a)?f(a).get():[a]),f.each(a,function(e,c){var j={},g,h,i,l,k;"object"===f.type(c)&&(c.nodeType&&(c=f(c)),s(c)?(j={href:c.data("fancybox-href")||c.attr("href"),title:c.data("fancybox-title")||c.attr("title"),isDom:!0,element:c},f.metadata&&f.extend(!0, -j,c.metadata())):j=c);g=d.href||j.href||(p(c)?c:null);h=d.title!==q?d.title:j.title||"";l=(i=d.content||j.content)?"html":d.type||j.type;!l&&j.isDom&&(l=c.data("fancybox-type"),l||(l=(l=c.prop("class").match(/fancybox\.(\w+)/))?l[1]:null));p(g)&&(l||(b.isImage(g)?l="image":b.isSWF(g)?l="swf":"#"===g.charAt(0)?l="inline":p(c)&&(l="html",i=c)),"ajax"===l&&(k=g.split(/\s+/,2),g=k.shift(),k=k.shift()));i||("inline"===l?g?i=f(p(g)?g.replace(/.*(?=#[^\s]+$)/,""):g):j.isDom&&(i=c):"html"===l?i=g:!l&&(!g&& -j.isDom)&&(l="inline",i=c));f.extend(j,{href:g,type:l,content:i,title:h,selector:k});a[e]=j}),b.opts=f.extend(!0,{},b.defaults,d),d.keys!==q&&(b.opts.keys=d.keys?f.extend({},b.defaults.keys,d.keys):!1),b.group=a,b._start(b.opts.index)},cancel:function(){var a=b.coming;a&&!1!==b.trigger("onCancel")&&(b.hideLoading(),b.ajaxLoad&&b.ajaxLoad.abort(),b.ajaxLoad=null,b.imgPreload&&(b.imgPreload.onload=b.imgPreload.onerror=null),a.wrap&&a.wrap.stop(!0,!0).trigger("onReset").remove(),b.coming=null,b.current|| -b._afterZoomOut(a))},close:function(a){b.cancel();!1!==b.trigger("beforeClose")&&(b.unbindEvents(),b.isActive&&(!b.isOpen||!0===a?(f(".fancybox-wrap").stop(!0).trigger("onReset").remove(),b._afterZoomOut()):(b.isOpen=b.isOpened=!1,b.isClosing=!0,f(".fancybox-item, .fancybox-nav").remove(),b.wrap.stop(!0,!0).removeClass("fancybox-opened"),b.transitions[b.current.closeMethod]())))},play:function(a){var d=function(){clearTimeout(b.player.timer)},e=function(){d();b.current&&b.player.isActive&&(b.player.timer= -setTimeout(b.next,b.current.playSpeed))},c=function(){d();f("body").unbind(".player");b.player.isActive=!1;b.trigger("onPlayEnd")};if(!0===a||!b.player.isActive&&!1!==a){if(b.current&&(b.current.loop||b.current.index=c.index?"next":"prev"],b.router=e||"jumpto",c.loop&&(0>a&&(a=c.group.length+a%c.group.length),a%=c.group.length),c.group[a]!==q&&(b.cancel(),b._start(a)))},reposition:function(a,d){var e=b.current,c=e?e.wrap:null,j;c&&(j=b._getPosition(d),a&&"scroll"===a.type?(delete j.position,c.stop(!0,!0).animate(j,200)):(c.css(j),e.pos=f.extend({}, -e.dim,j)))},update:function(a){var d=a&&a.type,e=!d||"orientationchange"===d;e&&(clearTimeout(u),u=null);b.isOpen&&!u&&(u=setTimeout(function(){var c=b.current;c&&!b.isClosing&&(b.wrap.removeClass("fancybox-tmp"),(e||"load"===d||"resize"===d&&c.autoResize)&&b._setDimension(),"scroll"===d&&c.canShrink||b.reposition(a),b.trigger("onUpdate"),u=null)},e&&!n?0:300))},toggle:function(a){b.isOpen&&(b.current.fitToView="boolean"===f.type(a)?a:!b.current.fitToView,n&&(b.wrap.removeAttr("style").addClass("fancybox-tmp"), -b.trigger("onUpdate")),b.update())},hideLoading:function(){m.unbind(".loading");f("#fancybox-loading").remove()},showLoading:function(){var a,d;b.hideLoading();a=f('
    ').click(b.cancel).appendTo("body");m.bind("keydown.loading",function(a){if(27===(a.which||a.keyCode))a.preventDefault(),b.cancel()});b.defaults.fixed||(d=b.getViewport(),a.css({position:"absolute",top:0.5*d.h+d.y,left:0.5*d.w+d.x}))},getViewport:function(){var a=b.current&&b.current.locked|| -!1,d={x:r.scrollLeft(),y:r.scrollTop()};a?(d.w=a[0].clientWidth,d.h=a[0].clientHeight):(d.w=n&&B.innerWidth?B.innerWidth:r.width(),d.h=n&&B.innerHeight?B.innerHeight:r.height());return d},unbindEvents:function(){b.wrap&&s(b.wrap)&&b.wrap.unbind(".fb");m.unbind(".fb");r.unbind(".fb")},bindEvents:function(){var a=b.current,d;a&&(r.bind("orientationchange.fb"+(n?"":" resize.fb")+(a.autoCenter&&!a.locked?" scroll.fb":""),b.update),(d=a.keys)&&m.bind("keydown.fb",function(e){var c=e.which||e.keyCode,j= -e.target||e.srcElement;if(27===c&&b.coming)return!1;!e.ctrlKey&&(!e.altKey&&!e.shiftKey&&!e.metaKey&&(!j||!j.type&&!f(j).is("[contenteditable]")))&&f.each(d,function(d,j){if(1h[0].clientWidth||h[0].clientHeight&&h[0].scrollHeight>h[0].clientHeight),h=f(h).parent();if(0!==c&&!i&&1g||0>j)b.next(0>g?"up":"right");d.preventDefault()}}))},trigger:function(a,d){var e,c=d||b.coming||b.current;if(c){f.isFunction(c[a])&&(e=c[a].apply(c,Array.prototype.slice.call(arguments,1)));if(!1===e)return!1;c.helpers&&f.each(c.helpers,function(d, -e){e&&(b.helpers[d]&&f.isFunction(b.helpers[d][a]))&&(e=f.extend(!0,{},b.helpers[d].defaults,e),b.helpers[d][a](e,c))});f.event.trigger(a+".fb")}},isImage:function(a){return p(a)&&a.match(/(^data:image\/.*,)|(\.(jp(e|g|eg)|gif|png|bmp|webp)((\?|#).*)?$)/i)},isSWF:function(a){return p(a)&&a.match(/\.(swf)((\?|#).*)?$/i)},_start:function(a){var d={},e,c,a=k(a);e=b.group[a]||null;if(!e)return!1;d=f.extend(!0,{},b.opts,e);e=d.margin;c=d.padding;"number"===f.type(e)&&(d.margin=[e,e,e,e]);"number"===f.type(c)&& -(d.padding=[c,c,c,c]);d.modal&&f.extend(!0,d,{closeBtn:!1,closeClick:!1,nextClick:!1,arrows:!1,mouseWheel:!1,keys:null,helpers:{overlay:{closeClick:!1}}});d.autoSize&&(d.autoWidth=d.autoHeight=!0);"auto"===d.width&&(d.autoWidth=!0);"auto"===d.height&&(d.autoHeight=!0);d.group=b.group;d.index=a;b.coming=d;if(!1===b.trigger("beforeLoad"))b.coming=null;else{c=d.type;e=d.href;if(!c)return b.coming=null,b.current&&b.router&&"jumpto"!==b.router?(b.current.index=a,b[b.router](b.direction)):!1;b.isActive= -!0;if("image"===c||"swf"===c)d.autoHeight=d.autoWidth=!1,d.scrolling="visible";"image"===c&&(d.aspectRatio=!0);"iframe"===c&&n&&(d.scrolling="scroll");d.wrap=f(d.tpl.wrap).addClass("fancybox-"+(n?"mobile":"desktop")+" fancybox-type-"+c+" fancybox-tmp "+d.wrapCSS).appendTo(d.parent||"body");f.extend(d,{skin:f(".fancybox-skin",d.wrap),outer:f(".fancybox-outer",d.wrap),inner:f(".fancybox-inner",d.wrap)});f.each(["Top","Right","Bottom","Left"],function(a,b){d.skin.css("padding"+b,v(d.padding[a]))});b.trigger("onReady"); -if("inline"===c||"html"===c){if(!d.content||!d.content.length)return b._error("content")}else if(!e)return b._error("href");"image"===c?b._loadImage():"ajax"===c?b._loadAjax():"iframe"===c?b._loadIframe():b._afterLoad()}},_error:function(a){f.extend(b.coming,{type:"html",autoWidth:!0,autoHeight:!0,minWidth:0,minHeight:0,scrolling:"no",hasError:a,content:b.coming.tpl.error});b._afterLoad()},_loadImage:function(){var a=b.imgPreload=new Image;a.onload=function(){this.onload=this.onerror=null;b.coming.width= -this.width;b.coming.height=this.height;b._afterLoad()};a.onerror=function(){this.onload=this.onerror=null;b._error("image")};a.src=b.coming.href;!0!==a.complete&&b.showLoading()},_loadAjax:function(){var a=b.coming;b.showLoading();b.ajaxLoad=f.ajax(f.extend({},a.ajax,{url:a.href,error:function(a,e){b.coming&&"abort"!==e?b._error("ajax",a):b.hideLoading()},success:function(d,e){"success"===e&&(a.content=d,b._afterLoad())}}))},_loadIframe:function(){var a=b.coming,d=f(a.tpl.iframe.replace(/\{rnd\}/g, -(new Date).getTime())).attr("scrolling",n?"auto":a.iframe.scrolling).attr("src",a.href);f(a.wrap).bind("onReset",function(){try{f(this).find("iframe").hide().attr("src","//about:blank").end().empty()}catch(a){}});a.iframe.preload&&(b.showLoading(),d.one("load",function(){f(this).data("ready",1);n||f(this).bind("load.fb",b.update);f(this).parents(".fancybox-wrap").width("100%").removeClass("fancybox-tmp").show();b._afterLoad()}));a.content=d.appendTo(a.inner);a.iframe.preload||b._afterLoad()},_preloadImages:function(){var a= -b.group,d=b.current,e=a.length,c=d.preload?Math.min(d.preload,e-1):0,f,g;for(g=1;g<=c;g+=1)f=a[(d.index+g)%e],"image"===f.type&&f.href&&((new Image).src=f.href)},_afterLoad:function(){var a=b.coming,d=b.current,e,c,j,g,h;b.hideLoading();if(a&&!1!==b.isActive)if(!1===b.trigger("afterLoad",a,d))a.wrap.stop(!0).trigger("onReset").remove(),b.coming=null;else{d&&(b.trigger("beforeChange",d),d.wrap.stop(!0).removeClass("fancybox-opened").find(".fancybox-item, .fancybox-nav").remove());b.unbindEvents(); -e=a.content;c=a.type;j=a.scrolling;f.extend(b,{wrap:a.wrap,skin:a.skin,outer:a.outer,inner:a.inner,current:a,previous:d});g=a.href;switch(c){case "inline":case "ajax":case "html":a.selector?e=f("
    ").html(e).find(a.selector):s(e)&&(e.data("fancybox-placeholder")||e.data("fancybox-placeholder",f('
    ').insertAfter(e).hide()),e=e.show().detach(),a.wrap.bind("onReset",function(){f(this).find(e).length&&e.hide().replaceAll(e.data("fancybox-placeholder")).data("fancybox-placeholder", -!1)}));break;case "image":e=a.tpl.image.replace("{href}",g);break;case "swf":e='',h="",f.each(a.swf,function(a,b){e+='';h+=" "+a+'="'+b+'"'}),e+='"}(!s(e)||!e.parent().is(a.inner))&&a.inner.append(e);b.trigger("beforeShow"); -a.inner.css("overflow","yes"===j?"scroll":"no"===j?"hidden":j);b._setDimension();b.reposition();b.isOpen=!1;b.coming=null;b.bindEvents();if(b.isOpened){if(d.prevMethod)b.transitions[d.prevMethod]()}else f(".fancybox-wrap").not(a.wrap).stop(!0).trigger("onReset").remove();b.transitions[b.isOpened?a.nextMethod:a.openMethod]();b._preloadImages()}},_setDimension:function(){var a=b.getViewport(),d=0,e=!1,c=!1,e=b.wrap,j=b.skin,g=b.inner,h=b.current,c=h.width,i=h.height,l=h.minWidth,t=h.minHeight,m=h.maxWidth, -n=h.maxHeight,r=h.scrolling,p=h.scrollOutside?h.scrollbarWidth:0,w=h.margin,y=k(w[1]+w[3]),q=k(w[0]+w[2]),x,z,s,C,A,F,B,D,u;e.add(j).add(g).width("auto").height("auto").removeClass("fancybox-tmp");w=k(j.outerWidth(!0)-j.width());x=k(j.outerHeight(!0)-j.height());z=y+w;s=q+x;C=E(c)?(a.w-z)*k(c)/100:c;A=E(i)?(a.h-s)*k(i)/100:i;if("iframe"===h.type){if(u=h.content,h.autoHeight&&1===u.data("ready"))try{u[0].contentWindow.document.location&&(g.width(C).height(9999),F=u.contents().find("body"),p&&F.css("overflow-x", -"hidden"),A=F.height())}catch(G){}}else if(h.autoWidth||h.autoHeight)g.addClass("fancybox-tmp"),h.autoWidth||g.width(C),h.autoHeight||g.height(A),h.autoWidth&&(C=g.width()),h.autoHeight&&(A=g.height()),g.removeClass("fancybox-tmp");c=k(C);i=k(A);D=C/A;l=k(E(l)?k(l,"w")-z:l);m=k(E(m)?k(m,"w")-z:m);t=k(E(t)?k(t,"h")-s:t);n=k(E(n)?k(n,"h")-s:n);F=m;B=n;h.fitToView&&(m=Math.min(a.w-z,m),n=Math.min(a.h-s,n));z=a.w-y;q=a.h-q;h.aspectRatio?(c>m&&(c=m,i=k(c/D)),i>n&&(i=n,c=k(i*D)),cz||y>q)&&(c>l&&i>t)&&!(19m&&(c=m,i=k(c/D)),g.width(c).height(i),e.width(c+w),a=e.width(),y=e.height();else c=Math.max(l,Math.min(c,c-(a-z))),i=Math.max(t,Math.min(i,i-(y-q)));p&&("auto"===r&&iz||y>q)&&c>l&&i>t;c=h.aspectRatio?ct&&i
    ').appendTo("body");this.fixed=!1;a.fixed&&b.defaults.fixed&&(this.overlay.addClass("fancybox-overlay-fixed"),this.fixed=!0)},open:function(a){var d=this,a=f.extend({},this.defaults,a);this.overlay?this.overlay.unbind(".overlay").width("auto").height("auto"):this.create(a);this.fixed||(r.bind("resize.overlay",f.proxy(this.update,this)),this.update());a.closeClick&&this.overlay.bind("click.overlay",function(a){f(a.target).hasClass("fancybox-overlay")&& -(b.isActive?b.close():d.close())});this.overlay.css(a.css).show()},close:function(){f(".fancybox-overlay").remove();r.unbind("resize.overlay");this.overlay=null;!1!==this.margin&&(f("body").css("margin-right",this.margin),this.margin=!1);this.el&&this.el.removeClass("fancybox-lock")},update:function(){var a="100%",b;this.overlay.width(a).height("100%");f.browser.msie?(b=Math.max(x.documentElement.offsetWidth,x.body.offsetWidth),m.width()>b&&(a=m.width())):m.width()>r.width()&&(a=m.width());this.overlay.width(a).height(m.height())}, -onReady:function(a,b){f(".fancybox-overlay").stop(!0,!0);this.overlay||(this.margin=m.height()>r.height()||"scroll"===f("body").css("overflow-y")?f("body").css("margin-right"):!1,this.el=x.all&&!x.querySelector?f("html"):f("body"),this.create(a));a.locked&&this.fixed&&(b.locked=this.overlay.append(b.wrap),b.fixed=!1);!0===a.showEarly&&this.beforeShow.apply(this,arguments)},beforeShow:function(a,b){b.locked&&(this.el.addClass("fancybox-lock"),!1!==this.margin&&f("body").css("margin-right",k(this.margin)+ -b.scrollbarWidth));this.open(a)},onUpdate:function(){this.fixed||this.update()},afterClose:function(a){this.overlay&&!b.isActive&&this.overlay.fadeOut(a.speedOut,f.proxy(this.close,this))}};b.helpers.title={defaults:{type:"float",position:"bottom"},beforeShow:function(a){var d=b.current,e=d.title,c=a.type;f.isFunction(e)&&(e=e.call(d.element,d));if(p(e)&&""!==f.trim(e)){d=f('
    '+e+"
    ");switch(c){case "inside":c=b.skin;break;case "outside":c= -b.wrap;break;case "over":c=b.inner;break;default:c=b.skin,d.appendTo("body"),f.browser.msie&&d.width(d.width()),d.wrapInner(''),b.current.margin[2]+=Math.abs(k(d.css("margin-bottom")))}d["top"===a.position?"prependTo":"appendTo"](c)}}};f.fn.fancybox=function(a){var d,e=f(this),c=this.selector||"",j=function(g){var h=f(this).blur(),i=d,j,k;!g.ctrlKey&&(!g.altKey&&!g.shiftKey&&!g.metaKey)&&!h.is(".fancybox-wrap")&&(j=a.groupAttr||"data-fancybox-group",k=h.attr(j),k||(j="rel", -k=h.get(0)[j]),k&&(""!==k&&"nofollow"!==k)&&(h=c.length?f(c):e,h=h.filter("["+j+'="'+k+'"]'),i=h.index(this)),a.index=i,!1!==b.open(h,a)&&g.preventDefault())},a=a||{};d=a.index||0;!c||!1===a.live?e.unbind("click.fb-start").bind("click.fb-start",j):m.undelegate(c,"click.fb-start").delegate(c+":not('.fancybox-item, .fancybox-nav')","click.fb-start",j);this.filter("[data-fancybox-start=1]").trigger("click");return this};m.ready(function(){f.scrollbarWidth===q&&(f.scrollbarWidth=function(){var a=f('
    ').appendTo("body"), -b=a.children(),b=b.innerWidth()-b.height(99).innerWidth();a.remove();return b});if(f.support.fixedPosition===q){var a=f.support,d=f('
    ').appendTo("body"),e=20===d[0].offsetTop||15===d[0].offsetTop;d.remove();a.fixedPosition=e}f.extend(b.defaults,{scrollbarWidth:f.scrollbarWidth(),fixed:f.support.fixedPosition,parent:f("body")})})})(window,document,jQuery); \ No newline at end of file diff --git a/favicon.ico b/favicon.ico index 9be986be4..70b0402c8 100644 Binary files a/favicon.ico and b/favicon.ico differ diff --git a/feed.php b/feed.php index accbf3841..138c7d70c 100644 --- a/feed.php +++ b/feed.php @@ -3,37 +3,41 @@ * COPS (Calibre OPDS PHP Server) main script * * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) - * @author Sbastien Lucas + * @author Sébastien Lucas * */ - require_once ("config.php"); - require_once ("base.php"); - require_once ("author.php"); - require_once ("serie.php"); - require_once ("tag.php"); - require_once ("book.php"); - require_once ("OPDS_renderer.php"); - - header ("Content-Type:application/xml"); - $page = getURLParam ("page", Base::PAGE_INDEX); - $query = getURLParam ("query"); - $n = getURLParam ("n", "1"); - if ($query) - $page = Base::PAGE_OPENSEARCH_QUERY; - $qid = getURLParam ("id"); - - $OPDSRender = new OPDSRenderer (); - - switch ($page) { - case Base::PAGE_OPENSEARCH : - echo $OPDSRender->getOpenSearch (); - return; - default: - $currentPage = Page::getPage ($page, $qid, $query, $n); - $currentPage->InitializeContent (); - echo $OPDSRender->render ($currentPage); - return; - break; +require_once dirname(__FILE__) . '/config.php'; +require_once dirname(__FILE__) . '/base.php'; +/** @var array $config */ + +initURLParam(); + +header('Content-Type:application/xml'); +$page = getURLParam('page', Base::PAGE_INDEX); +$query = getURLParam('query'); +$n = getURLParam('n', '1'); +if ($query) { + $page = Base::PAGE_OPENSEARCH_QUERY; +} +$qid = getURLParam('id'); + +if ($config ['cops_fetch_protect'] == '1') { + session_start(); + if (!isset($_SESSION['connected'])) { + $_SESSION['connected'] = 0; } -?> +} + +$OPDSRender = new OPDSRenderer(); + +switch ($page) { + case Base::PAGE_OPENSEARCH : + echo $OPDSRender->getOpenSearch(); + return; + default: + $currentPage = Page::getPage($page, $qid, $query, $n); + $currentPage->InitializeContent(); + echo $OPDSRender->render($currentPage); + return; +} diff --git a/fetch.php b/fetch.php index bbde6fd21..d02c3f647 100644 --- a/fetch.php +++ b/fetch.php @@ -1,115 +1,146 @@ with integration/modification by Sbastien Lucas + * @author Sébastien Lucas */ - - require_once ("config.php"); - require_once ("book.php"); - require_once ("data.php"); - - global $config; - $expires = 60*60*24*14; - header("Pragma: public"); - header("Cache-Control: maxage=".$expires); - header('Expires: ' . gmdate('D, d M Y H:i:s', time()+$expires) . ' GMT'); - $bookId = getURLParam ("id", NULL); - $type = getURLParam ("type", "jpg"); - $idData = getURLParam ("data", NULL); - if (is_null ($bookId)) - { - $book = Book::getBookByDataId($idData); - } - else - { - $book = Book::getBookById($bookId); - } - - switch ($type) - { - case "jpg": - header("Content-Type: image/jpeg"); - if (isset($_GET["width"])) - { - $file = $book->getFilePath ($type); - // get image size - if($size = GetImageSize($file)){ - $w = $size[0]; - $h = $size[1]; - //set new size - $nw = $_GET["width"]; - $nh = ($nw*$h)/$w; - } - else{ - //set new size - $nw = "160"; - $nh = "120"; - } - //draw the image - $src_img = imagecreatefromjpeg($file); - $dst_img = imagecreatetruecolor($nw,$nh); - imagecopyresampled($dst_img, $src_img, 0, 0, 0, 0, $nw, $nh, $w, $h);//resizing the image - imagejpeg($dst_img,null,100); - imagedestroy($src_img); - imagedestroy($dst_img); - return; - } - if (isset($_GET["height"])) - { - $file = $book->getFilePath ($type); - // get image size - if($size = GetImageSize($file)){ - $w = $size[0]; - $h = $size[1]; - //set new size - $nh = $_GET["height"]; - $nw = ($nh*$w)/$h; - } - else{ - //set new size - $nw = "160"; - $nh = "120"; - } - //draw the image - $src_img = imagecreatefromjpeg($file); - $dst_img = imagecreatetruecolor($nw,$nh); - imagecopyresampled($dst_img, $src_img, 0, 0, 0, 0, $nw, $nh, $w, $h);//resizing the image - imagejpeg($dst_img,null,100); - imagedestroy($src_img); - imagedestroy($dst_img); - return; - } - break; - default: - header("Content-Type: " . Data::$mimetypes[$type]); - break; - } - $file = $book->getFilePath ($type, $idData, true); - if ($type == "epub" && $config['cops_update_epub-metadata']) - { - $book->getUpdatedEpub ($idData); + +require_once dirname(__FILE__) . '/config.php'; +require_once dirname(__FILE__) . '/base.php'; +/** @var array $config */ + +initURLParam(); + +global $config; + +if ($config['cops_fetch_protect'] == '1') { + session_start(); + if (!isset($_SESSION['connected'])) { + notFound(); return; } - if ($type == "jpg") { - header('Content-Disposition: filename="' . basename ($file) . '"'); +} +// clean output buffers before sending the ebook data do avoid high memory usage on big ebooks (ie. comic books) +if (ob_get_length() !== false) { + ob_end_clean(); +} + +$expires = 60*60*24*14; +header('Pragma: public'); +header('Cache-Control: max-age=' . $expires); +header('Expires: ' . gmdate('D, d M Y H:i:s', time()+$expires) . ' GMT'); +$bookId = getURLParam('id', null); +$type = getURLParam('type', 'jpg'); +$idData = getURLParam('data', null); +$viewOnly = getURLParam('view', false); + +if (is_null($bookId)) { + $book = Book::getBookByDataId($idData); +} else { + $book = Book::getBookById($bookId); +} + +if (!$book) { + notFound(); + return; +} + +// -DC- Add png type +if ($book && ($type == 'jpg' || $type == 'png' || empty($config['calibre_internal_directory']))) { + if ($type == 'jpg' || $type == 'png') { + $file = $book->getFilePath($type); } else { - header('Content-Disposition: attachment; filename="' . basename ($file) . '"'); + $file = $book->getFilePath($type, $idData); } - - $dir = $config['calibre_internal_directory']; - if (empty ($config['calibre_internal_directory'])) { - $dir = $config['calibre_directory']; - } - - if (empty ($config['cops_x_accel_redirect'])) { - $filename = $dir . $file; - $fp = fopen($filename, 'rb'); - header("Content-Length: " . filesize($filename)); - fpassthru($fp); - } - else { - header ($config['cops_x_accel_redirect'] . ": " . $dir . $file); + if (is_null($file) || !file_exists($file)) { + notFound(); + return; } -?> \ No newline at end of file +} + +switch ($type) { + // -DC- Add png type + case 'jpg': + case 'png': + if ($type == 'jpg') { + header('Content-Type: image/jpeg'); + } else { + header('Content-Type: image/png'); + } + //by default, we don't cache + $thumbnailCacheFullpath = null; + if (isset($config['cops_thumbnail_cache_directory']) && $config['cops_thumbnail_cache_directory'] !== '') { + $thumbnailCacheFullpath = $config['cops_thumbnail_cache_directory']; + //if multiple databases, add a subfolder with the database ID + $thumbnailCacheFullpath .= !is_null(GetUrlParam(DB)) ? 'db-' . GetUrlParam(DB) . DIRECTORY_SEPARATOR : ''; + //when there are lots of thumbnails, it's better to save files in subfolders, so if the book's uuid is + //"01234567-89ab-cdef-0123-456789abcdef", we will save the thumbnail in .../0/12/34567-89ab-cdef-0123-456789abcdef-... + $thumbnailCacheFullpath .= substr($book->uuid, 0, 1) . DIRECTORY_SEPARATOR . substr($book->uuid, 1, 2) . DIRECTORY_SEPARATOR; + //check if cache folder exists or create it + if (file_exists($thumbnailCacheFullpath) || mkdir($thumbnailCacheFullpath, 0700, true)) { + //we name the thumbnail from the book's uuid and it's dimensions (width and/or height) + $thumbnailCacheName = substr($book->uuid, 3) . '-' . getURLParam('width') . 'x' . getURLParam('height') . '.' . $type; + $thumbnailCacheFullpath = $thumbnailCacheFullpath . $thumbnailCacheName; + } else { + //error creating the folder, so we don't cache + $thumbnailCacheFullpath = null; + } + } + + if ($thumbnailCacheFullpath !== null && file_exists($thumbnailCacheFullpath)) { + //return the already cached thumbnail + readfile($thumbnailCacheFullpath); + return; + } + + $width = getURLParam('width'); + $height = getURLParam('height'); + if ($book->getThumbnail($width, $height, $thumbnailCacheFullpath, $type)) { + //if we don't cache the thumbnail, imagejpeg() in $book->getThumbnail() already return the image data + if ($thumbnailCacheFullpath === null) { + // The cover had to be resized + return; + } else { + //return the just cached thumbnail + readfile($thumbnailCacheFullpath); + return; + } + } + break; + default: + $data = $book->getDataById($idData); + header('Content-Type: ' . $data->getMimeType()); + break; +} + +// absolute path for single DB in PHP app here - cfr. internal dir for X-Accel-Redirect with Nginx +$file = $book->getFilePath($type, $idData, false); +if (!$viewOnly && $type == 'epub' && $config['cops_update_epub-metadata']) { + $book->getUpdatedEpub($idData); + return; +} +// -DC- Add png type +if ($type == 'jpg' || $type == 'png') { + header('Content-Disposition: filename="' . basename($file) . '"'); +} elseif ($viewOnly) { + header('Content-Disposition: inline'); +} else { + header('Content-Disposition: attachment; filename="' . basename($file) . '"'); +} + +// -DC- File is a full path +//$dir = $config['calibre_internal_directory']; +//if (empty($config['calibre_internal_directory'])) { + // $dir = Base::getDbDirectory(); +//} +$dir = ''; + +if (empty($config['cops_x_accel_redirect'])) { + $filename = $dir . $file; + header('Content-Length: ' . filesize($filename)); + readfile($filename); +} else { + header($config['cops_x_accel_redirect'] . ': ' . $dir . $file); +} +exit(); diff --git a/getJSON.php b/getJSON.php new file mode 100644 index 000000000..ed9ea603b --- /dev/null +++ b/getJSON.php @@ -0,0 +1,18 @@ + + * + */ + +require_once dirname(__FILE__) . '/config.php'; +require_once dirname(__FILE__) . '/base.php'; +/** @var array $config */ + +initURLParam(); + +header('Content-Type:application/json;charset=utf-8'); + +echo json_encode(JSONRenderer::getJson()); diff --git a/images/Link.png b/images/Link.png deleted file mode 100644 index 2a5278e90..000000000 Binary files a/images/Link.png and /dev/null differ diff --git a/images/ajax-loader.gif b/images/ajax-loader.gif deleted file mode 100644 index 1560b646c..000000000 Binary files a/images/ajax-loader.gif and /dev/null differ diff --git a/images/allbook.png b/images/allbook.png index 7d863f949..680317168 100644 Binary files a/images/allbook.png and b/images/allbook.png differ diff --git a/images/author.png b/images/author.png index 79f35ccbd..5c09d1a27 100644 Binary files a/images/author.png and b/images/author.png differ diff --git a/images/bookcover.png b/images/bookcover.png new file mode 100644 index 000000000..6c3c8c743 Binary files /dev/null and b/images/bookcover.png differ diff --git a/images/custom.png b/images/custom.png new file mode 100644 index 000000000..86020c34a Binary files /dev/null and b/images/custom.png differ diff --git a/images/home.png b/images/home.png deleted file mode 100644 index c3bfde92e..000000000 Binary files a/images/home.png and /dev/null differ diff --git a/images/icons/icon114.png b/images/icons/icon114.png new file mode 100644 index 000000000..677ec79a0 Binary files /dev/null and b/images/icons/icon114.png differ diff --git a/images/icons/icon144.png b/images/icons/icon144.png new file mode 100644 index 000000000..facdfe1e7 Binary files /dev/null and b/images/icons/icon144.png differ diff --git a/images/icons/icon57.png b/images/icons/icon57.png new file mode 100644 index 000000000..a1609bbfe Binary files /dev/null and b/images/icons/icon57.png differ diff --git a/images/icons/icon72.png b/images/icons/icon72.png new file mode 100644 index 000000000..eb9735789 Binary files /dev/null and b/images/icons/icon72.png differ diff --git a/images/info.png b/images/info.png deleted file mode 100644 index 5f9894bc3..000000000 Binary files a/images/info.png and /dev/null differ diff --git a/images/language.png b/images/language.png new file mode 100644 index 000000000..5b18b4fa3 Binary files /dev/null and b/images/language.png differ diff --git a/images/next.png b/images/next.png deleted file mode 100644 index d258ec23e..000000000 Binary files a/images/next.png and /dev/null differ diff --git a/images/previous.png b/images/previous.png deleted file mode 100644 index e41d47260..000000000 Binary files a/images/previous.png and /dev/null differ diff --git a/images/publisher.png b/images/publisher.png new file mode 100644 index 000000000..f34b24fc3 Binary files /dev/null and b/images/publisher.png differ diff --git a/images/rating.png b/images/rating.png new file mode 100644 index 000000000..68c53c542 Binary files /dev/null and b/images/rating.png differ diff --git a/images/recent.png b/images/recent.png index 783c83357..e792a20a4 100644 Binary files a/images/recent.png and b/images/recent.png differ diff --git a/images/search32.png b/images/search32.png deleted file mode 100644 index 7f3e5feb4..000000000 Binary files a/images/search32.png and /dev/null differ diff --git a/images/serie.png b/images/serie.png index 0f9ed4d48..fcf414056 100644 Binary files a/images/serie.png and b/images/serie.png differ diff --git a/images/setting64.png b/images/setting64.png deleted file mode 100644 index 7bdc3ac96..000000000 Binary files a/images/setting64.png and /dev/null differ diff --git a/images/sort32.png b/images/sort32.png deleted file mode 100644 index 0e6c5c9e3..000000000 Binary files a/images/sort32.png and /dev/null differ diff --git a/images/tag.png b/images/tag.png index 9757fc6ed..746d2364e 100644 Binary files a/images/tag.png and b/images/tag.png differ diff --git a/index.php b/index.php index 7f862ec49..e18aa096b 100644 --- a/index.php +++ b/index.php @@ -3,299 +3,67 @@ * COPS (Calibre OPDS PHP Server) HTML main script * * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) - * @author Sbastien Lucas + * @author Sébastien Lucas * */ - - require_once ("config.php"); - require_once ("base.php"); - require_once ("author.php"); - require_once ("serie.php"); - require_once ("tag.php"); - require_once ("customcolumn.php"); - require_once ("book.php"); - - // If we detect that an OPDS reader try to connect try to redirect to feed.php - if (preg_match("/(MantanoReader|FBReader|Stanza|Aldiko|Moon+ Reader)/", $_SERVER['HTTP_USER_AGENT'])) { - header("location: feed.php"); - exit (); - } - - $withToolbar = false; - if (!isset($_COOKIE['toolbar'])) $withToolbar = true; - - header ("Content-Type:application/xhtml+xml"); - $page = getURLParam ("page", Base::PAGE_INDEX); - $query = getURLParam ("query"); - $qid = getURLParam ("id"); - $n = getURLParam ("n", "1"); - - $currentPage = Page::getPage ($page, $qid, $query, $n); - $currentPage->InitializeContent (); -/* Test to see if pages are opened on an Eink screen - * test Kindle, Kobo Touch and Sony PRS-T1 Ereader. - * HTTP_USER_AGENT = "Mozilla/5.0 (Linux; U; en-us; EBRD1101; EXT) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1" - */ +require_once dirname(__FILE__) . '/config.php'; +require_once dirname(__FILE__) . '/base.php'; +/** @var array $config */ - if (preg_match("/(Kobo|Kindle\/3.0|EBRD1101)/", $_SERVER['HTTP_USER_AGENT'])) { - $isEink = 1; - } else { - $isEink = 0; - } +// If we detect that an OPDS reader try to connect try to redirect to feed.php +if (preg_match('/(MantanoReader|FBReader|Stanza|Marvin|Aldiko|Moon\+ Reader|Chunky|AlReader|EBookDroid|BookReader|CoolReader|PageTurner|books\.ebook\.pdf\.reader|com\.hiwapps\.ebookreader|OpenBook)/', $_SERVER['HTTP_USER_AGENT'])) { + header('location: feed.php'); + exit(); +} +initURLParam(); -?> - - - - - - <?php echo htmlspecialchars ($currentPage->title) ?> - - - - - - - - " media="screen" /> - - - - - -
    -

    waiting Please Wait

    -
    -
    -
    - "> - " alt="Home" /> - - " alt="Settings and menu" /> -

    title) ?>

    -
    - - -
    - entryArray as $entry) { - if (get_class ($entry) != "EntryBook") { - ?> - - - - - -
    -
    - " alt="Home" /> -isPaginated ()) { -?> +} -
    - - " alt="Previous" /> - -

    n . " / " . $currentPage->getMaxPage () . " " ?>

    - - " alt="Next" /> - -
    +header('Content-Type:text/html;charset=utf-8'); + +$data = ['title' => $config['cops_title_default'], + 'version' => VERSION, + 'opds_url' => $config['cops_full_url'] . 'feed.php', + 'customHeader' => '', + 'template' => getCurrentTemplate(), + 'server_side_rendering' => useServerSideRendering(), + 'current_css' => getCurrentCss(), + 'favico' => $config['cops_icon'], + 'getjson_url' => 'getJSON.php?' . addURLParameter(getQueryString(), 'complete', 1)]; +if (preg_match('/Kindle/', $_SERVER['HTTP_USER_AGENT'])) { + $data['customHeader'] = ''; +} +$headcontent = file_get_contents('templates/' . getCurrentTemplate() . '/file.html'); +$template = new doT(); +$dot = $template->template($headcontent, null); +echo($dot($data)); +?> -
    -
    diff --git a/js/jquery.cookies.js b/js/jquery.cookies.js deleted file mode 100644 index 0321fcedb..000000000 --- a/js/jquery.cookies.js +++ /dev/null @@ -1,10 +0,0 @@ -/*! - * jQuery Cookie Plugin - * https://github.com/carhartl/jquery-cookie - * Copyright 2011, Klaus Hartl - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://www.opensource.org/licenses/mit-license.php - * http://www.opensource.org/licenses/GPL-2.0 - * Last update: Sun, 03 Mar 2013 06:56:32 +0000 - */ -(function(factory){if(typeof define==='function'&&define.amd){define(['jquery'],factory)}else{factory(jQuery)}}(function($){var pluses=/\+/g;function raw(s){return s}function decoded(s){return decodeURIComponent(s.replace(pluses,' '))}function converted(s){if(s.indexOf('"')===0){s=s.slice(1,-1).replace(/\\"/g, '"').replace(/\\\\/g,'\\');}try{return config.json?JSON.parse(s):s}catch(er){}}var config=$.cookie=function(key,value,options){if(value!==undefined){options=$.extend({},config.defaults,options);if(typeof options.expires==='number'){var days=options.expires,t=options.expires=new Date();t.setDate(t.getDate()+days)}value=config.json?JSON.stringify(value):String(value);return(document.cookie=[config.raw?key:encodeURIComponent(key),'=',config.raw?value:encodeURIComponent(value),options.expires?'; expires='+options.expires.toUTCString():'',options.path?'; path='+options.path:'',options.domain?'; domain='+options.domain:'',options.secure?'; secure':''].join(''))}var decode=config.raw?raw:decoded;var cookies=document.cookie.split('; ');var result=key?undefined:{};for(var i=0,l=cookies.length;i + */ + +class Author extends Base +{ + public const ALL_AUTHORS_ID = "cops:authors"; + + public const AUTHOR_COLUMNS = "authors.id as id, authors.name as name, authors.sort as sort, count(*) as count"; + public const SQL_AUTHORS_BY_FIRST_LETTER = "select {0} from authors, books_authors_link where author = authors.id and upper (authors.sort) like ? group by authors.id, authors.name, authors.sort order by sort"; + public const SQL_AUTHORS_FOR_SEARCH = "select {0} from authors, books_authors_link where author = authors.id and (upper (authors.sort) like ? or upper (authors.name) like ?) group by authors.id, authors.name, authors.sort order by sort"; + public const SQL_ALL_AUTHORS = "select {0} from authors, books_authors_link where author = authors.id group by authors.id, authors.name, authors.sort order by sort"; + + public $id; + public $name; + public $sort; + + public function __construct($post) + { + $this->id = $post->id; + $this->name = str_replace("|", ",", $post->name); + $this->sort = $post->sort; + } + + public function getUri() + { + return "?page=".parent::PAGE_AUTHOR_DETAIL."&id=$this->id"; + } + + public function getEntryId() + { + return self::ALL_AUTHORS_ID.":".$this->id; + } + + public static function getEntryIdByLetter($startingLetter) + { + return self::ALL_AUTHORS_ID.":letter:".$startingLetter; + } + + public static function getCount() + { + // str_format (localize("authors.alphabetical", count(array)) + return parent::getCountGeneric("authors", self::ALL_AUTHORS_ID, parent::PAGE_ALL_AUTHORS); + } + + public static function getAllAuthorsByFirstLetter() + { + [, $result] = parent::executeQuery("select {0} +from authors +group by substr (upper (sort), 1, 1) +order by substr (upper (sort), 1, 1)", "substr (upper (sort), 1, 1) as title, count(*) as count", "", [], -1); + $entryArray = []; + while ($post = $result->fetchObject()) { + array_push($entryArray, new Entry( + $post->title, + Author::getEntryIdByLetter($post->title), + str_format(localize("authorword", $post->count), $post->count), + "text", + [ new LinkNavigation("?page=".parent::PAGE_AUTHORS_FIRST_LETTER."&id=". rawurlencode($post->title))], + "", + $post->count + )); + } + return $entryArray; + } + + public static function getAuthorsByStartingLetter($letter) + { + return self::getEntryArray(self::SQL_AUTHORS_BY_FIRST_LETTER, [$letter . "%"]); + } + + public static function getAuthorsForSearch($query) + { + return self::getEntryArray(self::SQL_AUTHORS_FOR_SEARCH, [$query . "%", $query . "%"]); + } + + public static function getAllAuthors() + { + return self::getEntryArray(self::SQL_ALL_AUTHORS, []); + } + + public static function getEntryArray($query, $params) + { + return Base::getEntryArrayWithBookNumber($query, self::AUTHOR_COLUMNS, $params, "Author"); + } + + public static function getAuthorById($authorId) + { + $result = parent::getDb()->prepare('select ' . self::AUTHOR_COLUMNS . ' from authors where id = ?'); + $result->execute([$authorId]); + $post = $result->fetchObject(); + return new Author($post); + } + + public static function getAuthorByBookId($bookId) + { + $result = parent::getDb()->prepare('select authors.id as id, authors.name as name, authors.sort as sort from authors, books_authors_link +where author = authors.id +and book = ? order by books_authors_link.id'); + $result->execute([$bookId]); + $authorArray = []; + while ($post = $result->fetchObject()) { + array_push($authorArray, new Author($post)); + } + return $authorArray; + } +} diff --git a/lib/Base.php b/lib/Base.php new file mode 100644 index 000000000..6320f6b44 --- /dev/null +++ b/lib/Base.php @@ -0,0 +1,257 @@ + + */ + +abstract class Base +{ + public const PAGE_INDEX = "index"; + public const PAGE_ALL_AUTHORS = "1"; + public const PAGE_AUTHORS_FIRST_LETTER = "2"; + public const PAGE_AUTHOR_DETAIL = "3"; + public const PAGE_ALL_BOOKS = "4"; + public const PAGE_ALL_BOOKS_LETTER = "5"; + public const PAGE_ALL_SERIES = "6"; + public const PAGE_SERIE_DETAIL = "7"; + public const PAGE_OPENSEARCH = "8"; + public const PAGE_OPENSEARCH_QUERY = "9"; + public const PAGE_ALL_RECENT_BOOKS = "10"; + public const PAGE_ALL_TAGS = "11"; + public const PAGE_TAG_DETAIL = "12"; + public const PAGE_BOOK_DETAIL = "13"; + public const PAGE_ALL_CUSTOMS = "14"; + public const PAGE_CUSTOM_DETAIL = "15"; + public const PAGE_ABOUT = "16"; + public const PAGE_ALL_LANGUAGES = "17"; + public const PAGE_LANGUAGE_DETAIL = "18"; + public const PAGE_CUSTOMIZE = "19"; + public const PAGE_ALL_PUBLISHERS = "20"; + public const PAGE_PUBLISHER_DETAIL = "21"; + public const PAGE_ALL_RATINGS = "22"; + public const PAGE_RATING_DETAIL = "23"; + + public const COMPATIBILITY_XML_ALDIKO = "aldiko"; + + private static $db = null; + + public static function isMultipleDatabaseEnabled() + { + global $config; + return is_array($config['calibre_directory']); + } + + public static function useAbsolutePath() + { + global $config; + $path = self::getDbDirectory(); + return preg_match('/^\//', $path) || // Linux / + preg_match('/^\w\:/', $path); // Windows X: + } + + public static function noDatabaseSelected() + { + return self::isMultipleDatabaseEnabled() && is_null(GetUrlParam(DB)); + } + + public static function getDbList() + { + global $config; + if (self::isMultipleDatabaseEnabled()) { + return $config['calibre_directory']; + } else { + return ["" => $config['calibre_directory']]; + } + } + + public static function getDbNameList() + { + global $config; + if (self::isMultipleDatabaseEnabled()) { + return array_keys($config['calibre_directory']); + } else { + return [""]; + } + } + + public static function getDbName($database = null) + { + global $config; + if (self::isMultipleDatabaseEnabled()) { + if (is_null($database)) { + $database = GetUrlParam(DB, 0); + } + if (!is_null($database) && !preg_match('/^\d+$/', $database)) { + self::error($database); + } + $array = array_keys($config['calibre_directory']); + return $array[$database]; + } + return ""; + } + + public static function getDbDirectory($database = null) + { + global $config; + if (self::isMultipleDatabaseEnabled()) { + if (is_null($database)) { + $database = GetUrlParam(DB, 0); + } + if (!is_null($database) && !preg_match('/^\d+$/', $database)) { + self::error($database); + } + $array = array_values($config['calibre_directory']); + return $array[$database]; + } + return $config['calibre_directory']; + } + + // -DC- Add image directory + public static function getImgDirectory($database = null) + { + global $config; + if (self::isMultipleDatabaseEnabled()) { + if (is_null($database)) { + $database = GetUrlParam(DB, 0); + } + $array = array_values($config['image_directory']); + return $array[$database]; + } + return $config['image_directory']; + } + + public static function getDbFileName($database = null) + { + return self::getDbDirectory($database) .'metadata.db'; + } + + private static function error($database) + { + if (php_sapi_name() != "cli") { + header("location: checkconfig.php?err=1"); + } + throw new Exception("Database <{$database}> not found."); + } + + public static function getDb($database = null) + { + if (is_null(self::$db)) { + try { + if (is_readable(self::getDbFileName($database))) { + self::$db = new PDO('sqlite:'. self::getDbFileName($database)); + if (useNormAndUp()) { + self::$db->sqliteCreateFunction('normAndUp', 'normAndUp', 1); + } + } else { + self::error($database); + } + } catch (Exception $e) { + self::error($database); + } + } + return self::$db; + } + + public static function checkDatabaseAvailability() + { + if (self::noDatabaseSelected()) { + for ($i = 0; $i < count(self::getDbList()); $i++) { + self::getDb($i); + self::clearDb(); + } + } else { + self::getDb(); + } + return true; + } + + public static function clearDb() + { + self::$db = null; + } + + public static function executeQuerySingle($query, $database = null) + { + return self::getDb($database)->query($query)->fetchColumn(); + } + + public static function getCountGeneric($table, $id, $pageId, $numberOfString = null) + { + if (!$numberOfString) { + $numberOfString = $table . ".alphabetical"; + } + $count = self::executeQuerySingle('select count(*) from ' . $table); + if ($count == 0) { + return null; + } + $entry = new Entry( + localize($table . ".title"), + $id, + str_format(localize($numberOfString, $count), $count), + "text", + [ new LinkNavigation("?page=".$pageId)], + "", + $count + ); + return $entry; + } + + public static function getEntryArrayWithBookNumber($query, $columns, $params, $category) + { + /* @var $result PDOStatement */ + + [, $result] = self::executeQuery($query, $columns, "", $params, -1); + $entryArray = []; + while ($post = $result->fetchObject()) { + /* @var $instance Author|Tag|Serie|Publisher */ + + $instance = new $category($post); + if (property_exists($post, "sort")) { + $title = $post->sort; + } else { + $title = $post->name; + } + array_push($entryArray, new Entry( + $title, + $instance->getEntryId(), + str_format(localize("bookword", $post->count), $post->count), + "text", + [ new LinkNavigation($instance->getUri())], + "", + $post->count + )); + } + return $entryArray; + } + + public static function executeQuery($query, $columns, $filter, $params, $n, $database = null, $numberPerPage = null) + { + $totalResult = -1; + + if (useNormAndUp()) { + $query = preg_replace("/upper/", "normAndUp", $query); + $columns = preg_replace("/upper/", "normAndUp", $columns); + } + + if (is_null($numberPerPage)) { + $numberPerPage = getCurrentOption("max_item_per_page"); + } + + if ($numberPerPage != -1 && $n != -1) { + // First check total number of results + $result = self::getDb($database)->prepare(str_format($query, "count(*)", $filter)); + $result->execute($params); + $totalResult = $result->fetchColumn(); + + // Next modify the query and params + $query .= " limit ?, ?"; + array_push($params, ($n - 1) * $numberPerPage, $numberPerPage); + } + + $result = self::getDb($database)->prepare(str_format($query, $columns, $filter)); + $result->execute($params); + return [$totalResult, $result]; + } +} diff --git a/lib/Book.php b/lib/Book.php new file mode 100644 index 000000000..cd4853175 --- /dev/null +++ b/lib/Book.php @@ -0,0 +1,843 @@ + + */ + +// Silly thing because PHP forbid string concatenation in class const +define('SQL_BOOKS_LEFT_JOIN', 'left outer join comments on comments.book = books.id + left outer join books_ratings_link on books_ratings_link.book = books.id + left outer join ratings on books_ratings_link.rating = ratings.id '); +define('SQL_BOOKS_ALL', 'select {0} from books ' . SQL_BOOKS_LEFT_JOIN . ' order by books.sort '); +define('SQL_BOOKS_BY_PUBLISHER', 'select {0} from books_publishers_link, books ' . SQL_BOOKS_LEFT_JOIN . ' + where books_publishers_link.book = books.id and publisher = ? {1} order by publisher'); +define('SQL_BOOKS_BY_FIRST_LETTER', 'select {0} from books ' . SQL_BOOKS_LEFT_JOIN . ' + where upper (books.sort) like ? order by books.sort'); +define('SQL_BOOKS_BY_AUTHOR', 'select {0} from books_authors_link, books ' . SQL_BOOKS_LEFT_JOIN . ' + left outer join books_series_link on books_series_link.book = books.id + where books_authors_link.book = books.id and author = ? {1} order by series desc, series_index asc, pubdate asc'); +define('SQL_BOOKS_BY_SERIE', 'select {0} from books_series_link, books ' . SQL_BOOKS_LEFT_JOIN . ' + where books_series_link.book = books.id and series = ? {1} order by series_index'); +define('SQL_BOOKS_BY_TAG', 'select {0} from books_tags_link, books ' . SQL_BOOKS_LEFT_JOIN . ' + where books_tags_link.book = books.id and tag = ? {1} order by sort'); +define('SQL_BOOKS_BY_LANGUAGE', 'select {0} from books_languages_link, books ' . SQL_BOOKS_LEFT_JOIN . ' + where books_languages_link.book = books.id and lang_code = ? {1} order by sort'); +define('SQL_BOOKS_BY_CUSTOM', 'select {0} from {2}, books ' . SQL_BOOKS_LEFT_JOIN . ' + where {2}.book = books.id and {2}.{3} = ? {1} order by sort'); +define('SQL_BOOKS_BY_CUSTOM_BOOL_TRUE', 'select {0} from {2}, books ' . SQL_BOOKS_LEFT_JOIN . ' + where {2}.book = books.id and {2}.value = 1 {1} order by sort'); +define('SQL_BOOKS_BY_CUSTOM_BOOL_FALSE', 'select {0} from {2}, books ' . SQL_BOOKS_LEFT_JOIN . ' + where {2}.book = books.id and {2}.value = 0 {1} order by sort'); +define('SQL_BOOKS_BY_CUSTOM_BOOL_NULL', 'select {0} from books ' . SQL_BOOKS_LEFT_JOIN . ' + where books.id not in (select book from {2}) {1} order by sort'); +define('SQL_BOOKS_BY_CUSTOM_RATING', 'select {0} from books ' . SQL_BOOKS_LEFT_JOIN . ' + left join {2} on {2}.book = books.id + left join {3} on {3}.id = {2}.{4} + where {3}.value = ? order by sort'); +define('SQL_BOOKS_BY_CUSTOM_RATING_NULL', 'select {0} from books ' . SQL_BOOKS_LEFT_JOIN . ' + left join {2} on {2}.book = books.id + left join {3} on {3}.id = {2}.{4} + where ((books.id not in (select {2}.book from {2})) or ({3}.value = 0)) {1} order by sort'); +define('SQL_BOOKS_BY_CUSTOM_DATE', 'select {0} from {2}, books ' . SQL_BOOKS_LEFT_JOIN . ' + where {2}.book = books.id and date({2}.value) = ? {1} order by sort'); +define('SQL_BOOKS_BY_CUSTOM_DIRECT', 'select {0} from {2}, books ' . SQL_BOOKS_LEFT_JOIN . ' + where {2}.book = books.id and {2}.value = ? {1} order by sort'); +define('SQL_BOOKS_BY_CUSTOM_DIRECT_ID', 'select {0} from {2}, books ' . SQL_BOOKS_LEFT_JOIN . ' + where {2}.book = books.id and {2}.id = ? {1} order by sort'); +define('SQL_BOOKS_QUERY', 'select {0} from books ' . SQL_BOOKS_LEFT_JOIN . ' + where ( + exists (select null from authors, books_authors_link where book = books.id and author = authors.id and authors.name like ?) or + exists (select null from tags, books_tags_link where book = books.id and tag = tags.id and tags.name like ?) or + exists (select null from series, books_series_link on book = books.id and books_series_link.series = series.id and series.name like ?) or + exists (select null from publishers, books_publishers_link where book = books.id and books_publishers_link.publisher = publishers.id and publishers.name like ?) or + title like ?) {1} order by books.sort'); +define('SQL_BOOKS_RECENT', 'select {0} from books ' . SQL_BOOKS_LEFT_JOIN . ' + where 1=1 {1} order by timestamp desc limit '); +define('SQL_BOOKS_BY_RATING', 'select {0} from books ' . SQL_BOOKS_LEFT_JOIN . ' + where books_ratings_link.book = books.id and ratings.id = ? {1} order by sort'); + +require('Identifier.php'); + +class Book extends Base +{ + public const ALL_BOOKS_UUID = 'urn:uuid'; + public const ALL_BOOKS_ID = 'cops:books'; + public const ALL_RECENT_BOOKS_ID = 'cops:recentbooks'; + public const BOOK_COLUMNS = 'books.id as id, books.title as title, text as comment, path, timestamp, pubdate, series_index, uuid, has_cover, ratings.rating'; + + public const SQL_BOOKS_LEFT_JOIN = SQL_BOOKS_LEFT_JOIN; + public const SQL_BOOKS_ALL = SQL_BOOKS_ALL; + public const SQL_BOOKS_BY_PUBLISHER = SQL_BOOKS_BY_PUBLISHER; + public const SQL_BOOKS_BY_FIRST_LETTER = SQL_BOOKS_BY_FIRST_LETTER; + public const SQL_BOOKS_BY_AUTHOR = SQL_BOOKS_BY_AUTHOR; + public const SQL_BOOKS_BY_SERIE = SQL_BOOKS_BY_SERIE; + public const SQL_BOOKS_BY_TAG = SQL_BOOKS_BY_TAG; + public const SQL_BOOKS_BY_LANGUAGE = SQL_BOOKS_BY_LANGUAGE; + public const SQL_BOOKS_BY_CUSTOM = SQL_BOOKS_BY_CUSTOM; + public const SQL_BOOKS_BY_CUSTOM_BOOL_TRUE = SQL_BOOKS_BY_CUSTOM_BOOL_TRUE; + public const SQL_BOOKS_BY_CUSTOM_BOOL_FALSE = SQL_BOOKS_BY_CUSTOM_BOOL_FALSE; + public const SQL_BOOKS_BY_CUSTOM_BOOL_NULL = SQL_BOOKS_BY_CUSTOM_BOOL_NULL; + public const SQL_BOOKS_BY_CUSTOM_RATING = SQL_BOOKS_BY_CUSTOM_RATING; + public const SQL_BOOKS_BY_CUSTOM_RATING_NULL = SQL_BOOKS_BY_CUSTOM_RATING_NULL; + public const SQL_BOOKS_BY_CUSTOM_DATE = SQL_BOOKS_BY_CUSTOM_DATE; + public const SQL_BOOKS_BY_CUSTOM_DIRECT = SQL_BOOKS_BY_CUSTOM_DIRECT; + public const SQL_BOOKS_BY_CUSTOM_DIRECT_ID = SQL_BOOKS_BY_CUSTOM_DIRECT_ID; + public const SQL_BOOKS_QUERY = SQL_BOOKS_QUERY; + public const SQL_BOOKS_RECENT = SQL_BOOKS_RECENT; + public const SQL_BOOKS_BY_RATING = SQL_BOOKS_BY_RATING; + + public const BAD_SEARCH = 'QQQQQ'; + + public $id; + public $title; + public $timestamp; + public $pubdate; + public $path; + public $uuid; + public $hasCover; + public $relativePath; + public $seriesIndex; + public $comment; + public $rating; + public $datas = null; + public $authors = null; + public $publisher = null; + public $serie = null; + public $tags = null; + public $identifiers = null; + public $languages = null; + public $format = []; + private $coverFileName = null; + + public function __construct($line) + { + global $config; + + $this->id = $line->id; + $this->title = $line->title; + $this->timestamp = strtotime($line->timestamp); + $this->pubdate = $line->pubdate; + //$this->path = Base::getDbDirectory() . $line->path; + //$this->relativePath = $line->path; + // -DC- Init relative or full path + $this->path = $line->path; + if (!is_dir($this->path)) { + $this->path = Base::getDbDirectory() . $line->path; + } + $this->seriesIndex = $line->series_index; + $this->comment = $line->comment ?? ''; + $this->uuid = $line->uuid; + $this->hasCover = $line->has_cover; + // -DC- Use cover file name + //if (!file_exists($this->getFilePath('jpg'))) { + // // double check + // $this->hasCover = 0; + //} + if ($this->hasCover) { + if (!empty($config['calibre_database_field_cover'])) { + $imgDirectory = Base::getImgDirectory(); + $this->coverFileName = $line->cover; + if (!file_exists($this->coverFileName)) { + $this->coverFileName = null; + } + if (empty($this->coverFileName)) { + $this->coverFileName = sprintf('%s%s', $imgDirectory, $line->cover); + if (!file_exists($this->coverFileName)) { + $this->coverFileName = null; + } + } + if (empty($this->coverFileName)) { + // Try with the epub file name + $data = $this->getDataFormat('EPUB'); + if ($data) { + $this->coverFileName = sprintf('%s%s/%s', $imgDirectory, $data->name, $line->cover); + if (!file_exists($this->coverFileName)) { + $this->coverFileName = null; + } + if (empty($this->coverFileName)) { + $this->coverFileName = sprintf('%s%s.jpg', $imgDirectory, $data->name); + if (!file_exists($this->coverFileName)) { + $this->coverFileName = null; + } + } + } + } + } + // Else try with default cover file name + if (empty($this->coverFileName)) { + $cover = $this->getFilePath("jpg"); + if ($cover === false || !file_exists($cover)) { + $cover = $this->getFilePath("png"); + } + if ($cover === false || !file_exists($cover)) { + $this->hasCover = 0; + } else { + $this->coverFileName = $cover; + } + } + } + $this->rating = $line->rating; + } + + // -DC- Get customisable book columns + private static function getBookColumns() + { + global $config; + + $res = self::BOOK_COLUMNS; + if (!empty($config['calibre_database_field_cover'])) { + $res = str_replace('has_cover,', 'has_cover, ' . $config['calibre_database_field_cover'] . ',', $res); + } + + return $res; + } + + public function getEntryId() + { + return self::ALL_BOOKS_UUID.':'.$this->uuid; + } + + public static function getEntryIdByLetter($startingLetter) + { + return self::ALL_BOOKS_ID.':letter:'.$startingLetter; + } + + public function getUri() + { + return '?page='.parent::PAGE_BOOK_DETAIL.'&id=' . $this->id; + } + + public function getDetailUrl() + { + $urlParam = $this->getUri(); + if (!is_null(GetUrlParam(DB))) { + $urlParam = addURLParameter($urlParam, DB, GetUrlParam(DB)); + } + return 'index.php' . $urlParam; + } + + public function getTitle() + { + return $this->title; + } + + /* Other class (author, series, tag, ...) initialization and accessors */ + + /** + * @return Author[] + */ + public function getAuthors() + { + if (is_null($this->authors)) { + $this->authors = Author::getAuthorByBookId($this->id); + } + return $this->authors; + } + + public function getAuthorsName() + { + return implode(', ', array_map(function ($author) { + return $author->name; + }, $this->getAuthors())); + } + + public function getAuthorsSort() + { + return implode(', ', array_map(function ($author) { + return $author->sort; + }, $this->getAuthors())); + } + + public function getPublisher() + { + if (is_null($this->publisher)) { + $this->publisher = Publisher::getPublisherByBookId($this->id); + } + return $this->publisher; + } + + /** + * @return Serie + */ + public function getSerie() + { + if (is_null($this->serie)) { + $this->serie = Serie::getSerieByBookId($this->id); + } + return $this->serie; + } + + /** + * @return string + */ + public function getLanguages() + { + $lang = []; + $result = parent::getDb()->prepare('select languages.lang_code + from books_languages_link, languages + where books_languages_link.lang_code = languages.id + and book = ? + order by item_order'); + $result->execute([$this->id]); + while ($post = $result->fetchObject()) { + array_push($lang, Language::getLanguageString($post->lang_code)); + } + return implode(', ', $lang); + } + + /** + * @return Tag[] + */ + public function getTags() + { + if (is_null($this->tags)) { + $this->tags = []; + + $result = parent::getDb()->prepare('select tags.id as id, name + from books_tags_link, tags + where tag = tags.id + and book = ? + order by name'); + $result->execute([$this->id]); + while ($post = $result->fetchObject()) { + array_push($this->tags, new Tag($post)); + } + } + return $this->tags; + } + + public function getTagsName() + { + return implode(', ', array_map(function ($tag) { + return $tag->name; + }, $this->getTags())); + } + + /** + * @return Identifier[] + */ + public function getIdentifiers() + { + if (is_null($this->identifiers)) { + $this->identifiers = []; + + $result = parent::getDb()->prepare('select type, val, id + from identifiers + where book = ? + order by type'); + $result->execute([$this->id]); + while ($post = $result->fetchObject()) { + array_push($this->identifiers, new Identifier($post)); + } + } + return $this->identifiers; + } + + /** + * @return Data[] + */ + public function getDatas() + { + if (is_null($this->datas)) { + $this->datas = Data::getDataByBook($this); + } + return $this->datas; + } + + /* End of other class (author, series, tag, ...) initialization and accessors */ + + public static function getFilterString() + { + $filter = getURLParam('tag', null); + if (empty($filter)) { + return ''; + } + + $exists = true; + if (preg_match("/^!(.*)$/", $filter, $matches)) { + $exists = false; + $filter = $matches[1]; + } + + $result = 'exists (select null from books_tags_link, tags where books_tags_link.book = books.id and books_tags_link.tag = tags.id and tags.name = "' . $filter . '")'; + + if (!$exists) { + $result = 'not ' . $result; + } + + return 'and ' . $result; + } + + public function GetMostInterestingDataToSendToKindle() + { + $bestFormatForKindle = ['EPUB', 'PDF', 'AZW3', 'MOBI']; + $bestRank = -1; + $bestData = null; + foreach ($this->getDatas() as $data) { + $key = array_search($data->format, $bestFormatForKindle); + if ($key !== false && $key > $bestRank) { + $bestRank = $key; + $bestData = $data; + } + } + return $bestData; + } + + public function getDataById($idData) + { + $reduced = array_filter($this->getDatas(), function ($data) use ($idData) { + return $data->id == $idData; + }); + return reset($reduced); + } + + public function getRating() + { + if (is_null($this->rating) || $this->rating == 0) { + return ''; + } + $retour = ''; + for ($i = 0; $i < $this->rating / 2; $i++) { + $retour .= '★'; // full star + } + for ($i = 0; $i < 5 - $this->rating / 2; $i++) { + $retour .= '☆'; // empty star + } + return $retour; + } + + public function getPubDate() + { + if (empty($this->pubdate)) { + return ''; + } + $dateY = (int) substr($this->pubdate, 0, 4); + if ($dateY > 102) { + return str_pad(strval($dateY), 4, '0', STR_PAD_LEFT); + } + return ''; + } + + public function getComment($withSerie = true) + { + $addition = ''; + $se = $this->getSerie(); + if (!is_null($se) && $withSerie) { + $addition = $addition . '' . localize('content.series') . '' . str_format(localize('content.series.data'), $this->seriesIndex, htmlspecialchars($se->name)) . "
    \n"; + } + //if (preg_match('/<\/(div|p|a|span)>/', $this->comment)) { + return $addition . html2xhtml($this->comment); + //} else { + // return $addition . htmlspecialchars($this->comment); + //} + } + + public function getDataFormat($format) + { + $reduced = array_filter($this->getDatas(), function ($data) use ($format) { + return $data->format == $format; + }); + return reset($reduced); + } + + /** + * @checkme always returns absolute path for single DB in PHP app here - cfr. internal dir for X-Accel-Redirect with Nginx + * @param false $relative Deprecated + */ + public function getFilePath($extension, $idData = null, $relative = false) + { + /*if ($extension == 'jpg') + { + $file = 'cover.jpg'; + } else { + $data = $this->getDataById($idData); + if (!$data) { + return null; + } + $file = $data->name . '.' . strtolower($data->format); + } + + if ($relative) { + return $this->relativePath.'/'.$file; + } else { + return $this->path.'/'.$file; + }*/ + if ($extension == "jpg" || $extension == "png") { + if (empty($this->coverFileName)) { + return $this->path . '/cover.' . $extension; + } else { + $ext = strtolower(pathinfo($this->coverFileName, PATHINFO_EXTENSION)); + if ($ext == $extension) { + return $this->coverFileName; + } + } + return false; + } else { + $data = $this->getDataById($idData); + if (!$data) { + return null; + } + $file = $data->name . "." . strtolower($data->format); + return $this->path . '/' . $file; + } + } + + public function getUpdatedEpub($idData) + { + global $config; + $data = $this->getDataById($idData); + + try { + $epub = new EPub($data->getLocalPath()); + + $epub->Title($this->title); + $authorArray = []; + foreach ($this->getAuthors() as $author) { + $authorArray[$author->sort] = $author->name; + } + $epub->Authors($authorArray); + $epub->Language($this->getLanguages()); + $epub->Description($this->getComment(false)); + $epub->Subjects($this->getTagsName()); + // -DC- Use cover file name + // $epub->Cover2($this->getFilePath('jpg'), 'image/jpeg'); + $epub->Cover2($this->coverFileName, 'image/jpeg'); + $epub->Calibre($this->uuid); + $se = $this->getSerie(); + if (!is_null($se)) { + $epub->Serie($se->name); + $epub->SerieIndex($this->seriesIndex); + } + $filename = $data->getUpdatedFilenameEpub(); + if ($config['cops_provide_kepub'] == '1' && preg_match('/Kobo/', $_SERVER['HTTP_USER_AGENT'])) { + $epub->updateForKepub(); + $filename = $data->getUpdatedFilenameKepub(); + } + $epub->download($filename); + } catch (Exception $e) { + echo 'Exception : ' . $e->getMessage(); + } + } + + public function getThumbnail($width, $height, $outputfile = null, $inType = 'jpg') + { + if (is_null($width) && is_null($height)) { + return false; + } + + // -DC- Use cover file name + //$file = $this->getFilePath('jpg'); + $file = $this->coverFileName; + // get image size + if ($size = GetImageSize($file)) { + $w = $size[0]; + $h = $size[1]; + //set new size + if (!is_null($width)) { + $nw = $width; + if ($nw >= $w) { + return false; + } + $nh = intval(($nw*$h)/$w); + } else { + $nh = $height; + if ($nh >= $h) { + return false; + } + $nw = intval(($nh*$w)/$h); + } + } else { + return false; + } + + // Draw the image + if ($inType == 'png') { + $src_img = imagecreatefrompng($file); + } else { + $src_img = imagecreatefromjpeg($file); + } + $dst_img = imagecreatetruecolor($nw, $nh); + if (!imagecopyresampled($dst_img, $src_img, 0, 0, 0, 0, $nw, $nh, $w, $h)) { + return false; + } + if ($inType == 'png') { + if (!imagepng($dst_img, $outputfile, 9)) { + return false; + } + } else { + if (!imagejpeg($dst_img, $outputfile, 80)) { + return false; + } + } + imagedestroy($src_img); + imagedestroy($dst_img); + + return true; + } + + public function getLinkArray() + { + $linkArray = []; + + if ($this->hasCover) { + // -DC- Use cover file name + //array_push($linkArray, Data::getLink($this, 'jpg', 'image/jpeg', Link::OPDS_IMAGE_TYPE, 'cover.jpg', NULL)); + //array_push($linkArray, Data::getLink($this, 'jpg', 'image/jpeg', Link::OPDS_THUMBNAIL_TYPE, 'cover.jpg', NULL)); + $ext = strtolower(pathinfo($this->coverFileName, PATHINFO_EXTENSION)); + if ($ext == 'png') { + array_push($linkArray, Data::getLink($this, "png", "image/png", Link::OPDS_IMAGE_TYPE, "cover.png", null)); + array_push($linkArray, Data::getLink($this, "png", "image/png", Link::OPDS_THUMBNAIL_TYPE, "cover.png", null)); + } else { + array_push($linkArray, Data::getLink($this, 'jpg', 'image/jpeg', Link::OPDS_IMAGE_TYPE, 'cover.jpg', null)); + array_push($linkArray, Data::getLink($this, "jpg", "image/jpeg", Link::OPDS_THUMBNAIL_TYPE, "cover.jpg", null)); + } + } + + foreach ($this->getDatas() as $data) { + if ($data->isKnownType()) { + array_push($linkArray, $data->getDataLink(Link::OPDS_ACQUISITION_TYPE, $data->format)); + } + } + + foreach ($this->getAuthors() as $author) { + /* @var $author Author */ + array_push($linkArray, new LinkNavigation($author->getUri(), 'related', str_format(localize('bookentry.author'), localize('splitByLetter.book.other'), $author->name))); + } + + $serie = $this->getSerie(); + if (!is_null($serie)) { + array_push($linkArray, new LinkNavigation($serie->getUri(), 'related', str_format(localize('content.series.data'), $this->seriesIndex, $serie->name))); + } + + return $linkArray; + } + + + public function getEntry() + { + return new EntryBook( + $this->getTitle(), + $this->getEntryId(), + $this->getComment(), + 'text/html', + $this->getLinkArray(), + $this + ); + } + + public static function getBookCount($database = null) + { + return parent::executeQuerySingle('select count(*) from books', $database); + } + + public static function getCount() + { + global $config; + $nBooks = parent::executeQuerySingle('select count(*) from books'); + $result = []; + $entry = new Entry( + localize('allbooks.title'), + self::ALL_BOOKS_ID, + str_format(localize('allbooks.alphabetical', $nBooks), $nBooks), + 'text', + [new LinkNavigation('?page='.parent::PAGE_ALL_BOOKS)], + '', + $nBooks + ); + array_push($result, $entry); + if ($config['cops_recentbooks_limit'] > 0) { + $entry = new Entry( + localize('recent.title'), + self::ALL_RECENT_BOOKS_ID, + str_format(localize('recent.list'), $config['cops_recentbooks_limit']), + 'text', + [ new LinkNavigation('?page='.parent::PAGE_ALL_RECENT_BOOKS)], + '', + $config['cops_recentbooks_limit'] + ); + array_push($result, $entry); + } + return $result; + } + + public static function getBooksByAuthor($authorId, $n) + { + return self::getEntryArray(self::SQL_BOOKS_BY_AUTHOR, [$authorId], $n); + } + + public static function getBooksByRating($ratingId, $n) + { + return self::getEntryArray(self::SQL_BOOKS_BY_RATING, [$ratingId], $n); + } + + public static function getBooksByPublisher($publisherId, $n) + { + return self::getEntryArray(self::SQL_BOOKS_BY_PUBLISHER, [$publisherId], $n); + } + + public static function getBooksBySeries($serieId, $n) + { + return self::getEntryArray(self::SQL_BOOKS_BY_SERIE, [$serieId], $n); + } + + public static function getBooksByTag($tagId, $n) + { + return self::getEntryArray(self::SQL_BOOKS_BY_TAG, [$tagId], $n); + } + + public static function getBooksByLanguage($languageId, $n) + { + return self::getEntryArray(self::SQL_BOOKS_BY_LANGUAGE, [$languageId], $n); + } + + /** + * @param $customColumn CustomColumn + * @param $id integer + * @param $n integer + * @return array + */ + public static function getBooksByCustom($customColumn, $id, $n) + { + [$query, $params] = $customColumn->getQuery($id); + + return self::getEntryArray($query, $params, $n); + } + + public static function getBookById($bookId) + { + $result = parent::getDb()->prepare('select ' . self::getBookColumns() . ' +from books ' . self::SQL_BOOKS_LEFT_JOIN . ' +where books.id = ?'); + $result->execute([$bookId]); + while ($post = $result->fetchObject()) { + $book = new Book($post); + return $book; + } + return null; + } + + public static function getBookByDataId($dataId) + { + $result = parent::getDb()->prepare('select ' . self::getBookColumns() . ', data.name, data.format +from data, books ' . self::SQL_BOOKS_LEFT_JOIN . ' +where data.book = books.id and data.id = ?'); + $result->execute([$dataId]); + while ($post = $result->fetchObject()) { + $book = new Book($post); + $data = new Data($post, $book); + $data->id = $dataId; + $book->datas = [$data]; + return $book; + } + return null; + } + + public static function getBooksByQuery($query, $n, $database = null, $numberPerPage = null) + { + $i = 0; + $critArray = []; + foreach ([PageQueryResult::SCOPE_AUTHOR, + PageQueryResult::SCOPE_TAG, + PageQueryResult::SCOPE_SERIES, + PageQueryResult::SCOPE_PUBLISHER, + PageQueryResult::SCOPE_BOOK] as $key) { + if (in_array($key, getCurrentOption('ignored_categories')) || + (!array_key_exists($key, $query) && !array_key_exists('all', $query))) { + $critArray[$i] = self::BAD_SEARCH; + } else { + if (array_key_exists($key, $query)) { + $critArray[$i] = $query[$key]; + } else { + $critArray[$i] = $query["all"]; + } + } + $i++; + } + return self::getEntryArray(self::SQL_BOOKS_QUERY, $critArray, $n, $database, $numberPerPage); + } + + public static function getBooks($n) + { + [$entryArray, $totalNumber] = self::getEntryArray(self::SQL_BOOKS_ALL, [], $n); + return [$entryArray, $totalNumber]; + } + + public static function getAllBooks() + { + /* @var $result PDOStatement */ + + [, $result] = parent::executeQuery('select {0} +from books +group by substr (upper (sort), 1, 1) +order by substr (upper (sort), 1, 1)', 'substr (upper (sort), 1, 1) as title, count(*) as count', self::getFilterString(), [], -1); + + $entryArray = []; + while ($post = $result->fetchObject()) { + array_push($entryArray, new Entry( + $post->title, + Book::getEntryIdByLetter($post->title), + str_format(localize('bookword', $post->count), $post->count), + 'text', + [new LinkNavigation('?page='.parent::PAGE_ALL_BOOKS_LETTER.'&id='. rawurlencode($post->title))], + '', + $post->count + )); + } + return $entryArray; + } + + public static function getBooksByStartingLetter($letter, $n, $database = null, $numberPerPage = null) + { + return self::getEntryArray(self::SQL_BOOKS_BY_FIRST_LETTER, [$letter . '%'], $n, $database, $numberPerPage); + } + + public static function getEntryArray($query, $params, $n, $database = null, $numberPerPage = null) + { + /* @var $totalNumber integer */ + /* @var $result PDOStatement */ + [$totalNumber, $result] = parent::executeQuery($query, self::getBookColumns(), self::getFilterString(), $params, $n, $database, $numberPerPage); + + $entryArray = []; + while ($post = $result->fetchObject()) { + $book = new Book($post); + array_push($entryArray, $book->getEntry()); + } + return [$entryArray, $totalNumber]; + } + + public static function getAllRecentBooks() + { + global $config; + [$entryArray, ] = self::getEntryArray(self::SQL_BOOKS_RECENT . $config['cops_recentbooks_limit'], [], -1); + return $entryArray; + } + + /** + * The values of all the specified columns + * + * @param string[] $columns + * @return CustomColumn[] + */ + public function getCustomColumnValues($columns, $asArray = false) + { + $result = []; + + foreach ($columns as $lookup) { + $col = CustomColumnType::createByLookup($lookup); + if (!is_null($col)) { + $cust = $col->getCustomByBook($this); + if (!is_null($cust)) { + if ($asArray) { + array_push($result, $cust->toArray()); + } else { + array_push($result, $cust); + } + } + } + } + + return $result; + } +} diff --git a/lib/CustomColumn.php b/lib/CustomColumn.php new file mode 100644 index 000000000..9a52ff0fc --- /dev/null +++ b/lib/CustomColumn.php @@ -0,0 +1,109 @@ + + */ + +/** + * A CustomColumn with an value + */ +class CustomColumn extends Base +{ + /* @var string|integer the ID of the value */ + public $valueID; + /* @var string the (string) representation of the value */ + public $value; + /* @var CustomColumnType the custom column that contains the value */ + public $customColumnType; + /* @var string the value encoded for HTML displaying */ + public $htmlvalue; + + /** + * CustomColumn constructor. + * + * @param integer|string|null $pid id of the chosen value + * @param string $pvalue string representation of the value + * @param CustomColumnType $pcustomColumnType the CustomColumn this value lives in + */ + public function __construct($pid, $pvalue, $pcustomColumnType) + { + $this->valueID = $pid; + $this->value = $pvalue; + $this->customColumnType = $pcustomColumnType; + $this->htmlvalue = $this->customColumnType->encodeHTMLValue($this->value); + } + + /** + * Get the URI to show all books with this value + * + * @return string + */ + public function getUri() + { + return $this->customColumnType->getUri($this->valueID); + } + + /** + * Get the EntryID to show all books with this value + * + * @return string + */ + public function getEntryId() + { + return $this->customColumnType->getEntryId($this->valueID); + } + + /** + * Get the query to find all books with this value + * the returning array has two values: + * - first the query (string) + * - second an array of all PreparedStatement parameters + * + * @return array + */ + public function getQuery() + { + return $this->customColumnType->getQuery($this->valueID); + } + + /** + * Return the value of this column as an HTML snippet + * + * @return string + */ + public function getHTMLEncodedValue() + { + return $this->htmlvalue; + } + + /** + * Create an CustomColumn by CustomColumnID and ValueID + * + * @param integer $customId the id of the customColumn + * @param integer $id the id of the chosen value + * @return CustomColumn|null + */ + public static function createCustom($customId, $id) + { + $columnType = CustomColumnType::createByCustomID($customId); + + return $columnType->getCustom($id); + } + + /** + * Return this object as an array + * + * @return array + */ + public function toArray() + { + return [ + 'valueID' => $this->valueID, + 'value' => $this->value, + 'customColumnType' => (array)$this->customColumnType, + 'htmlvalue' => $this->htmlvalue, + ]; + } +} diff --git a/lib/CustomColumnType.php b/lib/CustomColumnType.php new file mode 100644 index 000000000..38fc343b8 --- /dev/null +++ b/lib/CustomColumnType.php @@ -0,0 +1,317 @@ + + */ + +/** + * A single calibre custom column + */ +abstract class CustomColumnType extends Base +{ + public const ALL_CUSTOMS_ID = "cops:custom"; + + public const CUSTOM_TYPE_TEXT = "text"; // type 1 + 2 + public const CUSTOM_TYPE_COMMENT = "comments"; // type 3 + public const CUSTOM_TYPE_SERIES = "series"; // type 4 + public const CUSTOM_TYPE_ENUM = "enumeration"; // type 5 + public const CUSTOM_TYPE_DATE = "datetime"; // type 6 + public const CUSTOM_TYPE_FLOAT = "float"; // type 7 + public const CUSTOM_TYPE_INT = "int"; // type 8 + public const CUSTOM_TYPE_RATING = "rating"; // type 9 + public const CUSTOM_TYPE_BOOL = "bool"; // type 10 + public const CUSTOM_TYPE_COMPOSITE = "composite"; // type 11 + 12 + + /** @var array[integer]CustomColumnType */ + private static $customColumnCacheID = []; + + /** @var array[string]CustomColumnType */ + private static $customColumnCacheLookup = []; + + /** @var integer the id of this column */ + public $customId; + /** @var string name/title of this column */ + public $columnTitle; + /** @var string the datatype of this column (one of the CUSTOM_TYPE_* constant values) */ + public $datatype; + /** @var null|Entry[] */ + private $customValues = null; + + protected function __construct($pcustomId, $pdatatype) + { + $this->columnTitle = self::getTitleByCustomID($pcustomId); + $this->customId = $pcustomId; + $this->datatype = $pdatatype; + $this->customValues = null; + } + + /** + * The URI to show all book swith a specific value in this column + * + * @param string|integer $id the id of the value to show + * @return string + */ + public function getUri($id) + { + return "?page=" . parent::PAGE_CUSTOM_DETAIL . "&custom={$this->customId}&id={$id}"; + } + + /** + * The URI to show all the values of this column + * + * @return string + */ + public function getUriAllCustoms() + { + return "?page=" . parent::PAGE_ALL_CUSTOMS . "&custom={$this->customId}"; + } + + /** + * The EntryID to show all book swith a specific value in this column + * + * @param string|integer $id the id of the value to show + * @return string + */ + public function getEntryId($id) + { + return self::ALL_CUSTOMS_ID . ":" . $this->customId . ":" . $id; + } + + /** + * The EntryID to show all the values of this column + * + * @return string + */ + public function getAllCustomsId() + { + return self::ALL_CUSTOMS_ID . ":" . $this->customId; + } + + /** + * The title of this column + * + * @return string + */ + public function getTitle() + { + return $this->columnTitle; + } + + /** + * The description of this column as it is definied in the database + * + * @return string|null + */ + public function getDatabaseDescription() + { + $result = $this->getDb()->prepare('SELECT display FROM custom_columns WHERE id = ?'); + $result->execute([$this->customId]); + if ($post = $result->fetchObject()) { + $json = json_decode($post->display); + return (isset($json->description) && !empty($json->description)) ? $json->description : null; + } + return null; + } + + /** + * Get the Entry for this column + * This is used in the initializeContent method to display e.g. the index page + * + * @return Entry + */ + public function getCount() + { + $ptitle = $this->getTitle(); + $pid = $this->getAllCustomsId(); + $pcontent = $this->getDescription(); + $pcontentType = $this->datatype; + $plinkArray = [new LinkNavigation($this->getUriAllCustoms())]; + $pclass = ""; + $pcount = $this->getDistinctValueCount(); + + return new Entry($ptitle, $pid, $pcontent, $pcontentType, $plinkArray, $pclass, $pcount); + } + + /** + * Get the amount of distinct values for this column + * + * @return int + */ + protected function getDistinctValueCount() + { + return count($this->getAllCustomValues()); + } + + /** + * Encode a value of this column ready to be displayed in an HTML document + * + * @param integer|string $value + * @return string + */ + public function encodeHTMLValue($value) + { + return htmlspecialchars($value); + } + + /** + * Get the datatype of a CustomColumn by its customID + * + * @param integer $customId + * @return string|null + */ + private static function getDatatypeByCustomID($customId) + { + $result = parent::getDb()->prepare('SELECT datatype FROM custom_columns WHERE id = ?'); + $result->execute([$customId]); + if ($post = $result->fetchObject()) { + return $post->datatype; + } + return null; + } + + /** + * Create a CustomColumnType by CustomID + * + * @param integer $customId the id of the custom column + * @return CustomColumnType|null + * @throws Exception If the $customId is not found or the datatype is unknown + */ + public static function createByCustomID($customId) + { + // Reuse already created CustomColumns for performance + if (array_key_exists($customId, self::$customColumnCacheID)) { + return self::$customColumnCacheID[$customId]; + } + + $datatype = self::getDatatypeByCustomID($customId); + + switch ($datatype) { + case self::CUSTOM_TYPE_TEXT: + return self::$customColumnCacheID[$customId] = new CustomColumnTypeText($customId); + case self::CUSTOM_TYPE_SERIES: + return self::$customColumnCacheID[$customId] = new CustomColumnTypeSeries($customId); + case self::CUSTOM_TYPE_ENUM: + return self::$customColumnCacheID[$customId] = new CustomColumnTypeEnumeration($customId); + case self::CUSTOM_TYPE_COMMENT: + return self::$customColumnCacheID[$customId] = new CustomColumnTypeComment($customId); + case self::CUSTOM_TYPE_DATE: + return self::$customColumnCacheID[$customId] = new CustomColumnTypeDate($customId); + case self::CUSTOM_TYPE_FLOAT: + return self::$customColumnCacheID[$customId] = new CustomColumnTypeFloat($customId); + case self::CUSTOM_TYPE_INT: + return self::$customColumnCacheID[$customId] = new CustomColumnTypeInteger($customId); + case self::CUSTOM_TYPE_RATING: + return self::$customColumnCacheID[$customId] = new CustomColumnTypeRating($customId); + case self::CUSTOM_TYPE_BOOL: + return self::$customColumnCacheID[$customId] = new CustomColumnTypeBool($customId); + case self::CUSTOM_TYPE_COMPOSITE: + return null; //TODO Currently not supported + default: + throw new Exception("Unkown column type: " . $datatype); + } + } + + /** + * Create a CustomColumnType by its lookup name + * + * @param string $lookup the lookup-name of the custom column + * @return CustomColumnType|null + */ + public static function createByLookup($lookup) + { + // Reuse already created CustomColumns for performance + if (array_key_exists($lookup, self::$customColumnCacheLookup)) { + return self::$customColumnCacheLookup[$lookup]; + } + + $result = parent::getDb()->prepare('SELECT id FROM custom_columns WHERE label = ?'); + $result->execute([$lookup]); + if ($post = $result->fetchObject()) { + return self::$customColumnCacheLookup[$lookup] = self::createByCustomID($post->id); + } + return self::$customColumnCacheLookup[$lookup] = null; + } + + /** + * Return an entry array for all possible (in the DB used) values of this column + * These are the values used in the getUriAllCustoms() page + * + * @return Entry[] + */ + public function getAllCustomValues() + { + // lazy loading + if ($this->customValues == null) { + $this->customValues = $this->getAllCustomValuesFromDatabase(); + } + + return $this->customValues; + } + + /** + * Get the title of a CustomColumn by its customID + * + * @param integer $customId + * @return string + */ + protected static function getTitleByCustomID($customId) + { + $result = parent::getDb()->prepare('SELECT name FROM custom_columns WHERE id = ?'); + $result->execute([$customId]); + if ($post = $result->fetchObject()) { + return $post->name; + } + return ""; + } + + /** + * Get the query to find all books with a specific value of this column + * the returning array has two values: + * - first the query (string) + * - second an array of all PreparedStatement parameters + * + * @param string|integer $id the id of the searched value + * @return array|null + */ + abstract public function getQuery($id); + + /** + * Get a CustomColumn for a specified (by ID) value + * + * @param string|integer $id the id of the searched value + * @return CustomColumn|null + */ + abstract public function getCustom($id); + + /** + * Return an entry array for all possible (in the DB used) values of this column by querying the database + * + * @return Entry[]|null + */ + abstract protected function getAllCustomValuesFromDatabase(); + + /** + * The description used in the index page + * + * @return string + */ + abstract public function getDescription(); + + /** + * Find the value of this column for a specific book + * + * @param Book $book + * @return CustomColumn + */ + abstract public function getCustomByBook($book); + + /** + * Is this column searchable by value + * only searchable columns can be displayed on the index page + * + * @return bool + */ + abstract public function isSearchable(); +} diff --git a/lib/CustomColumnTypeBool.php b/lib/CustomColumnTypeBool.php new file mode 100644 index 000000000..b6ce5275a --- /dev/null +++ b/lib/CustomColumnTypeBool.php @@ -0,0 +1,94 @@ + + */ + +class CustomColumnTypeBool extends CustomColumnType +{ + // PHP pre 5.6 does not support const arrays + private $BOOLEAN_NAMES = [ + -1 => "customcolumn.boolean.unknown", // localize("customcolumn.boolean.unknown") + 0 => "customcolumn.boolean.no", // localize("customcolumn.boolean.no") + +1 => "customcolumn.boolean.yes", // localize("customcolumn.boolean.yes") + ]; + + protected function __construct($pcustomId) + { + parent::__construct($pcustomId, self::CUSTOM_TYPE_BOOL); + } + + /** + * Get the name of the sqlite table for this column + * + * @return string + */ + private function getTableName() + { + return "custom_column_{$this->customId}"; + } + + public function getQuery($id) + { + if ($id == -1) { + $query = str_format(Book::SQL_BOOKS_BY_CUSTOM_BOOL_NULL, "{0}", "{1}", $this->getTableName()); + return [$query, []]; + } elseif ($id == 0) { + $query = str_format(Book::SQL_BOOKS_BY_CUSTOM_BOOL_FALSE, "{0}", "{1}", $this->getTableName()); + return [$query, []]; + } elseif ($id == 1) { + $query = str_format(Book::SQL_BOOKS_BY_CUSTOM_BOOL_TRUE, "{0}", "{1}", $this->getTableName()); + return [$query, []]; + } else { + return null; + } + } + + public function getCustom($id) + { + return new CustomColumn($id, localize($this->BOOLEAN_NAMES[$id]), $this); + } + + protected function getAllCustomValuesFromDatabase() + { + $queryFormat = "SELECT coalesce({0}.value, -1) AS id, count(*) AS count FROM books LEFT JOIN {0} ON books.id = {0}.book GROUP BY {0}.value ORDER BY {0}.value"; + $query = str_format($queryFormat, $this->getTableName()); + $result = $this->getDb()->query($query); + + $entryArray = []; + while ($post = $result->fetchObject()) { + $entryPContent = str_format(localize("bookword", $post->count), $post->count); + $entryPLinkArray = [new LinkNavigation($this->getUri($post->id))]; + + $entry = new Entry(localize($this->BOOLEAN_NAMES[$post->id]), $this->getEntryId($post->id), $entryPContent, $this->datatype, $entryPLinkArray, "", $post->count); + + array_push($entryArray, $entry); + } + return $entryArray; + } + + public function getDescription() + { + return localize("customcolumn.description.bool"); + } + + public function getCustomByBook($book) + { + $queryFormat = "SELECT {0}.value AS boolvalue FROM {0} WHERE {0}.book = {1}"; + $query = str_format($queryFormat, $this->getTableName(), $book->id); + + $result = $this->getDb()->query($query); + if ($post = $result->fetchObject()) { + return new CustomColumn($post->boolvalue, localize($this->BOOLEAN_NAMES[$post->boolvalue]), $this); + } else { + return new CustomColumn(-1, localize($this->BOOLEAN_NAMES[-1]), $this); + } + } + + public function isSearchable() + { + return true; + } +} diff --git a/lib/CustomColumnTypeComment.php b/lib/CustomColumnTypeComment.php new file mode 100644 index 000000000..b8f2400da --- /dev/null +++ b/lib/CustomColumnTypeComment.php @@ -0,0 +1,72 @@ + + */ + +class CustomColumnTypeComment extends CustomColumnType +{ + protected function __construct($pcustomId) + { + parent::__construct($pcustomId, self::CUSTOM_TYPE_COMMENT); + } + + /** + * Get the name of the sqlite table for this column + * + * @return string + */ + private function getTableName() + { + return "custom_column_{$this->customId}"; + } + + public function getQuery($id) + { + $query = str_format(Book::SQL_BOOKS_BY_CUSTOM_DIRECT_ID, "{0}", "{1}", $this->getTableName()); + return [$query, [$id]]; + } + + public function getCustom($id) + { + return new CustomColumn($id, $id, $this); + } + + public function encodeHTMLValue($value) + { + return "
    " . $value . "
    "; // no htmlspecialchars, this is already HTML + } + + protected function getAllCustomValuesFromDatabase() + { + return null; + } + + public function getDescription() + { + $desc = $this->getDatabaseDescription(); + if ($desc === null || empty($desc)) { + $desc = str_format(localize("customcolumn.description"), $this->getTitle()); + } + return $desc; + } + + public function getCustomByBook($book) + { + $queryFormat = "SELECT {0}.id AS id, {0}.value AS value FROM {0} WHERE {0}.book = {1}"; + $query = str_format($queryFormat, $this->getTableName(), $book->id); + + $result = $this->getDb()->query($query); + if ($post = $result->fetchObject()) { + return new CustomColumn($post->id, $post->value, $this); + } + return new CustomColumn(null, localize("customcolumn.float.unknown"), $this); + } + + public function isSearchable() + { + return false; + } +} diff --git a/lib/CustomColumnTypeDate.php b/lib/CustomColumnTypeDate.php new file mode 100644 index 000000000..e0d09952e --- /dev/null +++ b/lib/CustomColumnTypeDate.php @@ -0,0 +1,89 @@ + + */ + +class CustomColumnTypeDate extends CustomColumnType +{ + protected function __construct($pcustomId) + { + parent::__construct($pcustomId, self::CUSTOM_TYPE_DATE); + } + + /** + * Get the name of the sqlite table for this column + * + * @return string + */ + private function getTableName() + { + return "custom_column_{$this->customId}"; + } + + public function getQuery($id) + { + $date = new DateTime($id); + $query = str_format(Book::SQL_BOOKS_BY_CUSTOM_DATE, "{0}", "{1}", $this->getTableName()); + return [$query, [$date->format("Y-m-d")]]; + } + + public function getCustom($id) + { + $date = new DateTime($id); + + return new CustomColumn($id, $date->format(localize("customcolumn.date.format")), $this); + } + + protected function getAllCustomValuesFromDatabase() + { + $queryFormat = "SELECT date(value) AS datevalue, count(*) AS count FROM {0} GROUP BY datevalue"; + $query = str_format($queryFormat, $this->getTableName()); + $result = $this->getDb()->query($query); + + $entryArray = []; + while ($post = $result->fetchObject()) { + $date = new DateTime($post->datevalue); + $id = $date->format("Y-m-d"); + + $entryPContent = str_format(localize("bookword", $post->count), $post->count); + $entryPLinkArray = [new LinkNavigation($this->getUri($id))]; + + $entry = new Entry($date->format(localize("customcolumn.date.format")), $this->getEntryId($id), $entryPContent, $this->datatype, $entryPLinkArray, "", $post->count); + + array_push($entryArray, $entry); + } + + return $entryArray; + } + + public function getDescription() + { + $desc = $this->getDatabaseDescription(); + if ($desc === null || empty($desc)) { + $desc = str_format(localize("customcolumn.description"), $this->getTitle()); + } + return $desc; + } + + public function getCustomByBook($book) + { + $queryFormat = "SELECT date({0}.value) AS datevalue FROM {0} WHERE {0}.book = {1}"; + $query = str_format($queryFormat, $this->getTableName(), $book->id); + + $result = $this->getDb()->query($query); + if ($post = $result->fetchObject()) { + $date = new DateTime($post->datevalue); + + return new CustomColumn($date->format("Y-m-d"), $date->format(localize("customcolumn.date.format")), $this); + } + return new CustomColumn(null, localize("customcolumn.date.unknown"), $this); + } + + public function isSearchable() + { + return true; + } +} diff --git a/lib/CustomColumnTypeEnumeration.php b/lib/CustomColumnTypeEnumeration.php new file mode 100644 index 000000000..388cf8abc --- /dev/null +++ b/lib/CustomColumnTypeEnumeration.php @@ -0,0 +1,102 @@ + + */ + +class CustomColumnTypeEnumeration extends CustomColumnType +{ + protected function __construct($pcustomId) + { + parent::__construct($pcustomId, self::CUSTOM_TYPE_ENUM); + } + + /** + * Get the name of the sqlite table for this column + * + * @return string + */ + private function getTableName() + { + return "custom_column_{$this->customId}"; + } + + /** + * Get the name of the linking sqlite table for this column + * (or NULL if there is no linktable) + * + * @return string + */ + private function getTableLinkName() + { + return "books_custom_column_{$this->customId}_link"; + } + + /** + * Get the name of the linking column in the linktable + * + * @return string + */ + private function getTableLinkColumn() + { + return "value"; + } + + public function getQuery($id) + { + $query = str_format(Book::SQL_BOOKS_BY_CUSTOM, "{0}", "{1}", $this->getTableLinkName(), $this->getTableLinkColumn()); + return [$query, [$id]]; + } + + public function getCustom($id) + { + $result = $this->getDb()->prepare(str_format("SELECT id, value AS name FROM {0} WHERE id = ?", $this->getTableName())); + $result->execute([$id]); + if ($post = $result->fetchObject()) { + return new CustomColumn($id, $post->name, $this); + } + return null; + } + + protected function getAllCustomValuesFromDatabase() + { + $queryFormat = "SELECT {0}.id AS id, {0}.value AS name, count(*) AS count FROM {0}, {1} WHERE {0}.id = {1}.{2} GROUP BY {0}.id, {0}.value ORDER BY {0}.value"; + $query = str_format($queryFormat, $this->getTableName(), $this->getTableLinkName(), $this->getTableLinkColumn()); + + $result = $this->getDb()->query($query); + $entryArray = []; + while ($post = $result->fetchObject()) { + $entryPContent = str_format(localize("bookword", $post->count), $post->count); + $entryPLinkArray = [new LinkNavigation($this->getUri($post->id))]; + + $entry = new Entry($post->name, $this->getEntryId($post->id), $entryPContent, $this->datatype, $entryPLinkArray, "", $post->count); + + array_push($entryArray, $entry); + } + return $entryArray; + } + + public function getDescription() + { + return str_format(localize("customcolumn.description.enum", $this->getDistinctValueCount()), $this->getDistinctValueCount()); + } + + public function getCustomByBook($book) + { + $queryFormat = "SELECT {0}.id AS id, {0}.{2} AS name FROM {0}, {1} WHERE {0}.id = {1}.{2} AND {1}.book = {3}"; + $query = str_format($queryFormat, $this->getTableName(), $this->getTableLinkName(), $this->getTableLinkColumn(), $book->id); + + $result = $this->getDb()->query($query); + if ($post = $result->fetchObject()) { + return new CustomColumn($post->id, $post->name, $this); + } + return new CustomColumn(null, localize("customcolumn.enum.unknown"), $this); + } + + public function isSearchable() + { + return true; + } +} diff --git a/lib/CustomColumnTypeFloat.php b/lib/CustomColumnTypeFloat.php new file mode 100644 index 000000000..f92cb3990 --- /dev/null +++ b/lib/CustomColumnTypeFloat.php @@ -0,0 +1,80 @@ + + */ + +class CustomColumnTypeFloat extends CustomColumnType +{ + protected function __construct($pcustomId) + { + parent::__construct($pcustomId, self::CUSTOM_TYPE_FLOAT); + } + + /** + * Get the name of the sqlite table for this column + * + * @return string + */ + private function getTableName() + { + return "custom_column_{$this->customId}"; + } + + public function getQuery($id) + { + $query = str_format(Book::SQL_BOOKS_BY_CUSTOM_DIRECT, "{0}", "{1}", $this->getTableName()); + return [$query, [$id]]; + } + + public function getCustom($id) + { + return new CustomColumn($id, $id, $this); + } + + protected function getAllCustomValuesFromDatabase() + { + $queryFormat = "SELECT value AS id, count(*) AS count FROM {0} GROUP BY value"; + $query = str_format($queryFormat, $this->getTableName()); + + $result = $this->getDb()->query($query); + $entryArray = []; + while ($post = $result->fetchObject()) { + $entryPContent = str_format(localize("bookword", $post->count), $post->count); + $entryPLinkArray = [new LinkNavigation($this->getUri($post->id))]; + + $entry = new Entry($post->id, $this->getEntryId($post->id), $entryPContent, $this->datatype, $entryPLinkArray, "", $post->count); + + array_push($entryArray, $entry); + } + return $entryArray; + } + + public function getDescription() + { + $desc = $this->getDatabaseDescription(); + if ($desc === null || empty($desc)) { + $desc = str_format(localize("customcolumn.description"), $this->getTitle()); + } + return $desc; + } + + public function getCustomByBook($book) + { + $queryFormat = "SELECT {0}.value AS value FROM {0} WHERE {0}.book = {1}"; + $query = str_format($queryFormat, $this->getTableName(), $book->id); + + $result = $this->getDb()->query($query); + if ($post = $result->fetchObject()) { + return new CustomColumn($post->value, $post->value, $this); + } + return new CustomColumn(null, localize("customcolumn.float.unknown"), $this); + } + + public function isSearchable() + { + return true; + } +} diff --git a/lib/CustomColumnTypeInteger.php b/lib/CustomColumnTypeInteger.php new file mode 100644 index 000000000..7d4afcef9 --- /dev/null +++ b/lib/CustomColumnTypeInteger.php @@ -0,0 +1,93 @@ + + */ + +class CustomColumnTypeInteger extends CustomColumnType +{ + private static $type; + + protected function __construct($pcustomId, $datatype = self::CUSTOM_TYPE_INT) + { + self::$type = $datatype; + + switch ($datatype) { + case self::CUSTOM_TYPE_INT: + parent::__construct($pcustomId, self::CUSTOM_TYPE_INT); + break; + case self::CUSTOM_TYPE_FLOAT: + parent::__construct($pcustomId, self::CUSTOM_TYPE_FLOAT); + break; + default: + throw new UnexpectedValueException(); + } + } + + /** + * Get the name of the sqlite table for this column + * + * @return string + */ + private function getTableName() + { + return "custom_column_{$this->customId}"; + } + + public function getQuery($id) + { + $query = str_format(Book::SQL_BOOKS_BY_CUSTOM_DIRECT, "{0}", "{1}", $this->getTableName()); + return [$query, [$id]]; + } + + public function getCustom($id) + { + return new CustomColumn($id, $id, $this); + } + + protected function getAllCustomValuesFromDatabase() + { + $queryFormat = "SELECT value AS id, count(*) AS count FROM {0} GROUP BY value"; + $query = str_format($queryFormat, $this->getTableName()); + + $result = $this->getDb()->query($query); + $entryArray = []; + while ($post = $result->fetchObject()) { + $entryPContent = str_format(localize("bookword", $post->count), $post->count); + $entryPLinkArray = [new LinkNavigation($this->getUri($post->id))]; + + $entry = new Entry($post->id, $this->getEntryId($post->id), $entryPContent, $this->datatype, $entryPLinkArray, "", $post->count); + + array_push($entryArray, $entry); + } + return $entryArray; + } + + public function getDescription() + { + $desc = $this->getDatabaseDescription(); + if ($desc === null || empty($desc)) { + $desc = str_format(localize("customcolumn.description"), $this->getTitle()); + } + return $desc; + } + + public function getCustomByBook($book) + { + $queryFormat = "SELECT {0}.value AS value FROM {0} WHERE {0}.book = {1}"; + $query = str_format($queryFormat, $this->getTableName(), $book->id); + + $result = $this->getDb()->query($query); + if ($post = $result->fetchObject()) { + return new CustomColumn($post->value, $post->value, $this); + } + return new CustomColumn(null, localize("customcolumn.int.unknown"), $this); + } + + public function isSearchable() + { + return true; + } +} diff --git a/lib/CustomColumnTypeRating.php b/lib/CustomColumnTypeRating.php new file mode 100644 index 000000000..4a74c7ffa --- /dev/null +++ b/lib/CustomColumnTypeRating.php @@ -0,0 +1,110 @@ + + */ + +class CustomColumnTypeRating extends CustomColumnType +{ + protected function __construct($pcustomId) + { + parent::__construct($pcustomId, self::CUSTOM_TYPE_RATING); + } + + /** + * Get the name of the sqlite table for this column + * + * @return string + */ + private function getTableName() + { + return "custom_column_{$this->customId}"; + } + + /** + * Get the name of the linking sqlite table for this column + * (or NULL if there is no linktable) + * + * @return string + */ + private function getTableLinkName() + { + return "books_custom_column_{$this->customId}_link"; + } + + /** + * Get the name of the linking column in the linktable + * + * @return string + */ + private function getTableLinkColumn() + { + return "value"; + } + + public function getQuery($id) + { + if ($id == 0) { + $query = str_format(Book::SQL_BOOKS_BY_CUSTOM_RATING_NULL, "{0}", "{1}", $this->getTableLinkName(), $this->getTableName(), $this->getTableLinkColumn()); + return [$query, []]; + } else { + $query = str_format(Book::SQL_BOOKS_BY_CUSTOM_RATING, "{0}", "{1}", $this->getTableLinkName(), $this->getTableName(), $this->getTableLinkColumn()); + return [$query, [$id]]; + } + } + + public function getCustom($id) + { + return new CustomColumn($id, str_format(localize("customcolumn.stars", $id / 2), $id / 2), $this); + } + + protected function getAllCustomValuesFromDatabase() + { + $queryFormat = "SELECT coalesce({0}.value, 0) AS value, count(*) AS count FROM books LEFT JOIN {1} ON books.id = {1}.book LEFT JOIN {0} ON {0}.id = {1}.value GROUP BY coalesce({0}.value, -1)"; + $query = str_format($queryFormat, $this->getTableName(), $this->getTableLinkName()); + $result = $this->getDb()->query($query); + + $countArray = [0 => 0, 2 => 0, 4 => 0, 6 => 0, 8 => 0, 10 => 0]; + while ($row = $result->fetchObject()) { + $countArray[$row->value] = $row->count; + } + + $entryArray = []; + + for ($i = 0; $i <= 5; $i++) { + $count = $countArray[$i * 2]; + $name = str_format(localize("customcolumn.stars", $i), $i); + $entryid = $this->getEntryId($i * 2); + $content = str_format(localize("bookword", $count), $count); + $linkarray = [new LinkNavigation($this->getUri($i * 2))]; + $entry = new Entry($name, $entryid, $content, $this->datatype, $linkarray, "", $count); + array_push($entryArray, $entry); + } + + return $entryArray; + } + + public function getDescription() + { + return localize("customcolumn.description.rating"); + } + + public function getCustomByBook($book) + { + $queryFormat = "SELECT {0}.value AS value FROM {0}, {1} WHERE {0}.id = {1}.{2} AND {1}.book = {3}"; + $query = str_format($queryFormat, $this->getTableName(), $this->getTableLinkName(), $this->getTableLinkColumn(), $book->id); + + $result = $this->getDb()->query($query); + if ($post = $result->fetchObject()) { + return new CustomColumn($post->value, str_format(localize("customcolumn.stars", $post->value / 2), $post->value / 2), $this); + } + return new CustomColumn(null, localize("customcolumn.rating.unknown"), $this); + } + + public function isSearchable() + { + return true; + } +} diff --git a/lib/CustomColumnTypeSeries.php b/lib/CustomColumnTypeSeries.php new file mode 100644 index 000000000..8d49f0895 --- /dev/null +++ b/lib/CustomColumnTypeSeries.php @@ -0,0 +1,102 @@ + + */ + +class CustomColumnTypeSeries extends CustomColumnType +{ + protected function __construct($pcustomId) + { + parent::__construct($pcustomId, self::CUSTOM_TYPE_SERIES); + } + + /** + * Get the name of the sqlite table for this column + * + * @return string + */ + private function getTableName() + { + return "custom_column_{$this->customId}"; + } + + /** + * Get the name of the linking sqlite table for this column + * (or NULL if there is no linktable) + * + * @return string + */ + private function getTableLinkName() + { + return "books_custom_column_{$this->customId}_link"; + } + + /** + * Get the name of the linking column in the linktable + * + * @return string + */ + private function getTableLinkColumn() + { + return "value"; + } + + public function getQuery($id) + { + $query = str_format(Book::SQL_BOOKS_BY_CUSTOM, "{0}", "{1}", $this->getTableLinkName(), $this->getTableLinkColumn()); + return [$query, [$id]]; + } + + public function getCustom($id) + { + $result = $this->getDb()->prepare(str_format("SELECT id, value AS name FROM {0} WHERE id = ?", $this->getTableName())); + $result->execute([$id]); + if ($post = $result->fetchObject()) { + return new CustomColumn($id, $post->name, $this); + } + return null; + } + + protected function getAllCustomValuesFromDatabase() + { + $queryFormat = "SELECT {0}.id AS id, {0}.value AS name, count(*) AS count FROM {0}, {1} WHERE {0}.id = {1}.{2} GROUP BY {0}.id, {0}.value ORDER BY {0}.value"; + $query = str_format($queryFormat, $this->getTableName(), $this->getTableLinkName(), $this->getTableLinkColumn()); + + $result = $this->getDb()->query($query); + $entryArray = []; + while ($post = $result->fetchObject()) { + $entryPContent = str_format(localize("bookword", $post->count), $post->count); + $entryPLinkArray = [new LinkNavigation($this->getUri($post->id))]; + + $entry = new Entry($post->name, $this->getEntryId($post->id), $entryPContent, $this->datatype, $entryPLinkArray, "", $post->count); + + array_push($entryArray, $entry); + } + return $entryArray; + } + + public function getDescription() + { + return str_format(localize("customcolumn.description.series", $this->getDistinctValueCount()), $this->getDistinctValueCount()); + } + + public function getCustomByBook($book) + { + $queryFormat = "SELECT {0}.id AS id, {1}.{2} AS name, {1}.extra AS extra FROM {0}, {1} WHERE {0}.id = {1}.{2} AND {1}.book = {3}"; + $query = str_format($queryFormat, $this->getTableName(), $this->getTableLinkName(), $this->getTableLinkColumn(), $book->id); + + $result = $this->getDb()->query($query); + if ($post = $result->fetchObject()) { + return new CustomColumn($post->id, $post->name . " [" . $post->extra . "]", $this); + } + return new CustomColumn(null, "", $this); + } + + public function isSearchable() + { + return true; + } +} diff --git a/lib/CustomColumnTypeText.php b/lib/CustomColumnTypeText.php new file mode 100644 index 000000000..4f609f01a --- /dev/null +++ b/lib/CustomColumnTypeText.php @@ -0,0 +1,135 @@ + + */ + +class CustomColumnTypeText extends CustomColumnType +{ + private static $type; + + protected function __construct($pcustomId, $datatype = self::CUSTOM_TYPE_TEXT) + { + self::$type = $datatype; + + switch ($datatype) { + case self::CUSTOM_TYPE_TEXT: + parent::__construct($pcustomId, self::CUSTOM_TYPE_TEXT); + break; + case self::CUSTOM_TYPE_ENUM: + parent::__construct($pcustomId, self::CUSTOM_TYPE_ENUM); + break; + case self::CUSTOM_TYPE_SERIES: + parent::__construct($pcustomId, self::CUSTOM_TYPE_SERIES); + break; + default: + throw new UnexpectedValueException(); + } + parent::__construct($pcustomId, self::CUSTOM_TYPE_TEXT); + } + + /** + * Get the name of the sqlite table for this column + * + * @return string + */ + private function getTableName() + { + return "custom_column_{$this->customId}"; + } + + /** + * Get the name of the linking sqlite table for this column + * (or NULL if there is no linktable) + * + * @return string + */ + private function getTableLinkName() + { + return "books_custom_column_{$this->customId}_link"; + } + + /** + * Get the name of the linking column in the linktable + * + * @return string + */ + private function getTableLinkColumn() + { + return "value"; + } + + public function getQuery($id) + { + $query = str_format(Book::SQL_BOOKS_BY_CUSTOM, "{0}", "{1}", $this->getTableLinkName(), $this->getTableLinkColumn()); + return [$query, [$id]]; + } + + public function getCustom($id) + { + $result = $this->getDb()->prepare(str_format("SELECT id, value AS name FROM {0} WHERE id = ?", $this->getTableName())); + $result->execute([$id]); + if ($post = $result->fetchObject()) { + return new CustomColumn($id, $post->name, $this); + } + return null; + } + + protected function getAllCustomValuesFromDatabase() + { + $queryFormat = "SELECT {0}.id AS id, {0}.value AS name, count(*) AS count FROM {0}, {1} WHERE {0}.id = {1}.{2} GROUP BY {0}.id, {0}.value ORDER BY {0}.value"; + $query = str_format($queryFormat, $this->getTableName(), $this->getTableLinkName(), $this->getTableLinkColumn()); + + $result = $this->getDb()->query($query); + $entryArray = []; + while ($post = $result->fetchObject()) { + $entryPContent = str_format(localize("bookword", $post->count), $post->count); + $entryPLinkArray = [new LinkNavigation($this->getUri($post->id))]; + + $entry = new Entry($post->name, $this->getEntryId($post->id), $entryPContent, $this->datatype, $entryPLinkArray, "", $post->count); + + array_push($entryArray, $entry); + } + return $entryArray; + } + + public function getDescription() + { + $desc = $this->getDatabaseDescription(); + if ($desc === null || empty($desc)) { + $desc = str_format(localize("customcolumn.description"), $this->getTitle()); + } + return $desc; + } + + public function getCustomByBook($book) + { + switch (self::$type) { + case self::CUSTOM_TYPE_TEXT: + $queryFormat = "SELECT {0}.id AS id, {0}.{2} AS name FROM {0}, {1} WHERE {0}.id = {1}.{2} AND {1}.book = {3} ORDER BY {0}.value"; + break; + case self::CUSTOM_TYPE_ENUM: + $queryFormat = "SELECT {0}.id AS id, {0}.{2} AS name FROM {0}, {1} WHERE {0}.id = {1}.{2} AND {1}.book = {3}"; + break; + case self::CUSTOM_TYPE_SERIES: + $queryFormat = "SELECT {0}.id AS id, {1}.{2} AS name, {1}.extra AS extra FROM {0}, {1} WHERE {0}.id = {1}.{2} AND {1}.book = {3}"; + break; + default: + throw new UnexpectedValueException(); + } + $query = str_format($queryFormat, $this->getTableName(), $this->getTableLinkName(), $this->getTableLinkColumn(), $book->id); + + $result = $this->getDb()->query($query); + if ($post = $result->fetchObject()) { + return new CustomColumn($post->id, $post->name, $this); + } + return new CustomColumn(null, "", $this); + } + + public function isSearchable() + { + return true; + } +} diff --git a/lib/Data.php b/lib/Data.php new file mode 100644 index 000000000..c2fa6b50f --- /dev/null +++ b/lib/Data.php @@ -0,0 +1,245 @@ + + */ + +class Data extends Base +{ + public $id; + public $name; + public $format; + public $realFormat; + public $extension; + public $book; + + public static $mimetypes = [ + 'aac' => 'audio/aac', + 'azw' => 'application/x-mobipocket-ebook', + 'azw1' => 'application/x-topaz-ebook', + 'azw2' => 'application/x-kindle-application', + 'azw3' => 'application/x-mobi8-ebook', + 'cbz' => 'application/x-cbz', + 'cbr' => 'application/x-cbr', + 'djv' => 'image/vnd.djvu', + 'djvu' => 'image/vnd.djvu', + 'doc' => 'application/msword', + 'epub' => 'application/epub+zip', + 'fb2' => 'text/fb2+xml', + 'ibooks'=> 'application/x-ibooks+zip', + 'kepub' => 'application/epub+zip', + 'kobo' => 'application/x-koboreader-ebook', + 'm4a' => 'audio/mp4', + 'mobi' => 'application/x-mobipocket-ebook', + 'mp3' => 'audio/mpeg', + 'lit' => 'application/x-ms-reader', + 'lrs' => 'text/x-sony-bbeb+xml', + 'lrf' => 'application/x-sony-bbeb', + 'lrx' => 'application/x-sony-bbeb', + 'ncx' => 'application/x-dtbncx+xml', + 'opf' => 'application/oebps-package+xml', + 'otf' => 'application/x-font-opentype', + 'pdb' => 'application/vnd.palm', + 'pdf' => 'application/pdf', + 'prc' => 'application/x-mobipocket-ebook', + 'rtf' => 'application/rtf', + 'svg' => 'image/svg+xml', + 'ttf' => 'application/x-font-truetype', + 'tpz' => 'application/x-topaz-ebook', + 'wav' => 'audio/wav', + 'wmf' => 'image/wmf', + 'xhtml' => 'application/xhtml+xml', + 'xpgt' => 'application/adobe-page-template+xml', + 'zip' => 'application/zip', + ]; + + public function __construct($post, $book = null) + { + $this->id = $post->id; + $this->name = $post->name; + $this->format = $post->format; + $this->realFormat = str_replace("ORIGINAL_", "", $post->format); + $this->extension = strtolower($this->realFormat); + $this->book = $book; + } + + public function isKnownType() + { + return array_key_exists($this->extension, self::$mimetypes); + } + + public function getMimeType() + { + $result = "application/octet-stream"; + if ($this->isKnownType()) { + return self::$mimetypes [$this->extension]; + } elseif (function_exists('finfo_open') === true) { + $finfo = finfo_open(FILEINFO_MIME_TYPE); + + if ($finfo !== false) { + $result = finfo_file($finfo, $this->getLocalPath()); + finfo_close($finfo); + } + } + return $result; + } + + public function isEpubValidOnKobo() + { + return $this->format == "EPUB" || $this->format == "KEPUB"; + } + + public function getFilename() + { + return $this->name . "." . strtolower($this->format); + } + + public function getUpdatedFilename() + { + return $this->book->getAuthorsSort() . " - " . $this->book->title; + } + + public function getUpdatedFilenameEpub() + { + return $this->getUpdatedFilename() . ".epub"; + } + + public function getUpdatedFilenameKepub() + { + $str = $this->getUpdatedFilename() . ".kepub.epub"; + return str_replace( + [':', '#', '&'], + ['-', '-', ' '], + $str + ); + } + + public function getDataLink($rel, $title = null, $view = false) + { + global $config; + + if ($rel == Link::OPDS_ACQUISITION_TYPE && $config['cops_use_url_rewriting'] == "1") { + return $this->getHtmlLinkWithRewriting($title, $view); + } + + return self::getLink($this->book, $this->extension, $this->getMimeType(), $rel, $this->getFilename(), $this->id, $title, null, $view); + } + + public function getHtmlLink() + { + return $this->getDataLink(Link::OPDS_ACQUISITION_TYPE)->href; + } + + public function getViewHtmlLink() + { + return $this->getDataLink(Link::OPDS_ACQUISITION_TYPE, null, true)->href; + } + + public function getLocalPath() + { + return $this->book->path . "/" . $this->getFilename(); + } + + public function getHtmlLinkWithRewriting($title = null, $view = false) + { + global $config; + + $database = ""; + if (!is_null(GetUrlParam(DB))) { + $database = GetUrlParam(DB) . "/"; + } + + $prefix = "download"; + if ($view) { + $prefix = "view"; + } + $href = $prefix . "/" . $this->id . "/" . $database; + + if ($config['cops_provide_kepub'] == "1" && + $this->isEpubValidOnKobo() && + preg_match("/Kobo/", $_SERVER['HTTP_USER_AGENT'])) { + $href .= rawurlencode($this->getUpdatedFilenameKepub()); + } else { + $href .= rawurlencode($this->getFilename()); + } + return new Link($href, $this->getMimeType(), Link::OPDS_ACQUISITION_TYPE, $title); + } + + public static function getDataByBook($book) + { + global $config; + + $out = []; + + $sql = 'select id, format, name from data where book = ?'; + + $ignored_formats = $config['cops_ignored_formats']; + if (count($ignored_formats) > 0) { + $sql .= " and format not in ('" + . implode("','", $ignored_formats) + . "')"; + } + + $result = parent::getDb()->prepare($sql); + $result->execute([$book->id]); + + while ($post = $result->fetchObject()) { + array_push($out, new Data($post, $book)); + } + return $out; + } + + public static function handleThumbnailLink($urlParam, $height) + { + global $config; + + if (is_null($height)) { + if (preg_match('/feed.php/', $_SERVER["SCRIPT_NAME"])) { + $height = $config['cops_opds_thumbnail_height']; + } else { + $height = $config['cops_html_thumbnail_height']; + } + } + if ($config['cops_thumbnail_handling'] != "1") { + $urlParam = addURLParameter($urlParam, "height", $height); + } + + return $urlParam; + } + + public static function getLink($book, $type, $mime, $rel, $filename, $idData, $title = null, $height = null, $view = false) + { + global $config; + + $urlParam = addURLParameter("", "data", $idData); + if ($view) { + $urlParam = addURLParameter($urlParam, "view", 1); + } + + if (Base::useAbsolutePath() || + $rel == Link::OPDS_THUMBNAIL_TYPE || + ($type == "epub" && $config['cops_update_epub-metadata'])) { + if ($type != "jpg") { + $urlParam = addURLParameter($urlParam, "type", $type); + } + if ($rel == Link::OPDS_THUMBNAIL_TYPE) { + $urlParam = self::handleThumbnailLink($urlParam, $height); + } + $urlParam = addURLParameter($urlParam, "id", $book->id); + if (!is_null(GetUrlParam(DB))) { + $urlParam = addURLParameter($urlParam, DB, GetUrlParam(DB)); + } + if ($config['cops_thumbnail_handling'] != "1" && + !empty($config['cops_thumbnail_handling']) && + $rel == Link::OPDS_THUMBNAIL_TYPE) { + return new Link($config['cops_thumbnail_handling'], $mime, $rel, $title); + } else { + return new Link("fetch.php?" . $urlParam, $mime, $rel, $title); + } + } else { + return new Link(str_replace('%2F', '/', rawurlencode($book->path."/".$filename)), $mime, $rel, $title); + } + } +} diff --git a/lib/Entry.php b/lib/Entry.php new file mode 100644 index 000000000..8b2b59742 --- /dev/null +++ b/lib/Entry.php @@ -0,0 +1,83 @@ + + */ + +class Entry +{ + public $title; + public $id; + public $content; + public $numberOfElement; + public $contentType; + public $linkArray; + public $localUpdated; + public $className; + private static $updated = null; + + public static $icons = [ + Author::ALL_AUTHORS_ID => 'images/author.png', + Serie::ALL_SERIES_ID => 'images/serie.png', + Book::ALL_RECENT_BOOKS_ID => 'images/recent.png', + Tag::ALL_TAGS_ID => 'images/tag.png', + Language::ALL_LANGUAGES_ID => 'images/language.png', + CustomColumnType::ALL_CUSTOMS_ID => 'images/custom.png', + Rating::ALL_RATING_ID => 'images/rating.png', + "cops:books$" => 'images/allbook.png', + "cops:books:letter" => 'images/allbook.png', + Publisher::ALL_PUBLISHERS_ID => 'images/publisher.png', + ]; + + public function getUpdatedTime() + { + if (!is_null($this->localUpdated)) { + return date(DATE_ATOM, $this->localUpdated); + } + if (is_null(self::$updated)) { + self::$updated = time(); + } + return date(DATE_ATOM, self::$updated); + } + + public function getNavLink() + { + foreach ($this->linkArray as $link) { + /* @var $link LinkNavigation */ + + if ($link->type != Link::OPDS_NAVIGATION_TYPE) { + continue; + } + + return $link->hrefXhtml(); + } + return "#"; + } + + public function __construct($ptitle, $pid, $pcontent, $pcontentType, $plinkArray, $pclass = "", $pcount = 0) + { + global $config; + $this->title = $ptitle; + $this->id = $pid; + $this->content = $pcontent; + $this->contentType = $pcontentType; + $this->linkArray = $plinkArray; + $this->className = $pclass; + $this->numberOfElement = $pcount; + + if ($config['cops_show_icons'] == 1) { + foreach (self::$icons as $reg => $image) { + if (preg_match("/" . $reg . "/", $pid)) { + array_push($this->linkArray, new Link(getUrlWithVersion($image), "image/png", Link::OPDS_THUMBNAIL_TYPE)); + break; + } + } + } + + if (!is_null(GetUrlParam(DB))) { + $this->id = str_replace("cops:", "cops:" . GetUrlParam(DB) . ":", $this->id); + } + } +} diff --git a/lib/EntryBook.php b/lib/EntryBook.php new file mode 100644 index 000000000..77ea80e70 --- /dev/null +++ b/lib/EntryBook.php @@ -0,0 +1,52 @@ + + */ + +class EntryBook extends Entry +{ + public $book; + + /** + * EntryBook constructor. + * @param string $ptitle + * @param integer $pid + * @param string $pcontent + * @param string $pcontentType + * @param array $plinkArray + * @param Book $pbook + */ + public function __construct($ptitle, $pid, $pcontent, $pcontentType, $plinkArray, $pbook) + { + parent::__construct($ptitle, $pid, $pcontent, $pcontentType, $plinkArray); + $this->book = $pbook; + $this->localUpdated = $pbook->timestamp; + } + + public function getCoverThumbnail() + { + foreach ($this->linkArray as $link) { + /* @var $link LinkNavigation */ + + if ($link->rel == Link::OPDS_THUMBNAIL_TYPE) { + return $link->hrefXhtml(); + } + } + return null; + } + + public function getCover() + { + foreach ($this->linkArray as $link) { + /* @var $link LinkNavigation */ + + if ($link->rel == Link::OPDS_IMAGE_TYPE) { + return $link->hrefXhtml(); + } + } + return null; + } +} diff --git a/lib/Identifier.php b/lib/Identifier.php new file mode 100644 index 000000000..a795bd1a0 --- /dev/null +++ b/lib/Identifier.php @@ -0,0 +1,80 @@ + + */ + +class Identifier +{ + public $id; + public $type; + public $formattedType; + public $val; + public $uri; + + public function __construct($post) + { + $this->id = $post->id; + $this->type = strtolower($post->type); + $this->val = $post->val; + $this->formatType(); + } + + public function formatType() + { + if ($this->type == 'amazon') { + $this->formattedType = "Amazon"; + $this->uri = sprintf("https://amazon.com/dp/%s", $this->val); + } elseif ($this->type == "asin") { + $this->formattedType = $this->type; + $this->uri = sprintf("https://amazon.com/dp/%s", $this->val); + } elseif (substr($this->type, 0, 7) == "amazon_") { + $this->formattedType = sprintf("Amazon.co.%s", substr($this->type, 7)); + $this->uri = sprintf("https://amazon.co.%s/dp/%s", substr($this->type, 7), $this->val); + } elseif ($this->type == "isbn") { + $this->formattedType = "ISBN"; + $this->uri = sprintf("https://www.worldcat.org/isbn/%s", $this->val); + } elseif ($this->type == "doi") { + $this->formattedType = "DOI"; + $this->uri = sprintf("https://dx.doi.org/%s", $this->val); + } elseif ($this->type == "douban") { + $this->formattedType = "Douban"; + $this->uri = sprintf("https://book.douban.com/subject/%s", $this->val); + } elseif ($this->type == "goodreads") { + $this->formattedType = "Goodreads"; + $this->uri = sprintf("https://www.goodreads.com/book/show/%s", $this->val); + } elseif ($this->type == "google") { + $this->formattedType = "Google Books"; + $this->uri = sprintf("https://books.google.com/books?id=%s", $this->val); + } elseif ($this->type == "kobo") { + $this->formattedType = "Kobo"; + $this->uri = sprintf("https://www.kobo.com/ebook/%s", $this->val); + } elseif ($this->type == "litres") { + $this->formattedType = "ЛитРес"; + $this->uri = sprintf("https://www.litres.ru/%s", $this->val); + } elseif ($this->type == "issn") { + $this->formattedType = "ISSN"; + $this->uri = sprintf("https://portal.issn.org/resource/ISSN/%s", $this->val); + } elseif ($this->type == "isfdb") { + $this->formattedType = "ISFDB"; + $this->uri = sprintf("http://www.isfdb.org/cgi-bin/pl.cgi?%s", $this->val); + } elseif ($this->type == "lubimyczytac") { + $this->formattedType = "Lubimyczytac"; + $this->uri = sprintf("https://lubimyczytac.pl/ksiazka/%s/ksiazka", $this->val); + } elseif ($this->type == "url") { + $this->formattedType = $this->type; + $this->uri = $this->val; + } else { + $this->formattedType = $this->type; + $this->uri = ''; + } + } + + public function getUri() + { + return $this->uri; + } +} diff --git a/lib/JSON_renderer.php b/lib/JSON_renderer.php new file mode 100644 index 000000000..ebea26a18 --- /dev/null +++ b/lib/JSON_renderer.php @@ -0,0 +1,277 @@ + + */ + +require_once dirname(__FILE__) . '/../base.php'; + +class JSONRenderer +{ + /** + * @param Book $book + * @return array + */ + public static function getBookContentArray($book) + { + global $config; + $i = 0; + $preferedData = []; + foreach ($config['cops_prefered_format'] as $format) { + if ($i == 2) { + break; + } + if ($data = $book->getDataFormat($format)) { + $i++; + array_push($preferedData, ["url" => $data->getHtmlLink(), + "viewUrl" => $data->getViewHtmlLink(), "name" => $format]); + } + } + + $publisher = $book->getPublisher(); + if (is_null($publisher)) { + $pn = ""; + $pu = ""; + } else { + $pn = $publisher->name; + $link = new LinkNavigation($publisher->getUri()); + $pu = $link->hrefXhtml(); + } + + $serie = $book->getSerie(); + if (is_null($serie)) { + $sn = ""; + $scn = ""; + $su = ""; + } else { + $sn = $serie->name; + $scn = str_format(localize("content.series.data"), $book->seriesIndex, $serie->name); + $link = new LinkNavigation($serie->getUri()); + $su = $link->hrefXhtml(); + } + $cc = $book->getCustomColumnValues($config['cops_calibre_custom_column_list'], true); + + return ["id" => $book->id, + "hasCover" => $book->hasCover, + "preferedData" => $preferedData, + "rating" => $book->getRating(), + "publisherName" => $pn, + "publisherurl" => $pu, + "pubDate" => $book->getPubDate(), + "languagesName" => $book->getLanguages(), + "authorsName" => $book->getAuthorsName(), + "tagsName" => $book->getTagsName(), + "seriesName" => $sn, + "seriesIndex" => $book->seriesIndex, + "seriesCompleteName" => $scn, + "seriesurl" => $su, + "customcolumns_list" => $cc]; + } + + /** + * @param Book $book + * @return array + */ + public static function getFullBookContentArray($book) + { + global $config; + $out = self::getBookContentArray($book); + $database = GetUrlParam(DB); + + $out ["coverurl"] = Data::getLink($book, "jpg", "image/jpeg", Link::OPDS_IMAGE_TYPE, "cover.jpg", null)->hrefXhtml(); + $out ["thumbnailurl"] = Data::getLink($book, "jpg", "image/jpeg", Link::OPDS_THUMBNAIL_TYPE, "cover.jpg", null, null, $config['cops_html_thumbnail_height'] * 2)->hrefXhtml(); + $out ["content"] = $book->getComment(false); + $out ["datas"] = []; + $dataKindle = $book->GetMostInterestingDataToSendToKindle(); + foreach ($book->getDatas() as $data) { + $tab = ["id" => $data->id, + "format" => $data->format, + "url" => $data->getHtmlLink(), + "viewUrl" => $data->getViewHtmlLink(), + "mail" => 0, + "readerUrl" => ""]; + if (!empty($config['cops_mail_configuration']) && !is_null($dataKindle) && $data->id == $dataKindle->id) { + $tab ["mail"] = 1; + } + if ($data->format == "EPUB") { + $tab ["readerUrl"] = "epubreader.php?data={$data->id}&db={$database}"; + } + array_push($out ["datas"], $tab); + } + $out ["authors"] = []; + foreach ($book->getAuthors() as $author) { + $link = new LinkNavigation($author->getUri()); + array_push($out ["authors"], ["name" => $author->name, "url" => $link->hrefXhtml()]); + } + $out ["tags"] = []; + foreach ($book->getTags() as $tag) { + $link = new LinkNavigation($tag->getUri()); + array_push($out ["tags"], ["name" => $tag->name, "url" => $link->hrefXhtml()]); + } + + $out ["identifiers"] = []; + foreach ($book->getIdentifiers() as $ident) { + array_push($out ["identifiers"], ["name" => $ident->formattedType, "url" => $ident->getUri()]); + } + + $out ["customcolumns_preview"] = $book->getCustomColumnValues($config['cops_calibre_custom_column_preview'], true); + + return $out; + } + + public static function getContentArray($entry) + { + if ($entry instanceof EntryBook) { + $out = [ "title" => $entry->title]; + $out ["book"] = self::getBookContentArray($entry->book); + return $out; + } + return [ "title" => $entry->title, "content" => $entry->content, "navlink" => $entry->getNavLink(), "number" => $entry->numberOfElement ]; + } + + public static function getContentArrayTypeahead($page) + { + $out = []; + foreach ($page->entryArray as $entry) { + if ($entry instanceof EntryBook) { + array_push($out, ["class" => $entry->className, "title" => $entry->title, "navlink" => $entry->book->getDetailUrl()]); + } else { + if (empty($entry->className) xor Base::noDatabaseSelected()) { + array_push($out, ["class" => $entry->className, "title" => $entry->title, "navlink" => $entry->getNavLink()]); + } else { + array_push($out, ["class" => $entry->className, "title" => $entry->content, "navlink" => $entry->getNavLink()]); + } + } + } + return $out; + } + + public static function addCompleteArray($in) + { + global $config; + $out = $in; + + $out ["c"] = ["version" => VERSION, "i18n" => [ + "coverAlt" => localize("i18n.coversection"), + "authorsTitle" => localize("authors.title"), + "bookwordTitle" => localize("bookword.title"), + "tagsTitle" => localize("tags.title"), + "linksTitle" => localize("links.title"), + "seriesTitle" => localize("series.title"), + "customizeTitle" => localize("customize.title"), + "aboutTitle" => localize("about.title"), + "previousAlt" => localize("paging.previous.alternate"), + "nextAlt" => localize("paging.next.alternate"), + "searchAlt" => localize("search.alternate"), + "sortAlt" => localize("sort.alternate"), + "homeAlt" => localize("home.alternate"), + "cogAlt" => localize("cog.alternate"), + "permalinkAlt" => localize("permalink.alternate"), + "publisherName" => localize("publisher.name"), + "pubdateTitle" => localize("pubdate.title"), + "languagesTitle" => localize("language.title"), + "contentTitle" => localize("content.summary"), + "filterClearAll" => localize("filter.clearall"), + "sortorderAsc" => localize("search.sortorder.asc"), + "sortorderDesc" => localize("search.sortorder.desc"), + "customizeEmail" => localize("customize.email")], + "url" => [ + "detailUrl" => "index.php?page=13&id={0}&db={1}", + "coverUrl" => "fetch.php?id={0}&db={1}", + "thumbnailUrl" => "fetch.php?height=" . $config['cops_html_thumbnail_height'] . "&id={0}&db={1}"], + "config" => [ + "use_fancyapps" => $config ["cops_use_fancyapps"], + "max_item_per_page" => $config['cops_max_item_per_page'], + "kindleHack" => "", + "server_side_rendering" => useServerSideRendering(), + "html_tag_filter" => $config['cops_html_tag_filter']]]; + if ($config['cops_thumbnail_handling'] == "1") { + $out ["c"]["url"]["thumbnailUrl"] = $out ["c"]["url"]["coverUrl"]; + } elseif (!empty($config['cops_thumbnail_handling'])) { + $out ["c"]["url"]["thumbnailUrl"] = $config['cops_thumbnail_handling']; + } + if (preg_match("/./", $_SERVER['HTTP_USER_AGENT'])) { + $out ["c"]["config"]["kindleHack"] = 'style="text-decoration: none !important;"'; + } + return $out; + } + + public static function getJson($complete = false) + { + global $config; + $page = getURLParam("page", Base::PAGE_INDEX); + $query = getURLParam("query"); + $search = getURLParam("search"); + $qid = getURLParam("id"); + $n = getURLParam("n", "1"); + $database = GetUrlParam(DB); + + $currentPage = Page::getPage($page, $qid, $query, $n); + $currentPage->InitializeContent(); + + if ($search) { + return self::getContentArrayTypeahead($currentPage); + } + + $out = [ "title" => $currentPage->title]; + $entries = []; + foreach ($currentPage->entryArray as $entry) { + array_push($entries, self::getContentArray($entry)); + } + if (!is_null($currentPage->book)) { + $out ["book"] = self::getFullBookContentArray($currentPage->book); + } + $out ["databaseId"] = GetUrlParam(DB, ""); + $out ["databaseName"] = Base::getDbName(); + if ($out ["databaseId"] == "") { + $out ["databaseName"] = ""; + } + $out ["fullTitle"] = $out ["title"]; + if ($out ["databaseId"] != "" && $out ["databaseName"] != $out ["fullTitle"]) { + $out ["fullTitle"] = $out ["databaseName"] . " > " . $out ["fullTitle"]; + } + $out ["page"] = $page; + $out ["multipleDatabase"] = Base::isMultipleDatabaseEnabled() ? 1 : 0; + $out ["entries"] = $entries; + $out ["isPaginated"] = 0; + if ($currentPage->isPaginated()) { + $prevLink = $currentPage->getPrevLink(); + $nextLink = $currentPage->getNextLink(); + $out ["isPaginated"] = 1; + $out ["prevLink"] = ""; + if (!is_null($prevLink)) { + $out ["prevLink"] = $prevLink->hrefXhtml(); + } + $out ["nextLink"] = ""; + if (!is_null($nextLink)) { + $out ["nextLink"] = $nextLink->hrefXhtml(); + } + $out ["maxPage"] = $currentPage->getMaxPage(); + $out ["currentPage"] = $currentPage->n; + } + if (!is_null(getURLParam("complete")) || $complete) { + $out = self::addCompleteArray($out); + } + + $out ["containsBook"] = 0; + if ($currentPage->containsBook()) { + $out ["containsBook"] = 1; + } + + $out["abouturl"] = "index.php" . addURLParameter("?page=" . Base::PAGE_ABOUT, DB, $database); + + if ($page == Base::PAGE_ABOUT) { + $temp = preg_replace("/\About COPS\<\/h1\>/", "

    About COPS " . VERSION . "

    ", file_get_contents('about.html')); + $out ["fullhtml"] = $temp; + } + + $out ["homeurl"] = "index.php"; + if ($page != Base::PAGE_INDEX && !is_null($database)) { + $out ["homeurl"] = $out ["homeurl"] . "?" . addURLParameter("", DB, $database); + } + + return $out; + } +} diff --git a/lib/Language.php b/lib/Language.php new file mode 100644 index 000000000..d56691f71 --- /dev/null +++ b/lib/Language.php @@ -0,0 +1,81 @@ + + */ + +class Language extends Base +{ + public const ALL_LANGUAGES_ID = "cops:languages"; + + public $id; + public $lang_code; + + public function __construct($pid, $plang_code) + { + $this->id = $pid; + $this->lang_code = $plang_code; + } + + public function getUri() + { + return "?page=".parent::PAGE_LANGUAGE_DETAIL."&id=$this->id"; + } + + public function getEntryId() + { + return self::ALL_LANGUAGES_ID.":".$this->id; + } + + public static function getLanguageString($code) + { + $string = localize("languages.".$code); + if (preg_match("/^languages/", $string)) { + return $code; + } + return $string; + } + + public static function getCount() + { + // str_format (localize("languages.alphabetical", count(array)) + return parent::getCountGeneric("languages", self::ALL_LANGUAGES_ID, parent::PAGE_ALL_LANGUAGES); + } + + public static function getLanguageById($languageId) + { + $result = parent::getDb()->prepare('select id, lang_code from languages where id = ?'); + $result->execute([$languageId]); + if ($post = $result->fetchObject()) { + return new Language($post->id, Language::getLanguageString($post->lang_code)); + } + return null; + } + + + + public static function getAllLanguages() + { + $result = parent::getDb()->query('select languages.id as id, languages.lang_code as lang_code, count(*) as count +from languages, books_languages_link +where languages.id = books_languages_link.lang_code +group by languages.id, books_languages_link.lang_code +order by languages.lang_code'); + $entryArray = []; + while ($post = $result->fetchObject()) { + $language = new Language($post->id, $post->lang_code); + array_push($entryArray, new Entry( + Language::getLanguageString($language->lang_code), + $language->getEntryId(), + str_format(localize("bookword", $post->count), $post->count), + "text", + [ new LinkNavigation($language->getUri())], + "", + $post->count + )); + } + return $entryArray; + } +} diff --git a/lib/Link.php b/lib/Link.php new file mode 100644 index 000000000..f571740d1 --- /dev/null +++ b/lib/Link.php @@ -0,0 +1,44 @@ + + */ + +class Link +{ + public const OPDS_THUMBNAIL_TYPE = "http://opds-spec.org/image/thumbnail"; + public const OPDS_IMAGE_TYPE = "http://opds-spec.org/image"; + public const OPDS_ACQUISITION_TYPE = "http://opds-spec.org/acquisition"; + public const OPDS_NAVIGATION_TYPE = "application/atom+xml;profile=opds-catalog;kind=navigation"; + public const OPDS_PAGING_TYPE = "application/atom+xml;profile=opds-catalog;kind=acquisition"; + + public $href; + public $type; + public $rel; + public $title; + public $facetGroup; + public $activeFacet; + + public function __construct($phref, $ptype, $prel = null, $ptitle = null, $pfacetGroup = null, $pactiveFacet = false) + { + $this->href = $phref; + $this->type = $ptype; + $this->rel = $prel; + $this->title = $ptitle; + $this->facetGroup = $pfacetGroup; + $this->activeFacet = $pactiveFacet; + } + + public function hrefXhtml() + { + return $this->href; + } + + public function getScriptName() + { + $parts = explode('/', $_SERVER["SCRIPT_NAME"]); + return $parts[count($parts) - 1]; + } +} diff --git a/lib/LinkFacet.php b/lib/LinkFacet.php new file mode 100644 index 000000000..0df9bf49b --- /dev/null +++ b/lib/LinkFacet.php @@ -0,0 +1,19 @@ + + */ + +class LinkFacet extends Link +{ + public function __construct($phref, $ptitle = null, $pfacetGroup = null, $pactiveFacet = false) + { + parent::__construct($phref, Link::OPDS_PAGING_TYPE, "http://opds-spec.org/facet", $ptitle, $pfacetGroup, $pactiveFacet); + if (!is_null(GetUrlParam(DB))) { + $this->href = addURLParameter($this->href, DB, GetUrlParam(DB)); + } + $this->href = parent::getScriptName() . $this->href; + } +} diff --git a/lib/LinkNavigation.php b/lib/LinkNavigation.php new file mode 100644 index 000000000..28cf0ee38 --- /dev/null +++ b/lib/LinkNavigation.php @@ -0,0 +1,26 @@ + + */ + +class LinkNavigation extends Link +{ + public function __construct($phref, $prel = null, $ptitle = null) + { + parent::__construct($phref, Link::OPDS_NAVIGATION_TYPE, $prel, $ptitle); + if (!is_null(GetUrlParam(DB))) { + $this->href = addURLParameter($this->href, DB, GetUrlParam(DB)); + } + if (!preg_match("#^\?(.*)#", $this->href) && !empty($this->href)) { + $this->href = "?" . $this->href; + } + if (preg_match("/(bookdetail|getJSON).php/", parent::getScriptName())) { + $this->href = "index.php" . $this->href; + } else { + $this->href = parent::getScriptName() . $this->href; + } + } +} diff --git a/lib/OPDS_renderer.php b/lib/OPDS_renderer.php new file mode 100644 index 000000000..3f01be854 --- /dev/null +++ b/lib/OPDS_renderer.php @@ -0,0 +1,284 @@ + + */ + +require_once dirname(__FILE__) . '/../base.php'; + +class OPDSRenderer +{ + private $xmlStream = null; + private $updated = null; + + private function getUpdatedTime() + { + if (is_null($this->updated)) { + $this->updated = time(); + } + return date(DATE_ATOM, $this->updated); + } + + private function getXmlStream() + { + if (is_null($this->xmlStream)) { + $this->xmlStream = new XMLWriter(); + $this->xmlStream->openMemory(); + $this->xmlStream->setIndent(true); + } + return $this->xmlStream; + } + + public function getOpenSearch() + { + global $config; + $xml = new XMLWriter(); + $xml->openMemory(); + $xml->setIndent(true); + $xml->startDocument('1.0', 'UTF-8'); + $xml->startElement("OpenSearchDescription"); + $xml->writeAttribute("xmlns", "http://a9.com/-/spec/opensearch/1.1/"); + $xml->startElement("ShortName"); + $xml->text("My catalog"); + $xml->endElement(); + $xml->startElement("Description"); + $xml->text("Search for ebooks"); + $xml->endElement(); + $xml->startElement("InputEncoding"); + $xml->text("UTF-8"); + $xml->endElement(); + $xml->startElement("OutputEncoding"); + $xml->text("UTF-8"); + $xml->endElement(); + $xml->startElement("Image"); + $xml->writeAttribute("type", "image/x-icon"); + $xml->writeAttribute("width", "16"); + $xml->writeAttribute("height", "16"); + $xml->text($config['cops_icon']); + $xml->endElement(); + $xml->startElement("Url"); + $xml->writeAttribute("type", 'application/atom+xml'); + $urlparam = "?query={searchTerms}"; + if (!is_null(GetUrlParam(DB))) { + $urlparam = addURLParameter($urlparam, DB, GetUrlParam(DB)); + } + $urlparam = str_replace("%7B", "{", $urlparam); + $urlparam = str_replace("%7D", "}", $urlparam); + $xml->writeAttribute("template", $config['cops_full_url'] . 'feed.php' . $urlparam); + $xml->endElement(); + $xml->startElement("Query"); + $xml->writeAttribute("role", "example"); + $xml->writeAttribute("searchTerms", "robot"); + $xml->endElement(); + $xml->endElement(); + $xml->endDocument(); + return $xml->outputMemory(true); + } + + private function startXmlDocument($page) + { + global $config; + self::getXmlStream()->startDocument('1.0', 'UTF-8'); + self::getXmlStream()->startElement("feed"); + self::getXmlStream()->writeAttribute("xmlns", "http://www.w3.org/2005/Atom"); + self::getXmlStream()->writeAttribute("xmlns:xhtml", "http://www.w3.org/1999/xhtml"); + self::getXmlStream()->writeAttribute("xmlns:opds", "http://opds-spec.org/2010/catalog"); + self::getXmlStream()->writeAttribute("xmlns:opensearch", "http://a9.com/-/spec/opensearch/1.1/"); + self::getXmlStream()->writeAttribute("xmlns:dcterms", "http://purl.org/dc/terms/"); + self::getXmlStream()->startElement("title"); + self::getXmlStream()->text($page->title); + self::getXmlStream()->endElement(); + if ($page->subtitle != "") { + self::getXmlStream()->startElement("subtitle"); + self::getXmlStream()->text($page->subtitle); + self::getXmlStream()->endElement(); + } + self::getXmlStream()->startElement("id"); + if ($page->idPage) { + $idPage = $page->idPage; + if (!is_null(GetUrlParam(DB))) { + $idPage = str_replace("cops:", "cops:" . GetUrlParam(DB) . ":", $idPage); + } + self::getXmlStream()->text($idPage); + } else { + self::getXmlStream()->text($_SERVER['REQUEST_URI']); + } + self::getXmlStream()->endElement(); + self::getXmlStream()->startElement("updated"); + self::getXmlStream()->text(self::getUpdatedTime()); + self::getXmlStream()->endElement(); + self::getXmlStream()->startElement("icon"); + self::getXmlStream()->text($page->favicon); + self::getXmlStream()->endElement(); + self::getXmlStream()->startElement("author"); + self::getXmlStream()->startElement("name"); + self::getXmlStream()->text($page->authorName); + self::getXmlStream()->endElement(); + self::getXmlStream()->startElement("uri"); + self::getXmlStream()->text($page->authorUri); + self::getXmlStream()->endElement(); + self::getXmlStream()->startElement("email"); + self::getXmlStream()->text($page->authorEmail); + self::getXmlStream()->endElement(); + self::getXmlStream()->endElement(); + $link = new LinkNavigation("", "start", "Home"); + self::renderLink($link); + $link = new LinkNavigation("?" . getQueryString(), "self"); + self::renderLink($link); + $urlparam = "?"; + if (!is_null(GetUrlParam(DB))) { + $urlparam = addURLParameter($urlparam, DB, GetUrlParam(DB)); + } + if ($config['cops_generate_invalid_opds_stream'] == 0 || preg_match("/(MantanoReader|FBReader)/", $_SERVER['HTTP_USER_AGENT'])) { + // Good and compliant way of handling search + $urlparam = addURLParameter($urlparam, "page", Base::PAGE_OPENSEARCH); + $link = new Link("feed.php" . $urlparam, "application/opensearchdescription+xml", "search", "Search here"); + } else { + // Bad way, will be removed when OPDS client are fixed + $urlparam = addURLParameter($urlparam, "query", "{searchTerms}"); + $urlparam = str_replace("%7B", "{", $urlparam); + $urlparam = str_replace("%7D", "}", $urlparam); + $link = new Link($config['cops_full_url'] . 'feed.php' . $urlparam, "application/atom+xml", "search", "Search here"); + } + self::renderLink($link); + if ($page->containsBook() && !is_null($config['cops_books_filter']) && count($config['cops_books_filter']) > 0) { + $Urlfilter = getURLParam("tag", ""); + foreach ($config['cops_books_filter'] as $lib => $filter) { + $link = new LinkFacet("?" . addURLParameter(getQueryString(), "tag", $filter), $lib, localize("tagword.title"), $filter == $Urlfilter); + self::renderLink($link); + } + } + } + + private function endXmlDocument() + { + self::getXmlStream()->endElement(); + self::getXmlStream()->endDocument(); + return self::getXmlStream()->outputMemory(true); + } + + private function renderLink($link) + { + self::getXmlStream()->startElement("link"); + self::getXmlStream()->writeAttribute("href", $link->href); + self::getXmlStream()->writeAttribute("type", $link->type); + if (!is_null($link->rel)) { + self::getXmlStream()->writeAttribute("rel", $link->rel); + } + if (!is_null($link->title)) { + self::getXmlStream()->writeAttribute("title", $link->title); + } + if (!is_null($link->facetGroup)) { + self::getXmlStream()->writeAttribute("opds:facetGroup", $link->facetGroup); + } + if ($link->activeFacet) { + self::getXmlStream()->writeAttribute("opds:activeFacet", "true"); + } + self::getXmlStream()->endElement(); + } + + private function getPublicationDate($book) + { + $dateYmd = substr($book->pubdate, 0, 10); + $pubdate = \DateTime::createFromFormat('Y-m-d', $dateYmd); + if ($pubdate === false || + $pubdate->format("Y") == "0101" || + $pubdate->format("Y") == "0100") { + return ""; + } + return $pubdate->format("Y-m-d"); + } + + private function renderEntry($entry) + { + self::getXmlStream()->startElement("title"); + self::getXmlStream()->text($entry->title); + self::getXmlStream()->endElement(); + self::getXmlStream()->startElement("updated"); + self::getXmlStream()->text(self::getUpdatedTime()); + self::getXmlStream()->endElement(); + self::getXmlStream()->startElement("id"); + self::getXmlStream()->text($entry->id); + self::getXmlStream()->endElement(); + self::getXmlStream()->startElement("content"); + self::getXmlStream()->writeAttribute("type", $entry->contentType); + if ($entry->contentType == "text") { + self::getXmlStream()->text($entry->content); + } else { + self::getXmlStream()->writeRaw($entry->content); + } + self::getXmlStream()->endElement(); + foreach ($entry->linkArray as $link) { + self::renderLink($link); + } + + if (get_class($entry) != "EntryBook") { + return; + } + + foreach ($entry->book->getAuthors() as $author) { + self::getXmlStream()->startElement("author"); + self::getXmlStream()->startElement("name"); + self::getXmlStream()->text($author->name); + self::getXmlStream()->endElement(); + self::getXmlStream()->startElement("uri"); + self::getXmlStream()->text("feed.php" . $author->getUri()); + self::getXmlStream()->endElement(); + self::getXmlStream()->endElement(); + } + foreach ($entry->book->getTags() as $category) { + self::getXmlStream()->startElement("category"); + self::getXmlStream()->writeAttribute("term", $category->name); + self::getXmlStream()->writeAttribute("label", $category->name); + self::getXmlStream()->endElement(); + } + if ($entry->book->getPubDate() != "") { + self::getXmlStream()->startElement("dcterms:issued"); + self::getXmlStream()->text(self::getPublicationDate($entry->book)); + self::getXmlStream()->endElement(); + self::getXmlStream()->startElement("published"); + self::getXmlStream()->text(self::getPublicationDate($entry->book) . "T08:08:08Z"); + self::getXmlStream()->endElement(); + } + + $lang = $entry->book->getLanguages(); + if (!empty($lang)) { + self::getXmlStream()->startElement("dcterms:language"); + self::getXmlStream()->text($lang); + self::getXmlStream()->endElement(); + } + } + + public function render($page) + { + global $config; + self::startXmlDocument($page); + if ($page->isPaginated()) { + self::getXmlStream()->startElement("opensearch:totalResults"); + self::getXmlStream()->text($page->totalNumber); + self::getXmlStream()->endElement(); + self::getXmlStream()->startElement("opensearch:itemsPerPage"); + self::getXmlStream()->text($config['cops_max_item_per_page']); + self::getXmlStream()->endElement(); + self::getXmlStream()->startElement("opensearch:startIndex"); + self::getXmlStream()->text(($page->n - 1) * $config['cops_max_item_per_page'] + 1); + self::getXmlStream()->endElement(); + $prevLink = $page->getPrevLink(); + $nextLink = $page->getNextLink(); + if (!is_null($prevLink)) { + self::renderLink($prevLink); + } + if (!is_null($nextLink)) { + self::renderLink($nextLink); + } + } + foreach ($page->entryArray as $entry) { + self::getXmlStream()->startElement("entry"); + self::renderEntry($entry); + self::getXmlStream()->endElement(); + } + return self::endXmlDocument(); + } +} diff --git a/lib/Page.php b/lib/Page.php new file mode 100644 index 000000000..94b3cd25d --- /dev/null +++ b/lib/Page.php @@ -0,0 +1,203 @@ + + */ + +class Page +{ + public $title; + public $subtitle = ""; + public $authorName = ""; + public $authorUri = ""; + public $authorEmail = ""; + public $idPage; + public $idGet; + public $query; + public $favicon; + public $n; + public $book; + public $totalNumber = -1; + + /* @var Entry[] */ + public $entryArray = []; + + public static function getPage($pageId, $id, $query, $n) + { + switch ($pageId) { + case Base::PAGE_ALL_AUTHORS : + return new PageAllAuthors($id, $query, $n); + case Base::PAGE_AUTHORS_FIRST_LETTER : + return new PageAllAuthorsLetter($id, $query, $n); + case Base::PAGE_AUTHOR_DETAIL : + return new PageAuthorDetail($id, $query, $n); + case Base::PAGE_ALL_TAGS : + return new PageAllTags($id, $query, $n); + case Base::PAGE_TAG_DETAIL : + return new PageTagDetail($id, $query, $n); + case Base::PAGE_ALL_LANGUAGES : + return new PageAllLanguages($id, $query, $n); + case Base::PAGE_LANGUAGE_DETAIL : + return new PageLanguageDetail($id, $query, $n); + case Base::PAGE_ALL_CUSTOMS : + return new PageAllCustoms($id, $query, $n); + case Base::PAGE_CUSTOM_DETAIL : + return new PageCustomDetail($id, $query, $n); + case Base::PAGE_ALL_RATINGS : + return new PageAllRating($id, $query, $n); + case Base::PAGE_RATING_DETAIL : + return new PageRatingDetail($id, $query, $n); + case Base::PAGE_ALL_SERIES : + return new PageAllSeries($id, $query, $n); + case Base::PAGE_ALL_BOOKS : + return new PageAllBooks($id, $query, $n); + case Base::PAGE_ALL_BOOKS_LETTER: + return new PageAllBooksLetter($id, $query, $n); + case Base::PAGE_ALL_RECENT_BOOKS : + return new PageRecentBooks($id, $query, $n); + case Base::PAGE_SERIE_DETAIL : + return new PageSerieDetail($id, $query, $n); + case Base::PAGE_OPENSEARCH_QUERY : + return new PageQueryResult($id, $query, $n); + case Base::PAGE_BOOK_DETAIL : + return new PageBookDetail($id, $query, $n); + case Base::PAGE_ALL_PUBLISHERS: + return new PageAllPublishers($id, $query, $n); + case Base::PAGE_PUBLISHER_DETAIL : + return new PagePublisherDetail($id, $query, $n); + case Base::PAGE_ABOUT : + return new PageAbout($id, $query, $n); + case Base::PAGE_CUSTOMIZE : + return new PageCustomize($id, $query, $n); + default: + $page = new Page($id, $query, $n); + $page->idPage = "cops:catalog"; + return $page; + } + } + + public function __construct($pid, $pquery, $pn) + { + global $config; + + $this->idGet = $pid; + $this->query = $pquery; + $this->n = $pn; + $this->favicon = $config['cops_icon']; + $this->authorName = $config['cops_author_name'] ?: 'Sébastien Lucas'; + $this->authorUri = $config['cops_author_uri'] ?: 'http://blog.slucas.fr'; + $this->authorEmail = $config['cops_author_email'] ?: 'sebastien@slucas.fr'; + } + + public function InitializeContent() + { + global $config; + $this->title = $config['cops_title_default']; + $this->subtitle = $config['cops_subtitle_default']; + if (Base::noDatabaseSelected()) { + $i = 0; + foreach (Base::getDbNameList() as $key) { + $nBooks = Book::getBookCount($i); + array_push($this->entryArray, new Entry( + $key, + "cops:{$i}:catalog", + str_format(localize("bookword", $nBooks), $nBooks), + "text", + [ new LinkNavigation("?" . DB . "={$i}")], + "", + $nBooks + )); + $i++; + Base::clearDb(); + } + } else { + if (!in_array(PageQueryResult::SCOPE_AUTHOR, getCurrentOption('ignored_categories'))) { + array_push($this->entryArray, Author::getCount()); + } + if (!in_array(PageQueryResult::SCOPE_SERIES, getCurrentOption('ignored_categories'))) { + $series = Serie::getCount(); + if (!is_null($series)) { + array_push($this->entryArray, $series); + } + } + if (!in_array(PageQueryResult::SCOPE_PUBLISHER, getCurrentOption('ignored_categories'))) { + $publisher = Publisher::getCount(); + if (!is_null($publisher)) { + array_push($this->entryArray, $publisher); + } + } + if (!in_array(PageQueryResult::SCOPE_TAG, getCurrentOption('ignored_categories'))) { + $tags = Tag::getCount(); + if (!is_null($tags)) { + array_push($this->entryArray, $tags); + } + } + if (!in_array(PageQueryResult::SCOPE_RATING, getCurrentOption('ignored_categories'))) { + $rating = Rating::getCount(); + if (!is_null($rating)) { + array_push($this->entryArray, $rating); + } + } + if (!in_array("language", getCurrentOption('ignored_categories'))) { + $languages = Language::getCount(); + if (!is_null($languages)) { + array_push($this->entryArray, $languages); + } + } + foreach ($config['cops_calibre_custom_column'] as $lookup) { + $customColumn = CustomColumnType::createByLookup($lookup); + if (!is_null($customColumn) && $customColumn->isSearchable()) { + array_push($this->entryArray, $customColumn->getCount()); + } + } + $this->entryArray = array_merge($this->entryArray, Book::getCount()); + + if (Base::isMultipleDatabaseEnabled()) { + $this->title = Base::getDbName(); + } + } + } + + public function isPaginated() + { + return (getCurrentOption("max_item_per_page") != -1 && + $this->totalNumber != -1 && + $this->totalNumber > getCurrentOption("max_item_per_page")); + } + + public function getNextLink() + { + $currentUrl = preg_replace("/\&n=.*?$/", "", "?" . getQueryString()); + if (($this->n) * getCurrentOption("max_item_per_page") < $this->totalNumber) { + return new LinkNavigation($currentUrl . "&n=" . ($this->n + 1), "next", localize("paging.next.alternate")); + } + return null; + } + + public function getPrevLink() + { + $currentUrl = preg_replace("/\&n=.*?$/", "", "?" . getQueryString()); + if ($this->n > 1) { + return new LinkNavigation($currentUrl . "&n=" . ($this->n - 1), "previous", localize("paging.previous.alternate")); + } + return null; + } + + public function getMaxPage() + { + return ceil($this->totalNumber / getCurrentOption("max_item_per_page")); + } + + public function containsBook() + { + if (count($this->entryArray) == 0) { + return false; + } + if (get_class($this->entryArray [0]) == "EntryBook") { + return true; + } + return false; + } +} diff --git a/lib/PageAbout.php b/lib/PageAbout.php new file mode 100644 index 000000000..9aef7a6af --- /dev/null +++ b/lib/PageAbout.php @@ -0,0 +1,15 @@ + + */ + +class PageAbout extends Page +{ + public function InitializeContent() + { + $this->title = localize("about.title"); + } +} diff --git a/lib/PageAllAuthors.php b/lib/PageAllAuthors.php new file mode 100644 index 000000000..507f5497a --- /dev/null +++ b/lib/PageAllAuthors.php @@ -0,0 +1,21 @@ + + */ + +class PageAllAuthors extends Page +{ + public function InitializeContent() + { + $this->title = localize("authors.title"); + if (getCurrentOption("author_split_first_letter") == 1) { + $this->entryArray = Author::getAllAuthorsByFirstLetter(); + } else { + $this->entryArray = Author::getAllAuthors(); + } + $this->idPage = Author::ALL_AUTHORS_ID; + } +} diff --git a/lib/PageAllAuthorsLetter.php b/lib/PageAllAuthorsLetter.php new file mode 100644 index 000000000..cb6367f0b --- /dev/null +++ b/lib/PageAllAuthorsLetter.php @@ -0,0 +1,17 @@ + + */ + +class PageAllAuthorsLetter extends Page +{ + public function InitializeContent() + { + $this->idPage = Author::getEntryIdByLetter($this->idGet); + $this->entryArray = Author::getAuthorsByStartingLetter($this->idGet); + $this->title = str_format(localize("splitByLetter.letter"), str_format(localize("authorword", count($this->entryArray)), count($this->entryArray)), $this->idGet); + } +} diff --git a/lib/PageAllBooks.php b/lib/PageAllBooks.php new file mode 100644 index 000000000..ee89606f2 --- /dev/null +++ b/lib/PageAllBooks.php @@ -0,0 +1,21 @@ + + */ + +class PageAllBooks extends Page +{ + public function InitializeContent() + { + $this->title = localize("allbooks.title"); + if (getCurrentOption("titles_split_first_letter") == 1) { + $this->entryArray = Book::getAllBooks(); + } else { + [$this->entryArray, $this->totalNumber] = Book::getBooks($this->n); + } + $this->idPage = Book::ALL_BOOKS_ID; + } +} diff --git a/lib/PageAllBooksLetter.php b/lib/PageAllBooksLetter.php new file mode 100644 index 000000000..ef99d6f23 --- /dev/null +++ b/lib/PageAllBooksLetter.php @@ -0,0 +1,23 @@ + + */ + +class PageAllBooksLetter extends Page +{ + public function InitializeContent() + { + [$this->entryArray, $this->totalNumber] = Book::getBooksByStartingLetter($this->idGet, $this->n); + $this->idPage = Book::getEntryIdByLetter($this->idGet); + + $count = $this->totalNumber; + if ($count == -1) { + $count = count($this->entryArray); + } + + $this->title = str_format(localize("splitByLetter.letter"), str_format(localize("bookword", $count), $count), $this->idGet); + } +} diff --git a/lib/PageAllCustoms.php b/lib/PageAllCustoms.php new file mode 100644 index 000000000..abae5db52 --- /dev/null +++ b/lib/PageAllCustoms.php @@ -0,0 +1,20 @@ + + */ + +class PageAllCustoms extends Page +{ + public function InitializeContent() + { + $customId = getURLParam("custom", null); + $columnType = CustomColumnType::createByCustomID($customId); + + $this->title = $columnType->getTitle(); + $this->entryArray = $columnType->getAllCustomValues(); + $this->idPage = $columnType->getAllCustomsId(); + } +} diff --git a/lib/PageAllLanguages.php b/lib/PageAllLanguages.php new file mode 100644 index 000000000..15dc93b14 --- /dev/null +++ b/lib/PageAllLanguages.php @@ -0,0 +1,17 @@ + + */ + +class PageAllLanguages extends Page +{ + public function InitializeContent() + { + $this->title = localize("languages.title"); + $this->entryArray = Language::getAllLanguages(); + $this->idPage = Language::ALL_LANGUAGES_ID; + } +} diff --git a/lib/PageAllPublishers.php b/lib/PageAllPublishers.php new file mode 100644 index 000000000..d5b7e67b7 --- /dev/null +++ b/lib/PageAllPublishers.php @@ -0,0 +1,17 @@ + + */ + +class PageAllPublishers extends Page +{ + public function InitializeContent() + { + $this->title = localize("publishers.title"); + $this->entryArray = Publisher::getAllPublishers(); + $this->idPage = Publisher::ALL_PUBLISHERS_ID; + } +} diff --git a/lib/PageAllRating.php b/lib/PageAllRating.php new file mode 100644 index 000000000..fc5815e36 --- /dev/null +++ b/lib/PageAllRating.php @@ -0,0 +1,17 @@ + + */ + +class PageAllRating extends Page +{ + public function InitializeContent() + { + $this->title = localize("ratings.title"); + $this->entryArray = Rating::getAllRatings(); + $this->idPage = Rating::ALL_RATING_ID; + } +} diff --git a/lib/PageAllSeries.php b/lib/PageAllSeries.php new file mode 100644 index 000000000..d70cd211a --- /dev/null +++ b/lib/PageAllSeries.php @@ -0,0 +1,17 @@ + + */ + +class PageAllSeries extends Page +{ + public function InitializeContent() + { + $this->title = localize("series.title"); + $this->entryArray = Serie::getAllSeries(); + $this->idPage = Serie::ALL_SERIES_ID; + } +} diff --git a/lib/PageAllTags.php b/lib/PageAllTags.php new file mode 100644 index 000000000..e90c71eea --- /dev/null +++ b/lib/PageAllTags.php @@ -0,0 +1,17 @@ + + */ + +class PageAllTags extends Page +{ + public function InitializeContent() + { + $this->title = localize("tags.title"); + $this->entryArray = Tag::getAllTags(); + $this->idPage = Tag::ALL_TAGS_ID; + } +} diff --git a/lib/PageAuthorDetail.php b/lib/PageAuthorDetail.php new file mode 100644 index 000000000..aea53ae1b --- /dev/null +++ b/lib/PageAuthorDetail.php @@ -0,0 +1,18 @@ + + */ + +class PageAuthorDetail extends Page +{ + public function InitializeContent() + { + $author = Author::getAuthorById($this->idGet); + $this->idPage = $author->getEntryId(); + $this->title = $author->name; + [$this->entryArray, $this->totalNumber] = Book::getBooksByAuthor($this->idGet, $this->n); + } +} diff --git a/lib/PageBookDetail.php b/lib/PageBookDetail.php new file mode 100644 index 000000000..f182bd706 --- /dev/null +++ b/lib/PageBookDetail.php @@ -0,0 +1,16 @@ + + */ + +class PageBookDetail extends Page +{ + public function InitializeContent() + { + $this->book = Book::getBookById($this->idGet); + $this->title = $this->book->title; + } +} diff --git a/lib/PageCustomDetail.php b/lib/PageCustomDetail.php new file mode 100644 index 000000000..bc8a60ddd --- /dev/null +++ b/lib/PageCustomDetail.php @@ -0,0 +1,19 @@ + + */ + +class PageCustomDetail extends Page +{ + public function InitializeContent() + { + $customId = getURLParam("custom", null); + $custom = CustomColumn::createCustom($customId, $this->idGet); + $this->idPage = $custom->getEntryId(); + $this->title = $custom->value; + [$this->entryArray, $this->totalNumber] = Book::getBooksByCustom($custom, $this->idGet, $this->n); + } +} diff --git a/lib/PageCustomize.php b/lib/PageCustomize.php new file mode 100644 index 000000000..5f1396568 --- /dev/null +++ b/lib/PageCustomize.php @@ -0,0 +1,156 @@ + + */ + +class PageCustomize extends Page +{ + private function isChecked($key, $testedValue = 1) + { + $value = getCurrentOption($key); + if (is_array($value)) { + if (in_array($testedValue, $value)) { + return "checked='checked'"; + } + } else { + if ($value == $testedValue) { + return "checked='checked'"; + } + } + return ""; + } + + private function isSelected($key, $value) + { + if (getCurrentOption($key) == $value) { + return "selected='selected'"; + } + return ""; + } + + private function getTemplateList() + { + $result = []; + foreach (glob("templates/*") as $filename) { + if (preg_match('/templates\/(.*)/', $filename, $m)) { + array_push($result, $m [1]); + } + } + return $result; + } + + private function getStyleList() + { + $result = []; + foreach (glob("templates/" . getCurrentTemplate() . "/styles/style-*.css") as $filename) { + if (preg_match('/styles\/style-(.*?)\.css/', $filename, $m)) { + array_push($result, $m [1]); + } + } + return $result; + } + + public function InitializeContent() + { + $this->title = localize("customize.title"); + $this->entryArray = []; + + $ignoredBaseArray = [PageQueryResult::SCOPE_AUTHOR, + PageQueryResult::SCOPE_TAG, + PageQueryResult::SCOPE_SERIES, + PageQueryResult::SCOPE_PUBLISHER, + PageQueryResult::SCOPE_RATING, + "language"]; + + $content = ""; + if (!preg_match("/(Kobo|Kindle\/3.0|EBRD1101)/", $_SERVER['HTTP_USER_AGENT'])) { + $content .= "'; + } else { + foreach ($this-> getTemplateList() as $filename) { + $content .= "isChecked("template", $filename) . " />"; + } + } + array_push($this->entryArray, new Entry( + "Template", + "", + $content, + "text", + [] + )); + + $content = ""; + if (!preg_match("/(Kobo|Kindle\/3.0|EBRD1101)/", $_SERVER['HTTP_USER_AGENT'])) { + $content .= ''; + } else { + foreach ($this-> getStyleList() as $filename) { + $content .= "isChecked("style", $filename) . " />"; + } + } + array_push($this->entryArray, new Entry( + localize("customize.style"), + "", + $content, + "text", + [] + )); + if (!useServerSideRendering()) { + $content = 'isChecked("use_fancyapps") . ' />'; + array_push($this->entryArray, new Entry( + localize("customize.fancybox"), + "", + $content, + "text", + [] + )); + } + $content = ''; + array_push($this->entryArray, new Entry( + localize("customize.paging"), + "", + $content, + "text", + [] + )); + $content = ''; + array_push($this->entryArray, new Entry( + localize("customize.email"), + "", + $content, + "text", + [] + )); + $content = 'isChecked("html_tag_filter") . ' />'; + array_push($this->entryArray, new Entry( + localize("customize.filter"), + "", + $content, + "text", + [] + )); + $content = ""; + foreach ($ignoredBaseArray as $key) { + $keyPlural = preg_replace('/(ss)$/', 's', $key . "s"); + $content .= 'isChecked("ignored_categories", $key) . ' > ' . localize("{$keyPlural}.title") . ' '; + } + + array_push($this->entryArray, new Entry( + localize("customize.ignored"), + "", + $content, + "text", + [] + )); + } +} diff --git a/lib/PageLanguageDetail.php b/lib/PageLanguageDetail.php new file mode 100644 index 000000000..0bb2511cb --- /dev/null +++ b/lib/PageLanguageDetail.php @@ -0,0 +1,18 @@ + + */ + +class PageLanguageDetail extends Page +{ + public function InitializeContent() + { + $language = Language::getLanguageById($this->idGet); + $this->idPage = $language->getEntryId(); + $this->title = $language->lang_code; + [$this->entryArray, $this->totalNumber] = Book::getBooksByLanguage($this->idGet, $this->n); + } +} diff --git a/lib/PagePublisherDetail.php b/lib/PagePublisherDetail.php new file mode 100644 index 000000000..f99903598 --- /dev/null +++ b/lib/PagePublisherDetail.php @@ -0,0 +1,18 @@ + + */ + +class PagePublisherDetail extends Page +{ + public function InitializeContent() + { + $publisher = Publisher::getPublisherById($this->idGet); + $this->title = $publisher->name; + [$this->entryArray, $this->totalNumber] = Book::getBooksByPublisher($this->idGet, $this->n); + $this->idPage = $publisher->getEntryId(); + } +} diff --git a/lib/PageQueryResult.php b/lib/PageQueryResult.php new file mode 100644 index 000000000..27659e22a --- /dev/null +++ b/lib/PageQueryResult.php @@ -0,0 +1,186 @@ + + */ + +class PageQueryResult extends Page +{ + public const SCOPE_TAG = "tag"; + public const SCOPE_RATING = "rating"; + public const SCOPE_SERIES = "series"; + public const SCOPE_AUTHOR = "author"; + public const SCOPE_BOOK = "book"; + public const SCOPE_PUBLISHER = "publisher"; + + private function useTypeahead() + { + return !is_null(getURLParam("search")); + } + + private function searchByScope($scope, $limit = false) + { + $n = $this->n; + $numberPerPage = null; + $queryNormedAndUp = trim($this->query); + if (useNormAndUp()) { + $queryNormedAndUp = normAndUp($this->query); + } + if ($limit) { + $n = 1; + $numberPerPage = 5; + } + switch ($scope) { + case self::SCOPE_BOOK : + $array = Book::getBooksByStartingLetter('%' . $queryNormedAndUp, $n, null, $numberPerPage); + break; + case self::SCOPE_AUTHOR : + $array = Author::getAuthorsForSearch('%' . $queryNormedAndUp); + break; + case self::SCOPE_SERIES : + $array = Serie::getAllSeriesByQuery($queryNormedAndUp); + break; + case self::SCOPE_TAG : + $array = Tag::getAllTagsByQuery($queryNormedAndUp, $n, null, $numberPerPage); + break; + case self::SCOPE_PUBLISHER : + $array = Publisher::getAllPublishersByQuery($queryNormedAndUp); + break; + default: + $array = Book::getBooksByQuery( + ["all" => "%" . $queryNormedAndUp . "%"], + $n + ); + } + + return $array; + } + + public function doSearchByCategory() + { + $database = GetUrlParam(DB); + $out = []; + $pagequery = Base::PAGE_OPENSEARCH_QUERY; + $dbArray = [""]; + $d = $database; + $query = $this->query; + // Special case when no databases were chosen, we search on all databases + if (Base::noDatabaseSelected()) { + $dbArray = Base::getDbNameList(); + $d = 0; + } + foreach ($dbArray as $key) { + if (Base::noDatabaseSelected()) { + array_push($this->entryArray, new Entry( + $key, + DB . ":query:{$d}", + " ", + "text", + [ new LinkNavigation("?" . DB . "={$d}")], + "tt-header" + )); + Base::getDb($d); + } + foreach ([PageQueryResult::SCOPE_BOOK, + PageQueryResult::SCOPE_AUTHOR, + PageQueryResult::SCOPE_SERIES, + PageQueryResult::SCOPE_TAG, + PageQueryResult::SCOPE_PUBLISHER] as $key) { + if (in_array($key, getCurrentOption('ignored_categories'))) { + continue; + } + $array = $this->searchByScope($key, true); + + $i = 0; + if (count($array) == 2 && is_array($array [0])) { + $total = $array [1]; + $array = $array [0]; + } else { + $total = count($array); + } + if ($total > 0) { + // Comment to help the perl i18n script + // str_format (localize("bookword", count($array)) + // str_format (localize("authorword", count($array)) + // str_format (localize("seriesword", count($array)) + // str_format (localize("tagword", count($array)) + // str_format (localize("publisherword", count($array)) + array_push($this->entryArray, new Entry( + str_format(localize("search.result.{$key}"), $this->query), + DB . ":query:{$d}:{$key}", + str_format(localize("{$key}word", $total), $total), + "text", + [ new LinkNavigation("?page={$pagequery}&query={$query}&db={$d}&scope={$key}")], + Base::noDatabaseSelected() ? "" : "tt-header", + $total + )); + } + if (!Base::noDatabaseSelected() && $this->useTypeahead()) { + foreach ($array as $entry) { + array_push($this->entryArray, $entry); + $i++; + if ($i > 4) { + break; + }; + } + } + } + $d++; + if (Base::noDatabaseSelected()) { + Base::clearDb(); + } + } + return $out; + } + + public function InitializeContent() + { + $scope = getURLParam("scope"); + if (empty($scope)) { + $this->title = str_format(localize("search.result"), $this->query); + } else { + // Comment to help the perl i18n script + // str_format (localize ("search.result.author"), $this->query) + // str_format (localize ("search.result.tag"), $this->query) + // str_format (localize ("search.result.series"), $this->query) + // str_format (localize ("search.result.book"), $this->query) + // str_format (localize ("search.result.publisher"), $this->query) + $this->title = str_format(localize("search.result.{$scope}"), $this->query); + } + + $crit = "%" . $this->query . "%"; + + // Special case when we are doing a search and no database is selected + if (Base::noDatabaseSelected() && !$this->useTypeahead()) { + $i = 0; + foreach (Base::getDbNameList() as $key) { + Base::clearDb(); + [$array, $totalNumber] = Book::getBooksByQuery(["all" => $crit], 1, $i, 1); + array_push($this->entryArray, new Entry( + $key, + DB . ":query:{$i}", + str_format(localize("bookword", $totalNumber), $totalNumber), + "text", + [ new LinkNavigation("?" . DB . "={$i}&page=9&query=" . $this->query)], + "", + $totalNumber + )); + $i++; + } + return; + } + if (empty($scope)) { + $this->doSearchByCategory(); + return; + } + + $array = $this->searchByScope($scope); + if (count($array) == 2 && is_array($array [0])) { + [$this->entryArray, $this->totalNumber] = $array; + } else { + $this->entryArray = $array; + } + } +} diff --git a/lib/PageRatingDetail.php b/lib/PageRatingDetail.php new file mode 100644 index 000000000..09ccdfce2 --- /dev/null +++ b/lib/PageRatingDetail.php @@ -0,0 +1,18 @@ + + */ + +class PageRatingDetail extends Page +{ + public function InitializeContent() + { + $rating = Rating::getRatingById($this->idGet); + $this->idPage = $rating->getEntryId(); + $this->title =str_format(localize("ratingword", $rating->name/2), $rating->name/2); + [$this->entryArray, $this->totalNumber] = Book::getBooksByRating($this->idGet, $this->n); + } +} diff --git a/lib/PageRecentBooks.php b/lib/PageRecentBooks.php new file mode 100644 index 000000000..6085ba827 --- /dev/null +++ b/lib/PageRecentBooks.php @@ -0,0 +1,17 @@ + + */ + +class PageRecentBooks extends Page +{ + public function InitializeContent() + { + $this->title = localize("recent.title"); + $this->entryArray = Book::getAllRecentBooks(); + $this->idPage = Book::ALL_RECENT_BOOKS_ID; + } +} diff --git a/lib/PageSerieDetail.php b/lib/PageSerieDetail.php new file mode 100644 index 000000000..f1e3d5391 --- /dev/null +++ b/lib/PageSerieDetail.php @@ -0,0 +1,18 @@ + + */ + +class PageSerieDetail extends Page +{ + public function InitializeContent() + { + $serie = Serie::getSerieById($this->idGet); + $this->title = $serie->name; + [$this->entryArray, $this->totalNumber] = Book::getBooksBySeries($this->idGet, $this->n); + $this->idPage = $serie->getEntryId(); + } +} diff --git a/lib/PageTagDetail.php b/lib/PageTagDetail.php new file mode 100644 index 000000000..f47b75981 --- /dev/null +++ b/lib/PageTagDetail.php @@ -0,0 +1,18 @@ + + */ + +class PageTagDetail extends Page +{ + public function InitializeContent() + { + $tag = Tag::getTagById($this->idGet); + $this->idPage = $tag->getEntryId(); + $this->title = $tag->name; + [$this->entryArray, $this->totalNumber] = Book::getBooksByTag($this->idGet, $this->n); + } +} diff --git a/lib/Publisher.php b/lib/Publisher.php new file mode 100644 index 000000000..cf81fdda0 --- /dev/null +++ b/lib/Publisher.php @@ -0,0 +1,74 @@ + + */ + +class Publisher extends Base +{ + public const ALL_PUBLISHERS_ID = "cops:publishers"; + public const PUBLISHERS_COLUMNS = "publishers.id as id, publishers.name as name, count(*) as count"; + public const SQL_ALL_PUBLISHERS = "select {0} from publishers, books_publishers_link where publishers.id = publisher group by publishers.id, publishers.name order by publishers.name"; + public const SQL_PUBLISHERS_FOR_SEARCH = "select {0} from publishers, books_publishers_link where publishers.id = publisher and upper (publishers.name) like ? group by publishers.id, publishers.name order by publishers.name"; + + + public $id; + public $name; + + public function __construct($post) + { + $this->id = $post->id; + $this->name = $post->name; + } + + public function getUri() + { + return "?page=".parent::PAGE_PUBLISHER_DETAIL."&id=$this->id"; + } + + public function getEntryId() + { + return self::ALL_PUBLISHERS_ID.":".$this->id; + } + + public static function getCount() + { + // str_format (localize("publishers.alphabetical", count(array)) + return parent::getCountGeneric("publishers", self::ALL_PUBLISHERS_ID, parent::PAGE_ALL_PUBLISHERS); + } + + public static function getPublisherByBookId($bookId) + { + $result = parent::getDb()->prepare('select publishers.id as id, name +from books_publishers_link, publishers +where publishers.id = publisher and book = ?'); + $result->execute([$bookId]); + if ($post = $result->fetchObject()) { + return new Publisher($post); + } + return null; + } + + public static function getPublisherById($publisherId) + { + $result = parent::getDb()->prepare('select id, name +from publishers where id = ?'); + $result->execute([$publisherId]); + if ($post = $result->fetchObject()) { + return new Publisher($post); + } + return null; + } + + public static function getAllPublishers() + { + return Base::getEntryArrayWithBookNumber(self::SQL_ALL_PUBLISHERS, self::PUBLISHERS_COLUMNS, [], "Publisher"); + } + + public static function getAllPublishersByQuery($query) + { + return Base::getEntryArrayWithBookNumber(self::SQL_PUBLISHERS_FOR_SEARCH, self::PUBLISHERS_COLUMNS, ['%' . $query . '%'], "Publisher"); + } +} diff --git a/lib/Rating.php b/lib/Rating.php new file mode 100644 index 000000000..6363f9aa3 --- /dev/null +++ b/lib/Rating.php @@ -0,0 +1,72 @@ +id = $pid; + $this->name = $pname; + } + + public function getUri() + { + return "?page=".parent::PAGE_RATING_DETAIL."&id=$this->id"; + } + + public function getEntryId() + { + return self::ALL_RATING_ID.":".$this->id; + } + + public static function getCount() + { + // str_format (localize("ratings", count(array)) + return parent::getCountGeneric("ratings", self::ALL_RATING_ID, parent::PAGE_ALL_RATINGS, "ratings"); + } + + public static function getAllRatings() + { + return self::getEntryArray(self::SQL_ALL_RATINGS, []); + } + + public static function getEntryArray($query, $params) + { + [, $result] = parent::executeQuery($query, self::RATING_COLUMNS, "", $params, -1); + $entryArray = []; + while ($post = $result->fetchObject()) { + $ratingObj = new Rating($post->id, $post->rating); + $rating=$post->rating/2; + $rating = str_format(localize("ratingword", $rating), $rating); + array_push($entryArray, new Entry( + $rating, + $ratingObj->getEntryId(), + str_format(localize("bookword", $post->count), $post->count), + "text", + [ new LinkNavigation($ratingObj->getUri())], + "", + $post->count + )); + } + return $entryArray; + } + + public static function getRatingById($ratingId) + { + $result = parent::getDb()->prepare('select rating from ratings where id = ?'); + $result->execute([$ratingId]); + return new Rating($ratingId, $result->fetchColumn()); + } +} diff --git a/lib/SQLQueries.php b/lib/SQLQueries.php new file mode 100644 index 000000000..51e2556f5 --- /dev/null +++ b/lib/SQLQueries.php @@ -0,0 +1,29 @@ + + */ + +class Serie extends Base +{ + public const ALL_SERIES_ID = "cops:series"; + public const SERIES_COLUMNS = "series.id as id, series.name as name, series.sort as sort, count(*) as count"; + public const SQL_ALL_SERIES = "select {0} from series, books_series_link where series.id = series group by series.id, series.name, series.sort order by series.sort"; + public const SQL_SERIES_FOR_SEARCH = "select {0} from series, books_series_link where series.id = series and upper (series.name) like ? group by series.id, series.name, series.sort order by series.sort"; + + public $id; + public $name; + + public function __construct($post) + { + $this->id = $post->id; + $this->name = $post->name; + } + + public function getUri() + { + return "?page=".parent::PAGE_SERIE_DETAIL."&id=$this->id"; + } + + public function getEntryId() + { + return self::ALL_SERIES_ID.":".$this->id; + } + + public static function getCount() + { + // str_format (localize("series.alphabetical", count(array)) + return parent::getCountGeneric("series", self::ALL_SERIES_ID, parent::PAGE_ALL_SERIES); + } + + public static function getSerieByBookId($bookId) + { + $result = parent::getDb()->prepare('select series.id as id, name +from books_series_link, series +where series.id = series and book = ?'); + $result->execute([$bookId]); + if ($post = $result->fetchObject()) { + return new Serie($post); + } + return null; + } + + public static function getSerieById($serieId) + { + $result = parent::getDb()->prepare('select id, name from series where id = ?'); + $result->execute([$serieId]); + if ($post = $result->fetchObject()) { + return new Serie($post); + } + return null; + } + + public static function getAllSeries() + { + return Base::getEntryArrayWithBookNumber(self::SQL_ALL_SERIES, self::SERIES_COLUMNS, [], "Serie"); + } + + public static function getAllSeriesByQuery($query) + { + return Base::getEntryArrayWithBookNumber(self::SQL_SERIES_FOR_SEARCH, self::SERIES_COLUMNS, ['%' . $query . '%'], "Serie"); + } +} diff --git a/lib/Tag.php b/lib/Tag.php new file mode 100644 index 000000000..d01580d15 --- /dev/null +++ b/lib/Tag.php @@ -0,0 +1,81 @@ + + */ + +class Tag extends Base +{ + public const ALL_TAGS_ID = "cops:tags"; + public const TAG_COLUMNS = "tags.id as id, tags.name as name, count(*) as count"; + public const SQL_ALL_TAGS = "select {0} from tags, books_tags_link where tags.id = tag group by tags.id, tags.name order by tags.name"; + + public $id; + public $name; + + public function __construct($post) + { + $this->id = $post->id; + $this->name = $post->name; + } + + public function getUri() + { + return "?page=".parent::PAGE_TAG_DETAIL."&id=$this->id"; + } + + public function getEntryId() + { + return self::ALL_TAGS_ID.":".$this->id; + } + + public static function getCount() + { + // str_format (localize("tags.alphabetical", count(array)) + return parent::getCountGeneric("tags", self::ALL_TAGS_ID, parent::PAGE_ALL_TAGS); + } + + public static function getTagById($tagId) + { + $result = parent::getDb()->prepare('select id, name from tags where id = ?'); + $result->execute([$tagId]); + if ($post = $result->fetchObject()) { + return new Tag($post); + } + return null; + } + + public static function getAllTags() + { + global $config; + + $sql = self::SQL_ALL_TAGS; + $sortField = $config['calibre_database_field_sort'] ?? ''; + if (!empty($sortField)) { + $sql = str_replace('tags.name', 'tags.' . $sortField, $sql); + } + + return Base::getEntryArrayWithBookNumber($sql, self::TAG_COLUMNS, [], "Tag"); + } + + public static function getAllTagsByQuery($query, $n, $database = null, $numberPerPage = null) + { + $columns = "tags.id as id, tags.name as name, (select count(*) from books_tags_link where tags.id = tag) as count"; + $sql = 'select {0} from tags where upper (tags.name) like ? {1} order by tags.name'; + [$totalNumber, $result] = parent::executeQuery($sql, $columns, "", ['%' . $query . '%'], $n, $database, $numberPerPage); + $entryArray = []; + while ($post = $result->fetchObject()) { + $tag = new Tag($post); + array_push($entryArray, new Entry( + $tag->name, + $tag->getEntryId(), + str_format(localize("bookword", $post->count), $post->count), + "text", + [ new LinkNavigation($tag->getUri())] + )); + } + return [$entryArray, $totalNumber]; + } +} diff --git a/login.html b/login.html new file mode 100644 index 000000000..9a8c64073 --- /dev/null +++ b/login.html @@ -0,0 +1,97 @@ + + + + + + COPS + + + + + +
    +
    + + + +
    +
    + + diff --git a/package.json b/package.json new file mode 100644 index 000000000..d4d93673e --- /dev/null +++ b/package.json @@ -0,0 +1,12 @@ +{ + "name": "seblucas-cops", + "packageManager": "yarn@3.5.0", + "dependencies": { + "dot": "^1.1.3", + "jquery": "^1.12.4", + "js-cookie": "^2.2.1", + "lru-fast": "^0.2.2", + "magnific-popup": "^1.1.0", + "normalize.css": "^8.0.1" + } +} diff --git a/php-epub-meta/LICENSE b/php-epub-meta/LICENSE deleted file mode 100644 index 128bf1f66..000000000 --- a/php-epub-meta/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2012 Andreas Gohr - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/php-epub-meta/epub.php b/php-epub-meta/epub.php deleted file mode 100644 index f6cf71f23..000000000 --- a/php-epub-meta/epub.php +++ /dev/null @@ -1,664 +0,0 @@ - - */ - -require_once('tbszip.php'); - -define ("METADATA_FILE", "META-INF/container.xml"); - -class EPub { - public $xml; //FIXME change to protected, later - protected $xpath; - protected $file; - protected $meta; - protected $zip; - protected $coverpath=''; - protected $namespaces; - protected $imagetoadd=''; - - /** - * Constructor - * - * @param string $file path to epub file to work on - * @throws Exception if metadata could not be loaded - */ - public function __construct($file){ - // open file - $this->file = $file; - $this->zip = new clsTbsZip(); - if(!$this->zip->Open($this->file)){ - throw new Exception('Failed to read epub file'); - } - - // read container data - if (!$this->zip->FileExists(METADATA_FILE)) { - throw new Exception ("Unable to find metadata.xml"); - } - - $data = $this->zip->FileRead(METADATA_FILE); - if($data == false){ - throw new Exception('Failed to access epub container data'); - } - $xml = new DOMDocument(); - $xml->registerNodeClass('DOMElement','EPubDOMElement'); - $xml->loadXML($data); - $xpath = new EPubDOMXPath($xml); - $nodes = $xpath->query('//n:rootfiles/n:rootfile[@media-type="application/oebps-package+xml"]'); - $this->meta = $nodes->item(0)->attr('full-path'); - - // load metadata - if (!$this->zip->FileExists($this->meta)) { - throw new Exception ("Unable to find " . $this->meta); - } - - $data = $this->zip->FileRead($this->meta); - if(!$data){ - throw new Exception('Failed to access epub metadata'); - } - $this->xml = new DOMDocument(); - $this->xml->registerNodeClass('DOMElement','EPubDOMElement'); - $this->xml->loadXML($data); - $this->xml->formatOutput = true; - $this->xpath = new EPubDOMXPath($this->xml); - } - - /** - * file name getter - */ - public function file(){ - return $this->file; - } - - /** - * Close the epub file - */ - public function close (){ - $this->zip->FileCancelModif($this->meta); - // TODO : Add cancelation of cover image - $this->zip->Close (); - } - - /** - * Writes back all meta data changes - * TODO update - */ - public function save(){ - $this->download (); - $zip->close(); - } - - /** - * Get the updated epub - */ - public function download($file=false){ - $this->zip->FileReplace($this->meta,$this->xml->saveXML()); - // add the cover image - if($this->imagetoadd){ - $this->zip->FileReplace($this->coverpath,file_get_contents($this->imagetoadd)); - $this->imagetoadd=''; - } - if ($file) $this->zip->Flush(TBSZIP_DOWNLOAD, $file); - } - - - - /** - * Get or set the book author(s) - * - * Authors should be given with a "file-as" and a real name. The file as - * is used for sorting in e-readers. - * - * Example: - * - * array( - * 'Pratchett, Terry' => 'Terry Pratchett', - * 'Simpson, Jacqeline' => 'Jacqueline Simpson', - * ) - * - * @params array $authors - */ - public function Authors($authors=false){ - // set new data - if($authors !== false){ - // Author where given as a comma separated list - if(is_string($authors)){ - if($authors == ''){ - $authors = array(); - }else{ - $authors = explode(',',$authors); - $authors = array_map('trim',$authors); - } - } - - // delete existing nodes - $nodes = $this->xpath->query('//opf:metadata/dc:creator[@opf:role="aut"]'); - foreach($nodes as $node) $node->delete(); - - // add new nodes - $parent = $this->xpath->query('//opf:metadata')->item(0); - foreach($authors as $as => $name){ - if(is_int($as)) $as = $name; //numeric array given - $node = $parent->newChild('dc:creator',$name); - $node->attr('opf:role', 'aut'); - $node->attr('opf:file-as', $as); - } - - $this->reparse(); - } - - // read current data - $rolefix = false; - $authors = array(); - $nodes = $this->xpath->query('//opf:metadata/dc:creator[@opf:role="aut"]'); - if($nodes->length == 0){ - // no nodes where found, let's try again without role - $nodes = $this->xpath->query('//opf:metadata/dc:creator'); - $rolefix = true; - } - foreach($nodes as $node){ - $name = $node->nodeValue; - $as = $node->attr('opf:file-as'); - if(!$as){ - $as = $name; - $node->attr('opf:file-as',$as); - } - if($rolefix){ - $node->attr('opf:role','aut'); - } - $authors[$as] = $name; - } - return $authors; - } - - /** - * Set or get the book title - * - * @param string $title - */ - public function Title($title=false){ - return $this->getset('dc:title',$title); - } - - /** - * Set or get the book's language - * - * @param string $lang - */ - public function Language($lang=false){ - return $this->getset('dc:language',$lang); - } - - /** - * Set or get the book' publisher info - * - * @param string $publisher - */ - public function Publisher($publisher=false){ - return $this->getset('dc:publisher',$publisher); - } - - /** - * Set or get the book's copyright info - * - * @param string $rights - */ - public function Copyright($rights=false){ - return $this->getset('dc:rights',$rights); - } - - /** - * Set or get the book's description - * - * @param string $description - */ - public function Description($description=false){ - return $this->getset('dc:description',$description); - } - - /** - * Set or get the book's ISBN number - * - * @param string $isbn - */ - public function ISBN($isbn=false){ - return $this->getset('dc:identifier',$isbn,'opf:scheme','ISBN'); - } - - /** - * Set or get the Google Books ID - * - * @param string $google - */ - public function Google($google=false){ - return $this->getset('dc:identifier',$google,'opf:scheme','GOOGLE'); - } - - /** - * Set or get the Amazon ID of the book - * - * @param string $amazon - */ - public function Amazon($amazon=false){ - return $this->getset('dc:identifier',$amazon,'opf:scheme','AMAZON'); - } - - /** - * Set or get the Calibre UUID of the book - * - * @param string $uuid - */ - public function Calibre($uuid=false){ - return $this->getset('dc:identifier',$uuid,'opf:scheme','calibre'); - } - - /** - * Set or get the Serie of the book - * - * @param string $serie - */ - public function Serie($serie=false){ - return $this->getset('opf:meta',$serie,'name','calibre:series','content'); - } - - /** - * Set or get the Serie Index of the book - * - * @param string $serieIndex - */ - public function SerieIndex($serieIndex=false){ - return $this->getset('opf:meta',$serieIndex,'name','calibre:series_index','content'); - } - - /** - * Set or get the book's subjects (aka. tags) - * - * Subject should be given as array, but a comma separated string will also - * be accepted. - * - * @param array $subjects - */ - public function Subjects($subjects=false){ - // setter - if($subjects !== false){ - if(is_string($subjects)){ - if($subjects === ''){ - $subjects = array(); - }else{ - $subjects = explode(',',$subjects); - $subjects = array_map('trim',$subjects); - } - } - - // delete previous - $nodes = $this->xpath->query('//opf:metadata/dc:subject'); - foreach($nodes as $node){ - $node->delete(); - } - // add new ones - $parent = $this->xpath->query('//opf:metadata')->item(0); - foreach($subjects as $subj){ - $node = $this->xml->createElement('dc:subject',htmlspecialchars($subj)); - $node = $parent->appendChild($node); - } - - $this->reparse(); - } - - //getter - $subjects = array(); - $nodes = $this->xpath->query('//opf:metadata/dc:subject'); - foreach($nodes as $node){ - $subjects[] = $node->nodeValue; - } - return $subjects; - } - - /** - * Read the cover data - * - * Returns an associative array with the following keys: - * - * mime - filetype (usually image/jpeg) - * data - the binary image data - * found - the internal path, or false if no image is set in epub - * - * When no image is set in the epub file, the binary data for a transparent - * GIF pixel is returned. - * - * When adding a new image this function return no or old data because the - * image contents are not in the epub file, yet. The image will be added when - * the save() method is called. - * - * @param string $path local filesystem path to a new cover image - * @param string $mime mime type of the given file - * @return array - */ - public function Cover($path=false, $mime=false){ - // set cover - if($path !== false){ - // remove current pointer - $nodes = $this->xpath->query('//opf:metadata/opf:meta[@name="cover"]'); - foreach($nodes as $node) $node->delete(); - // remove previous manifest entries if they where made by us - $nodes = $this->xpath->query('//opf:manifest/opf:item[@id="php-epub-meta-cover"]'); - foreach($nodes as $node) $node->delete(); - - if($path){ - // add pointer - $parent = $this->xpath->query('//opf:metadata')->item(0); - $node = $parent->newChild('opf:meta'); - $node->attr('opf:name','cover'); - $node->attr('opf:content','php-epub-meta-cover'); - - // add manifest - $parent = $this->xpath->query('//opf:manifest')->item(0); - $node = $parent->newChild('opf:item'); - $node->attr('id','php-epub-meta-cover'); - $node->attr('opf:href','php-epub-meta-cover.img'); - $node->attr('opf:media-type',$mime); - - // remember path for save action - $this->imagetoadd = $path; - } - - $this->reparse(); - } - - // load cover - $nodes = $this->xpath->query('//opf:metadata/opf:meta[@name="cover"]'); - if(!$nodes->length) return $this->no_cover(); - $coverid = (String) $nodes->item(0)->attr('opf:content'); - if(!$coverid) return $this->no_cover(); - - $nodes = $this->xpath->query('//opf:manifest/opf:item[@id="'.$coverid.'"]'); - if(!$nodes->length) return $this->no_cover(); - $mime = $nodes->item(0)->attr('opf:media-type'); - $path = $nodes->item(0)->attr('opf:href'); - $path = dirname('/'.$this->meta).'/'.$path; // image path is relative to meta file - $path = ltrim($path,'/'); - - $zip = new ZipArchive(); - if(!@$zip->open($this->file)){ - throw new Exception('Failed to read epub file'); - } - $data = $zip->getFromName($path); - - return array( - 'mime' => $mime, - 'data' => $data, - 'found' => $path - ); - } - - public function getCoverItem () { - $nodes = $this->xpath->query('//opf:metadata/opf:meta[@name="cover"]'); - if(!$nodes->length) return NULL; - - $coverid = (String) $nodes->item(0)->attr('opf:content'); - if(!$coverid) return NULL; - - $nodes = $this->xpath->query('//opf:manifest/opf:item[@id="'.$coverid.'"]'); - if(!$nodes->length) return NULL; - - return $nodes->item(0); - } - - public function updateForKepub () { - $item = $this->getCoverItem (); - if (!is_null ($item)) { - $item->attr('opf:properties', 'cover-image'); - } - } - - - public function Cover2($path=false, $mime=false){ - $hascover = true; - $item = $this->getCoverItem (); - if (is_null ($item)) { - $hascover = false; - } else { - $mime = $item->attr('opf:media-type'); - $this->coverpath = $item->attr('opf:href'); - $this->coverpath = dirname('/'.$this->meta).'/'.$this->coverpath; // image path is relative to meta file - $this->coverpath = ltrim($this->coverpath,'/'); - } - - // set cover - if($path !== false){ - if (!$hascover) return; // TODO For now only update - - if($path){ - $item->attr('opf:media-type',$mime); - - // remember path for save action - $this->imagetoadd = $path; - } - - $this->reparse(); - } - - if (!$hascover) return $this->no_cover(); - - $zip = new ZipArchive(); - if(!@$zip->open($this->file)){ - throw new Exception('Failed to read epub file'); - } - $data = $zip->getFromName($this->coverpath); - - return array( - 'mime' => $mime, - 'data' => $data, - 'found' => $this->coverpath - ); - } - - /** - * A simple getter/setter for simple meta attributes - * - * It should only be used for attributes that are expected to be unique - * - * @param string $item XML node to set/get - * @param string $value New node value - * @param string $att Attribute name - * @param string $aval Attribute value - * @param string $datt Destination attribute - */ - protected function getset($item,$value=false,$att=false,$aval=false,$datt=false){ - // construct xpath - $xpath = '//opf:metadata/'.$item; - if($att){ - $xpath .= "[@$att=\"$aval\"]"; - } - - // set value - if($value !== false){ - $value = htmlspecialchars($value); - $nodes = $this->xpath->query($xpath); - if($nodes->length == 1 ){ - if($value === ''){ - // the user want's to empty this value -> delete the node - $nodes->item(0)->delete(); - }else{ - // replace value - if ($datt){ - $nodes->item(0)->attr ($datt, $value); - }else{ - $nodes->item(0)->nodeValue = $value; - } - } - }else{ - // if there are multiple matching nodes for some reason delete - // them. we'll replace them all with our own single one - foreach($nodes as $n) $n->delete(); - // readd them - if($value){ - $parent = $this->xpath->query('//opf:metadata')->item(0); - - $node = $parent->newChild ($item); - if($att) $node->attr($att,$aval); - if ($datt){ - $node->attr ($datt, $value); - }else{ - $node->nodeValue = $value; - } - } - } - - $this->reparse(); - } - - // get value - $nodes = $this->xpath->query($xpath); - if($nodes->length){ - if ($datt){ - return $nodes->item(0)->attr ($datt); - }else{ - return $nodes->item(0)->nodeValue; - } - }else{ - return ''; - } - } - - /** - * Return a not found response for Cover() - */ - protected function no_cover(){ - return array( - 'data' => base64_decode('R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAEALAAAAAABAAEAAAIBTAA7'), - 'mime' => 'image/gif', - 'found' => false - ); - } - - /** - * Reparse the DOM tree - * - * I had to rely on this because otherwise xpath failed to find the newly - * added nodes - */ - protected function reparse() { - $this->xml->loadXML($this->xml->saveXML()); - $this->xpath = new EPubDOMXPath($this->xml); - } -} - -class EPubDOMXPath extends DOMXPath { - public function __construct(DOMDocument $doc){ - parent::__construct($doc); - - if(is_a($doc->documentElement, 'EPubDOMElement')){ - foreach($doc->documentElement->namespaces as $ns => $url){ - $this->registerNamespace($ns,$url); - } - } - } -} - -class EPubDOMElement extends DOMElement { - public $namespaces = array( - 'n' => 'urn:oasis:names:tc:opendocument:xmlns:container', - 'opf' => 'http://www.idpf.org/2007/opf', - 'dc' => 'http://purl.org/dc/elements/1.1/' - ); - - - public function __construct($name, $value='', $namespaceURI=''){ - list($ns,$name) = $this->splitns($name); - $value = htmlspecialchars($value); - if(!$namespaceURI && $ns){ - $namespaceURI = $this->namespaces[$ns]; - } - parent::__construct($name, $value, $namespaceURI); - } - - - /** - * Create and append a new child - * - * Works with our epub namespaces and omits default namespaces - */ - public function newChild($name, $value=''){ - list($ns,$local) = $this->splitns($name); - if($ns){ - $nsuri = $this->namespaces[$ns]; - if($this->isDefaultNamespace($nsuri)){ - $name = $local; - $nsuri = ''; - } - } - - // this doesn't call the construcor: $node = $this->ownerDocument->createElement($name,$value); - $node = new EPubDOMElement($name,$value,$nsuri); - return $this->appendChild($node); - } - - /** - * Split given name in namespace prefix and local part - * - * @param string $name - * @return array (namespace, name) - */ - public function splitns($name){ - $list = explode(':',$name,2); - if(count($list) < 2) array_unshift($list,''); - return $list; - } - - /** - * Simple EPub namespace aware attribute accessor - */ - public function attr($attr,$value=null){ - list($ns,$attr) = $this->splitns($attr); - - $nsuri = ''; - if($ns){ - $nsuri = $this->namespaces[$ns]; - if(!$this->namespaceURI){ - if($this->isDefaultNamespace($nsuri)){ - $nsuri = ''; - } - }elseif($this->namespaceURI == $nsuri){ - $nsuri = ''; - } - } - - if(!is_null($value)){ - if($value === false){ - // delete if false was given - if($nsuri){ - $this->removeAttributeNS($nsuri,$attr); - }else{ - $this->removeAttribute($attr); - } - }else{ - // modify if value was given - if($nsuri){ - $this->setAttributeNS($nsuri,$attr,$value); - }else{ - $this->setAttribute($attr,$value); - } - } - }else{ - // return value if none was given - if($nsuri){ - return $this->getAttributeNS($nsuri,$attr); - }else{ - return $this->getAttribute($attr); - } - } - } - - /** - * Remove this node from the DOM - */ - public function delete(){ - $this->parentNode->removeChild($this); - } - -} - - diff --git a/php-epub-meta/tbszip.php b/php-epub-meta/tbszip.php deleted file mode 100644 index ba1214de9..000000000 --- a/php-epub-meta/tbszip.php +++ /dev/null @@ -1,883 +0,0 @@ -Meth8Ok = extension_loaded('zlib'); // check if Zlib extension is available. This is need for compress and uncompress with method 8. - $this->DisplayError = true; - $this->ArchFile = ''; - $this->Error = false; - } - - function CreateNew($ArchName='new.zip') { - // Create a new virtual empty archive, the name will be the default name when the archive is flushed. - if (!isset($this->Meth8Ok)) $this->__construct(); // for PHP 4 compatibility - $this->Close(); // note that $this->ArchHnd is set to false here - $this->Error = false; - $this->ArchFile = $ArchName; - $this->ArchIsNew = true; - $bin = 'PK'.chr(05).chr(06).str_repeat(chr(0), 18); - $this->CdEndPos = strlen($bin) - 4; - $this->CdInfo = array('disk_num_curr'=>0, 'disk_num_cd'=>0, 'file_nbr_curr'=>0, 'file_nbr_tot'=>0, 'l_cd'=>0, 'p_cd'=>0, 'l_comm'=>0, 'v_comm'=>'', 'bin'=>$bin); - $this->CdPos = $this->CdInfo['p_cd']; - } - - function Open($ArchFile) { - // Open the zip archive - if (!isset($this->Meth8Ok)) $this->__construct(); // for PHP 4 compatibility - $this->Close(); // close handle and init info - $this->Error = false; - $this->ArchFile = $ArchFile; - $this->ArchIsNew = false; - // open the file - $this->ArchHnd = fopen($ArchFile, 'rb'); - $ok = !($this->ArchHnd===false); - if ($ok) $ok = $this->CentralDirRead(); - return $ok; - } - - function Close() { - if (isset($this->ArchHnd) and ($this->ArchHnd!==false)) fclose($this->ArchHnd); - $this->ArchFile = ''; - $this->ArchHnd = false; - $this->CdInfo = array(); - $this->CdFileLst = array(); - $this->CdFileNbr = 0; - $this->CdFileByName = array(); - $this->VisFileLst = array(); - $this->ArchCancelModif(); - } - - function ArchCancelModif() { - $this->LastReadComp = false; // compression of the last read file (1=compressed, 0=stored not compressed, -1= stored compressed but read uncompressed) - $this->LastReadIdx = false; // index of the last file read - $this->ReplInfo = array(); - $this->ReplByPos = array(); - $this->AddInfo = array(); - } - - function FileAdd($Name, $Data, $DataType=TBSZIP_STRING, $Compress=true) { - - if ($Data===false) return $this->FileCancelModif($Name, false); // Cancel a previously added file - - // Save information for adding a new file into the archive - $Diff = 30 + 46 + 2*strlen($Name); // size of the header + cd info - $Ref = $this->_DataCreateNewRef($Data, $DataType, $Compress, $Diff, $Name); - if ($Ref===false) return false; - $Ref['name'] = $Name; - $this->AddInfo[] = $Ref; - return $Ref['res']; - - } - - function CentralDirRead() { - $cd_info = 'PK'.chr(05).chr(06); // signature of the Central Directory - $cd_pos = -22; - $this->_MoveTo($cd_pos, SEEK_END); - $b = $this->_ReadData(4); - if ($b!==$cd_info) return $this->RaiseError('The footer of the Central Directory is not found.'); - - $this->CdEndPos = ftell($this->ArchHnd) - 4; - $this->CdInfo = $this->CentralDirRead_End($cd_info); - $this->CdFileLst = array(); - $this->CdFileNbr = $this->CdInfo['file_nbr_curr']; - $this->CdPos = $this->CdInfo['p_cd']; - - if ($this->CdFileNbr<=0) return $this->RaiseError('No file found in the Central Directory.'); - if ($this->CdPos<=0) return $this->RaiseError('No position found for the Central Directory listing.'); - - $this->_MoveTo($this->CdPos); - for ($i=0;$i<$this->CdFileNbr;$i++) { - $x = $this->CentralDirRead_File($i); - if ($x!==false) { - $this->CdFileLst[$i] = $x; - $this->CdFileByName[$x['v_name']] = $i; - } - } - return true; - } - - function CentralDirRead_End($cd_info) { - $b = $cd_info.$this->_ReadData(18); - $x = array(); - $x['disk_num_curr'] = $this->_GetDec($b,4,2); // number of this disk - $x['disk_num_cd'] = $this->_GetDec($b,6,2); // number of the disk with the start of the central directory - $x['file_nbr_curr'] = $this->_GetDec($b,8,2); // total number of entries in the central directory on this disk - $x['file_nbr_tot'] = $this->_GetDec($b,10,2); // total number of entries in the central directory - $x['l_cd'] = $this->_GetDec($b,12,4); // size of the central directory - $x['p_cd'] = $this->_GetDec($b,16,4); // offset of start of central directory with respect to the starting disk number - $x['l_comm'] = $this->_GetDec($b,20,2); // .ZIP file comment length - $x['v_comm'] = $this->_ReadData($x['l_comm']); // .ZIP file comment - $x['bin'] = $b.$x['v_comm']; - return $x; - } - - function CentralDirRead_File($idx) { - - $b = $this->_ReadData(46); - - $x = $this->_GetHex($b,0,4); - if ($x!=='h:02014b50') return $this->RaiseError('Signature of file information not found in the Central Directory in position '.(ftell($this->ArchHnd)-46).' for file #'.$idx.'.'); - - $x = array(); - $x['vers_used'] = $this->_GetDec($b,4,2); - $x['vers_necess'] = $this->_GetDec($b,6,2); - $x['purp'] = $this->_GetBin($b,8,2); - $x['meth'] = $this->_GetDec($b,10,2); - $x['time'] = $this->_GetDec($b,12,2); - $x['date'] = $this->_GetDec($b,14,2); - $x['crc32'] = $this->_GetDec($b,16,4); - $x['l_data_c'] = $this->_GetDec($b,20,4); - $x['l_data_u'] = $this->_GetDec($b,24,4); - $x['l_name'] = $this->_GetDec($b,28,2); - $x['l_fields'] = $this->_GetDec($b,30,2); - $x['l_comm'] = $this->_GetDec($b,32,2); - $x['disk_num'] = $this->_GetDec($b,34,2); - $x['int_file_att'] = $this->_GetDec($b,36,2); - $x['ext_file_att'] = $this->_GetDec($b,38,4); - $x['p_loc'] = $this->_GetDec($b,42,4); - $x['v_name'] = $this->_ReadData($x['l_name']); - $x['v_fields'] = $this->_ReadData($x['l_fields']); - $x['v_comm'] = $this->_ReadData($x['l_comm']); - - $x['bin'] = $b.$x['v_name'].$x['v_fields'].$x['v_comm']; - - return $x; - } - - function RaiseError($Msg) { - if ($this->DisplayError) echo ''.get_class($this).' ERROR : '.$Msg.'
    '."\r\n"; - $this->Error = $Msg; - return false; - } - - function Debug($FileHeaders=false) { - - $this->DisplayError = true; - - echo "
    \r\n"; - echo "------------------
    \r\n"; - echo "Central Directory:
    \r\n"; - echo "------------------
    \r\n"; - print_r($this->CdInfo); - - echo "
    \r\n"; - echo "-----------------------------------
    \r\n"; - echo "File List in the Central Directory:
    \r\n"; - echo "-----------------------------------
    \r\n"; - print_r($this->CdFileLst); - - if ($FileHeaders) { - echo "
    \r\n"; - echo "------------------------------
    \r\n"; - echo "File List in the Data Section:
    \r\n"; - echo "------------------------------
    \r\n"; - $idx = 0; - $pos = 0; - $this->_MoveTo($pos); - while ($ok = $this->_ReadFile($idx,false)) { - $this->VisFileLst[$idx]['debug_pos'] = $pos; - $pos = ftell($this->ArchHnd); - $idx++; - } - print_r($this->VisFileLst); - } - - } - - function FileExists($NameOrIdx) { - return ($this->FileGetIdx($NameOrIdx)!==false); - } - - function FileGetIdx($NameOrIdx) { - // Check if a file name, or a file index exists in the Central Directory, and return its index - if (is_string($NameOrIdx)) { - if (isset($this->CdFileByName[$NameOrIdx])) { - return $this->CdFileByName[$NameOrIdx]; - } else { - return false; - } - } else { - if (isset($this->CdFileLst[$NameOrIdx])) { - return $NameOrIdx; - } else { - return false; - } - } - } - - function FileGetIdxAdd($Name) { - // Check if a file name exists in the list of file to add, and return its index - if (!is_string($Name)) return false; - $idx_lst = array_keys($this->AddInfo); - foreach ($idx_lst as $idx) { - if ($this->AddInfo[$idx]['name']===$Name) return $idx; - } - return false; - } - - function FileRead($NameOrIdx, $Uncompress=true) { - - $this->LastReadComp = false; // means the file is not found - $this->LastReadIdx = false; - - $idx = $this->FileGetIdx($NameOrIdx); - if ($idx===false) return $this->RaiseError('File "'.$NameOrIdx.'" is not found in the Central Directory.'); - - $pos = $this->CdFileLst[$idx]['p_loc']; - $this->_MoveTo($pos); - - $this->LastReadIdx = $idx; // Can be usefull to get the idx - - $Data = $this->_ReadFile($idx, true); - - // Manage uncompression - $Comp = 1; // means the contents stays compressed - $meth = $this->CdFileLst[$idx]['meth']; - if ($meth==8) { - if ($Uncompress) { - if ($this->Meth8Ok) { - $Data = gzinflate($Data); - $Comp = -1; // means uncompressed - } else { - $this->RaiseError('Unable to uncompress file "'.$NameOrIdx.'" because extension Zlib is not installed.'); - } - } - } elseif($meth==0) { - $Comp = 0; // means stored without compression - } else { - if ($Uncompress) $this->RaiseError('Unable to uncompress file "'.$NameOrIdx.'" because it is compressed with method '.$meth.'.'); - } - $this->LastReadComp = $Comp; - - return $Data; - - } - - function _ReadFile($idx, $ReadData) { - // read the file header (and maybe the data ) in the archive, assuming the cursor in at a new file position - - $b = $this->_ReadData(30); - - $x = $this->_GetHex($b,0,4); - if ($x!=='h:04034b50') return $this->RaiseError('Signature of file information not found in the Data Section in position '.(ftell($this->ArchHnd)-30).' for file #'.$idx.'.'); - - $x = array(); - $x['vers'] = $this->_GetDec($b,4,2); - $x['purp'] = $this->_GetBin($b,6,2); - $x['meth'] = $this->_GetDec($b,8,2); - $x['time'] = $this->_GetDec($b,10,2); - $x['date'] = $this->_GetDec($b,12,2); - $x['crc32'] = $this->_GetDec($b,14,4); - $x['l_data_c'] = $this->_GetDec($b,18,4); - $x['l_data_u'] = $this->_GetDec($b,22,4); - $x['l_name'] = $this->_GetDec($b,26,2); - $x['l_fields'] = $this->_GetDec($b,28,2); - $x['v_name'] = $this->_ReadData($x['l_name']); - $x['v_fields'] = $this->_ReadData($x['l_fields']); - - $x['bin'] = $b.$x['v_name'].$x['v_fields']; - - // Read Data - $len_cd = $this->CdFileLst[$idx]['l_data_c']; - if ($x['l_data_c']==0) { - // Sometimes, the size is not specified in the local information. - $len = $len_cd; - } else { - $len = $x['l_data_c']; - if ($len!=$len_cd) { - //echo "TbsZip Warning: Local information for file #".$idx." says len=".$len.", while Central Directory says len=".$len_cd."."; - } - } - - if ($ReadData) { - $Data = $this->_ReadData($len); - } else { - $this->_MoveTo($len, SEEK_CUR); - } - - // Description information - $desc_ok = ($x['purp'][2+3]=='1'); - if ($desc_ok) { - $b = $this->_ReadData(16); - $x['desc_bin'] = $b; - $x['desc_sign'] = $this->_GetHex($b,0,4); // not specified in the documentation sign=h:08074b50 - $x['desc_crc32'] = $this->_GetDec($b,4,4); - $x['desc_l_data_c'] = $this->_GetDec($b,8,4); - $x['desc_l_data_u'] = $this->_GetDec($b,12,4); - } - - // Save file info without the data - $this->VisFileLst[$idx] = $x; - - // Return the info - if ($ReadData) { - return $Data; - } else { - return true; - } - - } - - function FileReplace($NameOrIdx, $Data, $DataType=TBSZIP_STRING, $Compress=true) { - // Store replacement information. - - $idx = $this->FileGetIdx($NameOrIdx); - if ($idx===false) return $this->RaiseError('File "'.$NameOrIdx.'" is not found in the Central Directory.'); - - $pos = $this->CdFileLst[$idx]['p_loc']; - - if ($Data===false) { - // file to delete - $this->ReplInfo[$idx] = false; - $Result = true; - } else { - // file to replace - $Diff = - $this->CdFileLst[$idx]['l_data_c']; - $Ref = $this->_DataCreateNewRef($Data, $DataType, $Compress, $Diff, $NameOrIdx); - if ($Ref===false) return false; - $this->ReplInfo[$idx] = $Ref; - $Result = $Ref['res']; - } - - $this->ReplByPos[$pos] = $idx; - - return $Result; - - } - - function FileCancelModif($NameOrIdx, $ReplacedAndDeleted=true) { - // cancel added, modified or deleted modifications on a file in the archive - // return the number of cancels - - $nbr = 0; - - if ($ReplacedAndDeleted) { - // replaced or deleted files - $idx = $this->FileGetIdx($NameOrIdx); - if ($idx!==false) { - if (isset($this->ReplInfo[$idx])) { - $pos = $this->CdFileLst[$idx]['p_loc']; - unset($this->ReplByPos[$pos]); - unset($this->ReplInfo[$idx]); - $nbr++; - } - } - } - - // added files - $idx = $this->FileGetIdxAdd($NameOrIdx); - if ($idx!==false) { - unset($this->AddInfo[$idx]); - $nbr++; - } - - return $nbr; - - } - - function Flush($Render=TBSZIP_DOWNLOAD, $File='', $ContentType='') { - - if ( ($File!=='') && ($this->ArchFile===$File)) { - $this->RaiseError('Method Flush() cannot overwrite the current opened archive: \''.$File.'\''); // this makes corrupted zip archives without PHP error. - return false; - } - - $ArchPos = 0; - $Delta = 0; - $FicNewPos = array(); - $DelLst = array(); // idx of deleted files - $DeltaCdLen = 0; // delta of the CD's size - - $now = time(); - $date = $this->_MsDos_Date($now); - $time = $this->_MsDos_Time($now); - - if (!$this->OutputOpen($Render, $File, $ContentType)) return false; - - // output modified zipped files and unmodified zipped files that are beetween them - ksort($this->ReplByPos); - foreach ($this->ReplByPos as $ReplPos => $ReplIdx) { - // output data from the zip archive which is before the data to replace - $this->OutputFromArch($ArchPos, $ReplPos); - // get current file information - if (!isset($this->VisFileLst[$ReplIdx])) $this->_ReadFile($ReplIdx, false); - $FileInfo =& $this->VisFileLst[$ReplIdx]; - $b1 = $FileInfo['bin']; - if (isset($FileInfo['desc_bin'])) { - $b2 = $FileInfo['desc_bin']; - } else { - $b2 = ''; - } - $info_old_len = strlen($b1) + $this->CdFileLst[$ReplIdx]['l_data_c'] + strlen($b2); // $FileInfo['l_data_c'] may have a 0 value in some archives - // get replacement information - $ReplInfo =& $this->ReplInfo[$ReplIdx]; - if ($ReplInfo===false) { - // The file is to be deleted - $Delta = $Delta - $info_old_len; // headers and footers are also deleted - $DelLst[$ReplIdx] = true; - } else { - // prepare the header of the current file - $this->_DataPrepare($ReplInfo); // get data from external file if necessary - $this->_PutDec($b1, $time, 10, 2); // time - $this->_PutDec($b1, $date, 12, 2); // date - $this->_PutDec($b1, $ReplInfo['crc32'], 14, 4); // crc32 - $this->_PutDec($b1, $ReplInfo['len_c'], 18, 4); // l_data_c - $this->_PutDec($b1, $ReplInfo['len_u'], 22, 4); // l_data_u - if ($ReplInfo['meth']!==false) $this->_PutDec($b1, $ReplInfo['meth'], 8, 2); // meth - // prepare the bottom description if the zipped file, if any - if ($b2!=='') { - $this->_PutDec($b2, $ReplInfo['crc32'], 4, 4); // crc32 - $this->_PutDec($b2, $ReplInfo['len_c'], 8, 4); // l_data_c - $this->_PutDec($b2, $ReplInfo['len_u'], 12, 4); // l_data_u - } - // output data - $this->OutputFromString($b1.$ReplInfo['data'].$b2); - unset($ReplInfo['data']); // save PHP memory - $Delta = $Delta + $ReplInfo['diff'] + $ReplInfo['len_c']; - } - // Update the delta of positions for zipped files which are physically after the currently replaced one - for ($i=0;$i<$this->CdFileNbr;$i++) { - if ($this->CdFileLst[$i]['p_loc']>$ReplPos) { - $FicNewPos[$i] = $this->CdFileLst[$i]['p_loc'] + $Delta; - } - } - // Update the current pos in the archive - $ArchPos = $ReplPos + $info_old_len; - } - - // Ouput all the zipped files that remain before the Central Directory listing - if ($this->ArchHnd!==false) $this->OutputFromArch($ArchPos, $this->CdPos); // ArchHnd is false if CreateNew() has been called - $ArchPos = $this->CdPos; - - // Output file to add - $AddNbr = count($this->AddInfo); - $AddDataLen = 0; // total len of added data (inlcuding file headers) - if ($AddNbr>0) { - $AddPos = $ArchPos + $Delta; // position of the start - $AddLst = array_keys($this->AddInfo); - foreach ($AddLst as $idx) { - $n = $this->_DataOuputAddedFile($idx, $AddPos); - $AddPos += $n; - $AddDataLen += $n; - } - } - - // Modifiy file information in the Central Directory for replaced files - $b2 = ''; - $old_cd_len = 0; - for ($i=0;$i<$this->CdFileNbr;$i++) { - $b1 = $this->CdFileLst[$i]['bin']; - $old_cd_len += strlen($b1); - if (!isset($DelLst[$i])) { - if (isset($FicNewPos[$i])) $this->_PutDec($b1, $FicNewPos[$i], 42, 4); // p_loc - if (isset($this->ReplInfo[$i])) { - $ReplInfo =& $this->ReplInfo[$i]; - $this->_PutDec($b1, $time, 12, 2); // time - $this->_PutDec($b1, $date, 14, 2); // date - $this->_PutDec($b1, $ReplInfo['crc32'], 16, 4); // crc32 - $this->_PutDec($b1, $ReplInfo['len_c'], 20, 4); // l_data_c - $this->_PutDec($b1, $ReplInfo['len_u'], 24, 4); // l_data_u - if ($ReplInfo['meth']!==false) $this->_PutDec($b1, $ReplInfo['meth'], 10, 2); // meth - } - $b2 .= $b1; - } - } - $this->OutputFromString($b2); - $ArchPos += $old_cd_len; - $DeltaCdLen = $DeltaCdLen + strlen($b2) - $old_cd_len; - - // Output until Central Directory footer - if ($this->ArchHnd!==false) $this->OutputFromArch($ArchPos, $this->CdEndPos); // ArchHnd is false if CreateNew() has been called - - // Output file information of the Central Directory for added files - if ($AddNbr>0) { - $b2 = ''; - foreach ($AddLst as $idx) { - $b2 .= $this->AddInfo[$idx]['bin']; - } - $this->OutputFromString($b2); - $DeltaCdLen += strlen($b2); - } - - // Output Central Directory footer - $b2 = $this->CdInfo['bin']; - $DelNbr = count($DelLst); - if ( ($AddNbr>0) or ($DelNbr>0) ) { - // total number of entries in the central directory on this disk - $n = $this->_GetDec($b2, 8, 2); - $this->_PutDec($b2, $n + $AddNbr - $DelNbr, 8, 2); - // total number of entries in the central directory - $n = $this->_GetDec($b2, 10, 2); - $this->_PutDec($b2, $n + $AddNbr - $DelNbr, 10, 2); - // size of the central directory - $n = $this->_GetDec($b2, 12, 4); - $this->_PutDec($b2, $n + $DeltaCdLen, 12, 4); - $Delta = $Delta + $AddDataLen; - } - $this->_PutDec($b2, $this->CdPos+$Delta , 16, 4); // p_cd (offset of start of central directory with respect to the starting disk number) - $this->OutputFromString($b2); - - $this->OutputClose(); - - return true; - - } - - // ---------------- - // output functions - // ---------------- - - function OutputOpen($Render, $File, $ContentType) { - - if (($Render & TBSZIP_FILE)==TBSZIP_FILE) { - $this->OutputMode = TBSZIP_FILE; - if (''.$File=='') $File = basename($this->ArchFile).'.zip'; - $this->OutputHandle = @fopen($File, 'w'); - if ($this->OutputHandle===false) { - $this->RaiseError('Method Flush() cannot overwrite the target file \''.$File.'\'. This may not be a valid file path or the file may be locked by another process or because of a denied permission.'); - return false; - } - } elseif (($Render & TBSZIP_STRING)==TBSZIP_STRING) { - $this->OutputMode = TBSZIP_STRING; - $this->OutputSrc = ''; - } elseif (($Render & TBSZIP_DOWNLOAD)==TBSZIP_DOWNLOAD) { - $this->OutputMode = TBSZIP_DOWNLOAD; - // Output the file - if (''.$File=='') $File = basename($this->ArchFile); - if (($Render & TBSZIP_NOHEADER)==TBSZIP_NOHEADER) { - } else { - header ('Pragma: no-cache'); - if ($ContentType!='') header ('Content-Type: '.$ContentType); - header('Content-Disposition: attachment; filename="'.$File.'"'); - header('Expires: 0'); - header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); - header('Cache-Control: public'); - header('Content-Description: File Transfer'); - header('Content-Transfer-Encoding: binary'); - $Len = $this->_EstimateNewArchSize(); - if ($Len!==false) header('Content-Length: '.$Len); - } - } - - return true; - - } - - function OutputFromArch($pos, $pos_stop) { - $len = $pos_stop - $pos; - if ($len<0) return; - $this->_MoveTo($pos); - $block = 1024; - while ($len>0) { - $l = min($len, $block); - $x = $this->_ReadData($l); - $this->OutputFromString($x); - $len = $len - $l; - } - unset($x); - } - - function OutputFromString($data) { - if ($this->OutputMode===TBSZIP_DOWNLOAD) { - echo $data; // donwload - } elseif ($this->OutputMode===TBSZIP_STRING) { - $this->OutputSrc .= $data; // to string - } elseif (TBSZIP_FILE) { - fwrite($this->OutputHandle, $data); // to file - } - } - - function OutputClose() { - if ( ($this->OutputMode===TBSZIP_FILE) && ($this->OutputHandle!==false) ) { - fclose($this->OutputHandle); - $this->OutputHandle = false; - } - } - - // ---------------- - // Reading functions - // ---------------- - - function _MoveTo($pos, $relative = SEEK_SET) { - fseek($this->ArchHnd, $pos, $relative); - } - - function _ReadData($len) { - if ($len>0) { - $x = fread($this->ArchHnd, $len); - return $x; - } else { - return ''; - } - } - - // ---------------- - // Take info from binary data - // ---------------- - - function _GetDec($txt, $pos, $len) { - $x = substr($txt, $pos, $len); - $z = 0; - for ($i=0;$i<$len;$i++) { - $asc = ord($x[$i]); - if ($asc>0) $z = $z + $asc*pow(256,$i); - } - return $z; - } - - function _GetHex($txt, $pos, $len) { - $x = substr($txt, $pos, $len); - return 'h:'.bin2hex(strrev($x)); - } - - function _GetBin($txt, $pos, $len) { - $x = substr($txt, $pos, $len); - $z = ''; - for ($i=0;$i<$len;$i++) { - $asc = ord($x[$i]); - if (isset($x[$i])) { - for ($j=0;$j<8;$j++) { - $z .= ($asc & pow(2,$j)) ? '1' : '0'; - } - } else { - $z .= '00000000'; - } - } - return 'b:'.$z; - } - - // ---------------- - // Put info into binary data - // ---------------- - - function _PutDec(&$txt, $val, $pos, $len) { - $x = ''; - for ($i=0;$i<$len;$i++) { - if ($val==0) { - $z = 0; - } else { - $z = intval($val % 256); - if (($val<0) && ($z!=0)) { // ($z!=0) is very important, example: val=-420085702 - // special opration for negative value. If the number id too big, PHP stores it into a signed integer. For example: crc32('coucou') => -256185401 instead of 4038781895. NegVal = BigVal - (MaxVal+1) = BigVal - 256^4 - $val = ($val - $z)/256 -1; - $z = 256 + $z; - } else { - $val = ($val - $z)/256; - } - } - $x .= chr($z); - } - $txt = substr_replace($txt, $x, $pos, $len); - } - - function _MsDos_Date($Timestamp = false) { - // convert a date-time timstamp into the MS-Dos format - $d = ($Timestamp===false) ? getdate() : getdate($Timestamp); - return (($d['year']-1980)*512) + ($d['mon']*32) + $d['mday']; - } - function _MsDos_Time($Timestamp = false) { - // convert a date-time timstamp into the MS-Dos format - $d = ($Timestamp===false) ? getdate() : getdate($Timestamp); - return ($d['hours']*2048) + ($d['minutes']*32) + intval($d['seconds']/2); // seconds are rounded to an even number in order to save 1 bit - } - - function _MsDos_Debug($date, $time) { - // Display the formated date and time. Just for debug purpose. - // date end time are encoded on 16 bits (2 bytes) : date = yyyyyyymmmmddddd , time = hhhhhnnnnnssssss - $y = ($date & 65024)/512 + 1980; - $m = ($date & 480)/32; - $d = ($date & 31); - $h = ($time & 63488)/2048; - $i = ($time & 1984)/32; - $s = ($time & 31) * 2; // seconds have been rounded to an even number in order to save 1 bit - return $y.'-'.str_pad($m,2,'0',STR_PAD_LEFT).'-'.str_pad($d,2,'0',STR_PAD_LEFT).' '.str_pad($h,2,'0',STR_PAD_LEFT).':'.str_pad($i,2,'0',STR_PAD_LEFT).':'.str_pad($s,2,'0',STR_PAD_LEFT); - } - - function _DataOuputAddedFile($Idx, $PosLoc) { - - $Ref =& $this->AddInfo[$Idx]; - $this->_DataPrepare($Ref); // get data from external file if necessary - - // Other info - $now = time(); - $date = $this->_MsDos_Date($now); - $time = $this->_MsDos_Time($now); - $len_n = strlen($Ref['name']); - $purp = 2048 ; // purpose // +8 to indicates that there is an extended local header - - // Header for file in the data section - $b = 'PK'.chr(03).chr(04).str_repeat(' ',26); // signature - $this->_PutDec($b,20,4,2); //vers = 20 - $this->_PutDec($b,$purp,6,2); // purp - $this->_PutDec($b,$Ref['meth'],8,2); // meth - $this->_PutDec($b,$time,10,2); // time - $this->_PutDec($b,$date,12,2); // date - $this->_PutDec($b,$Ref['crc32'],14,4); // crc32 - $this->_PutDec($b,$Ref['len_c'],18,4); // l_data_c - $this->_PutDec($b,$Ref['len_u'],22,4); // l_data_u - $this->_PutDec($b,$len_n,26,2); // l_name - $this->_PutDec($b,0,28,2); // l_fields - $b .= $Ref['name']; // name - $b .= ''; // fields - - // Output the data - $this->OutputFromString($b.$Ref['data']); - $OutputLen = strlen($b) + $Ref['len_c']; // new position of the cursor - unset($Ref['data']); // save PHP memory - - // Information for file in the Central Directory - $b = 'PK'.chr(01).chr(02).str_repeat(' ',42); // signature - $this->_PutDec($b,20,4,2); // vers_used = 20 - $this->_PutDec($b,20,6,2); // vers_necess = 20 - $this->_PutDec($b,$purp,8,2); // purp - $this->_PutDec($b,$Ref['meth'],10,2); // meth - $this->_PutDec($b,$time,12,2); // time - $this->_PutDec($b,$date,14,2); // date - $this->_PutDec($b,$Ref['crc32'],16,4); // crc32 - $this->_PutDec($b,$Ref['len_c'],20,4); // l_data_c - $this->_PutDec($b,$Ref['len_u'],24,4); // l_data_u - $this->_PutDec($b,$len_n,28,2); // l_name - $this->_PutDec($b,0,30,2); // l_fields - $this->_PutDec($b,0,32,2); // l_comm - $this->_PutDec($b,0,34,2); // disk_num - $this->_PutDec($b,0,36,2); // int_file_att - $this->_PutDec($b,0,38,4); // ext_file_att - $this->_PutDec($b,$PosLoc,42,4); // p_loc - $b .= $Ref['name']; // v_name - $b .= ''; // v_fields - $b .= ''; // v_comm - - $Ref['bin'] = $b; - - return $OutputLen; - - } - - function _DataCreateNewRef($Data, $DataType, $Compress, $Diff, $NameOrIdx) { - - if (is_array($Compress)) { - $result = 2; - $meth = $Compress['meth']; - $len_u = $Compress['len_u']; - $crc32 = $Compress['crc32']; - $Compress = false; - } elseif ($Compress and ($this->Meth8Ok)) { - $result = 1; - $meth = 8; - $len_u = false; // means unknown - $crc32 = false; - } else { - $result = ($Compress) ? -1 : 0; - $meth = 0; - $len_u = false; - $crc32 = false; - $Compress = false; - } - - if ($DataType==TBSZIP_STRING) { - $path = false; - if ($Compress) { - // we compress now in order to save PHP memory - $len_u = strlen($Data); - $crc32 = crc32($Data); - $Data = gzdeflate($Data); - $len_c = strlen($Data); - } else { - $len_c = strlen($Data); - if ($len_u===false) { - $len_u = $len_c; - $crc32 = crc32($Data); - } - } - } else { - $path = $Data; - $Data = false; - if (file_exists($path)) { - $fz = filesize($path); - if ($len_u===false) $len_u = $fz; - $len_c = ($Compress) ? false : $fz; - } else { - return $this->RaiseError("Cannot add the file '".$path."' because it is not found."); - } - } - - // at this step $Data and $crc32 can be false only in case of external file, and $len_c is false only in case of external file to compress - return array('data'=>$Data, 'path'=>$path, 'meth'=>$meth, 'len_u'=>$len_u, 'len_c'=>$len_c, 'crc32'=>$crc32, 'diff'=>$Diff, 'res'=>$result); - - } - - function _DataPrepare(&$Ref) { - // returns the real size of data - if ($Ref['path']!==false) { - $Ref['data'] = file_get_contents($Ref['path']); - if ($Ref['crc32']===false) $Ref['crc32'] = crc32($Ref['data']); - if ($Ref['len_c']===false) { - // means the data must be compressed - $Ref['data'] = gzdeflate($Ref['data']); - $Ref['len_c'] = strlen($Ref['data']); - } - } - } - - function _EstimateNewArchSize($Optim=true) { - // Return the size of the new archive, or false if it cannot be calculated (because of external file that must be compressed before to be insered) - - if ($this->ArchIsNew) { - $Len = strlen($this->CdInfo['bin']); - } else { - $Len = filesize($this->ArchFile); - } - - // files to replace or delete - foreach ($this->ReplByPos as $i) { - $Ref =& $this->ReplInfo[$i]; - if ($Ref===false) { - // file to delete - $Info =& $this->CdFileLst[$i]; - if (!isset($this->VisFileLst[$i])) { - if ($Optim) return false; // if $Optimization is set to true, then we d'ont rewind to read information - $this->_MoveTo($Info['p_loc']); - $this->_ReadFile($i, false); - } - $Vis =& $this->VisFileLst[$i]; - $Len += -strlen($Vis['bin']) -strlen($Info['bin']) - $Info['l_data_c']; - if (isset($Vis['desc_bin'])) $Len += -strlen($Vis['desc_bin']); - } elseif ($Ref['len_c']===false) { - return false; // information not yet known - } else { - // file to replace - $Len += $Ref['len_c'] + $Ref['diff']; - } - } - - // files to add - $i_lst = array_keys($this->AddInfo); - foreach ($i_lst as $i) { - $Ref =& $this->AddInfo[$i]; - if ($Ref['len_c']===false) { - return false; // information not yet known - } else { - $Len += $Ref['len_c'] + $Ref['diff']; - } - } - - return $Len; - - } - -} \ No newline at end of file diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon new file mode 100644 index 000000000..6d59e5233 --- /dev/null +++ b/phpstan-baseline.neon @@ -0,0 +1,11 @@ +parameters: + ignoreErrors: + - + message: "#^Variable \\$sortField in empty\\(\\) always exists and is not falsy\\.$#" + count: 2 + path: resources/epub-loader/CalibreDbLoader.class.php + + - + message: "#^Call to an undefined method DOMNode\\:\\:attr\\(\\)\\.$#" + count: 1 + path: resources/php-epub-meta/lib/EPub.php diff --git a/phpstan.neon.dist b/phpstan.neon.dist new file mode 100644 index 000000000..4cef5b9c2 --- /dev/null +++ b/phpstan.neon.dist @@ -0,0 +1,12 @@ +includes: + - phpstan-baseline.neon + +parameters: + level: 5 + paths: + - . + bootstrapFiles: + - vendor/autoload.php + excludePaths: + - vendor/* + - test/Sauce.php diff --git a/phpunit.xml.dist b/phpunit.xml.dist new file mode 100644 index 000000000..e901cad13 --- /dev/null +++ b/phpunit.xml.dist @@ -0,0 +1,26 @@ + + + + + ./ + + + ./resources + ./test + ./saucetest + ./vendor + config.php + config_default.php + + + + + + + + + + ./test/ + + + diff --git a/resources/dot-php/.hgtags b/resources/dot-php/.hgtags new file mode 100644 index 000000000..a24748477 --- /dev/null +++ b/resources/dot-php/.hgtags @@ -0,0 +1 @@ +9a405bbdd1a9eb1ba72eecfc67115d3bd3efdcbb 1.0.0 diff --git a/resources/dot-php/LICENSE b/resources/dot-php/LICENSE new file mode 100644 index 000000000..52df22e70 --- /dev/null +++ b/resources/dot-php/LICENSE @@ -0,0 +1,339 @@ +GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + PHP rendering engine for doT.js (The fastest + concise javascript template engine for nodejs and browsers) + Copyright (C) 2013 Sébastien Lucas + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + {signature of Ty Coon}, 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/resources/dot-php/README.md b/resources/dot-php/README.md new file mode 100644 index 000000000..a31fe87b9 --- /dev/null +++ b/resources/dot-php/README.md @@ -0,0 +1,41 @@ +doT-php +======= + +PHP rendering engine for [doT.js (The fastest + concise javascript template engine for nodejs and browsers)](https://github.com/olado/doT). + + +How to use it +------------- + +```php +// Load the library +require_once('resources/doT-php/doT.php'); + +// Load the template +$page = file_get_contents('templates/page.html'); + +// instanciate the object +$template = new doT(); + +// Compile your templace in a PHP function ($dot) +$dot = $template->template($page); + +// the data is simple PHP array +$data = array('title' => 'My custom title'); + +// Write the HTML +echo $dot($data); +``` + + +Warning +------- + +It's far from complete. I needed it just to provide a server side rendering engine +for another project ([COPS](https://github.com/seblucas/cops)). + +So the code provided works perfectly for the templates of COPS and was never tested +elsewhere, doT's unit test were also never tested. + +That being said, You can fork, enhance it and send me some pull request, I'll +happily merge them. diff --git a/resources/dot-php/composer.json b/resources/dot-php/composer.json new file mode 100644 index 000000000..30afa9262 --- /dev/null +++ b/resources/dot-php/composer.json @@ -0,0 +1,22 @@ +{ + "name": "seblucas/dot-php", + "type": "library", + "description": "PHP rendering engine for doT.js (The fastest + concise javascript template engine for nodejs and browsers)", + "keywords": ["doT", "template", "engine", "rendering"], + "homepage": "https://github.com/seblucas/doT-php", + "license": "GPL-2.0-or-later", + "authors": [ + { + "name": "Sébastien Lucas", + "email": "sebastien@slucas.fr", + "homepage": "http://www.slucas.fr/", + "role": "Developer" + } + ], + "require": { + "php": ">=5.3.0" + }, + "autoload": { + "classmap": ["doT.php"] + } +} diff --git a/resources/dot-php/doT.php b/resources/dot-php/doT.php new file mode 100644 index 000000000..d38b59d6f --- /dev/null +++ b/resources/dot-php/doT.php @@ -0,0 +1,114 @@ + + */ + + +class doT +{ + public $functionBody; + /** + * @var callable + */ + private $functionCode; + public $def; + + public function resolveDefs($block) + { + $me = $this; + return preg_replace_callback("/\{\{#([\s\S]+?)\}\}/", function ($m) use ($me) { + $d = $m[1]; + $d = substr($d, 4); + if (!array_key_exists($d, $me->def)) { + return ""; + } + if (preg_match("/\{\{#([\s\S]+?)\}\}/", $me->def [$d])) { + //return $me->resolveDefs($me->def [$d], $me->def); + return $me->resolveDefs($me->def [$d]); + } else { + return $me->def [$d]; + } + }, $block); + } + + public function handleDotNotation($string) + { + $out = preg_replace("/(\w+)\.(.*?)([\s,\)])/", "\$$1[\"$2\"]$3", $string); + $out = preg_replace("/(\w+)\.([\w\.]*?)$/", "\$$1[\"$2\"] ", $out); + $out = preg_replace("/\./", '"]["', $out); + + // Special hideous case : shouldn't be committed + $out = preg_replace("/^i /", ' $i ', $out); + return $out; + } + + public function template($string, $def) + { + $me = $this; + + $func = $string; + + // deps + if (empty($def)) { + $func = preg_replace("/\{\{#([\s\S]+?)\}\}/", "", $func); + } else { + $this->def = $def; + $func = $this->resolveDefs($func); + } + + // @todo this messes up serverside rendering for client-side javascript, e.g. in header template: + // handleDotNotation($m[1]) . " . '"; + }, $func); + // Conditional + $func = preg_replace_callback("/\{\{\?(\?)?\s*([\s\S]*?)\s*\}\}/", function ($m) use ($me) { + $elsecase = $m[1]; + $code = $m[2]; + if ($elsecase) { + if ($code) { + return "';} else if (" . $me->handleDotNotation($code) . ") { $" . "out.='"; + } else { + return "';} else { $" . "out.='"; + } + } else { + if ($code) { + return "'; if (" . $me->handleDotNotation($code) . ") { $" . "out.='"; + } else { + return "';} $" . "out.='"; + } + } + }, $func); + // Iterate + $func = preg_replace_callback("/\{\{~\s*(?:\}\}|([\s\S]+?)\s*\:\s*([\w$]+)\s*(?:\:\s*([\w$]+))?\s*\}\})/", function ($m) use ($me) { + if (count($m) > 1) { + $iterate = $m[1]; + $vname = $m[2]; + $iname = $m[3]; + $iterate = $me->handleDotNotation($iterate); + return "'; for (\$$iname = 0; \$$iname < count($iterate); \$$iname++) { \$$vname = $iterate [\$$iname]; \$out.='"; + } else { + return "';} $" . "out.='"; + } + }, $func); + $func = '$out = \'' . $func . '\'; return $out;'; + + $this->functionBody = $func; + + //return @create_function('$it', $func); + return function ($it) use ($func) { + return eval($func); + }; + } + + public function execute($data) + { + return ($this->functionCode)($data); + } +} diff --git a/resources/monocle/README.md b/resources/monocle/README.md new file mode 100644 index 000000000..34a3771d6 --- /dev/null +++ b/resources/monocle/README.md @@ -0,0 +1,150 @@ +# Monocle + +A silky, tactile browser-based ebook reader. + +Initial development by Joseph Pearson of Inventive Labs. Released under the +MIT license. + +____________________________________________________________________________ +THIS PROJECT IS NOW OVER EIGHT YEARS OLD. +IT HAS NOT BEEN ACTIVELY MAINTAINED SINCE 2015. +You are welcome to explore and learn from the code, but it is no longer the +best approach for modern browsers and devices, and it is not recommended for +new projects or production applications. +____________________________________________________________________________ + + +## Getting Monocle + +There's a few different ways to get Monocle. The easiest way to explore +it is from the test site, which is always running the latest `master`: + +http://test.monoclejs.com/test + +To grab the code for your own use, see: + +https://github.com/joseph/Monocle/wiki/Getting-Monocle-running + +The scripts and stylesheets are separated into: + +* `monocore` - the essential Monocle functionality +* `monoctrl` - the optional basic controls for page numbers, font-sizing, etc + + +## Integrating Monocle + +Here's the simplest thing that could possibly work. + + + + + + + + + + +
    +

    Hello world.

    +
    + + + + + + +In this example, we initialise the reader with the contents of the div +itself. In theory there's no limit on the size of the contents of that div. + +A more advanced scenario involves feeding Monocle a "book data object", from +which it can lazily load the contents of the book as the user requests it. + + +## Connecting Monocle to your book content + +For a non-trivial Monocle implementation, your task is to connect the +Monocle Reader to your book's HTML content and structure. You create +something called "the book data object" to do this. + +The book data object is really pretty simple. You'll find the specification +and some examples in the [Monocle Wiki page on the book data object](https://github.com/joseph/Monocle/wiki/Book-data-object). + +For more advanced uses and customisations of Monocle, you should definitely +read the [Monocle Wiki](https://github.com/joseph/Monocle/wiki). + + +## Browser support + +At this time, Monocle aims for full support of all browsers with a +W3C-compliant CSS column module implementation. That is Gecko, WebKit and +Opera at this point. Please encourage your browser-maker to work on +implementing these standards in particular: + +* CSS Multi-Column Layout +* W3C DOM Level 2 Event Model +* CSS 2D Transforms (better: 3D Transforms, even better: hardware acceleration) + +Monocle has a particular focus on mobile devices. Monocle supports: + +* iOS 4.2+ +* Android 2.2+ +* Kindle 3 + +All these mobile platforms implement columned iframes differently, so support +may be imperfect in places, but we're working on it. Patches that improve or +broaden Monocle's browser support are very welcome (but please provide tests). + +Inventive Labs would like to thank Ebooq for providing a device to assist with +Android testing. + + +## Future directions + +Monocle has a small set of big goals: + +* Faster, more responsive page flipping +* Wider browser support (and better tests, automated as far as possible) +* Tracking spec developments in EPUB and Zhook, supporting where appropriate + +We'd also like to provide more implementation showcases in the tests, and +offer more developer documentation in the wiki. + +If you can help out with any of these things, fork away (or create an issue +on GitHub). + + +## History + +3.2.0 - A new event management subsystem, called Gala, replacing the old + Monocle.Events. Gala unifies touch and mouse event registration + a lot better. It also works as a standalone library, if you need that - + there are no dependencies on other parts of Monocle. + +3.1.0 - Numerous stability fixes, plus improvements for Android and Opera, + including minor API changes to flippers and slow-browser detection. + +3.0.1 - Bugfixes for component loading, cancelling magic panel contacts. + +3.0.0 - Magic panel, IE10 support, iOS6 support, better Android support, + selection events, billboard feature, Monocle.Formatting to clean up + Reader, removing deprecated flippers, Stencil refactor, component + weights (for more accurate component percentages), and many bug + fixes. See https://github.com/joseph/Monocle/compare/v2.3.1...v3.0.0 + +2.3.1 - Fix for serious Firefox 12 bug in paginating content. + +2.3.0 - Smoother transitions and animations in more browsers. + +2.2.1 - Slider fixes for better iOS performance. + +2.2.0 - Speed, compatibility improvements (esp iOS5, Android, Kindle3). + +2.1.0 - Source file reorganisation, Sprockets 2, distributables, wiki. + +2.0.0 - Complete rewrite to sandbox content in iframes (the Componentry branch). + +1.0.1 - Scrolling flipper, more tests, work on sandboxing in iframe (Framer). + +1.0.0 - Initial release. diff --git a/resources/monocle/scripts/monocore.js b/resources/monocle/scripts/monocore.js new file mode 100644 index 000000000..ae8b64532 --- /dev/null +++ b/resources/monocle/scripts/monocore.js @@ -0,0 +1,5641 @@ +/*! + * Monocle - A silky, tactile browser-based ebook JavaScript library. + * + * Copyright 2012, Joseph Pearson + * Licensed under the MIT license. + */ + + +Monocle = { + VERSION: "3.2.0" +}; + + +Monocle.Dimensions = {}; +Monocle.Controls = {}; +Monocle.Flippers = {}; +Monocle.Panels = {}; +// A class that tests the browser environment for required capabilities and +// known bugs (for which we have workarounds). +// +Monocle.Env = function () { + + var API = { constructor: Monocle.Env } + var k = API.constants = API.constructor; + var p = API.properties = { + // Assign to a function before running survey in order to get + // results as they come in. The function should take two arguments: + // testName and value. + resultCallback: null + } + + // These are private variables so they don't clutter up properties. + var css = Monocle.Browser.css; + var activeTestName = null; + var frameLoadCallback = null; + var testFrame = null; + var testFrameCntr = null; + var testFrameSize = 100; + var surveyCallback = null; + + + function survey(cb) { + surveyCallback = cb; + runNextTest(); + } + + + function runNextTest() { + var test = envTests.shift(); + if (!test) { return completed(); } + activeTestName = test[0]; + try { test[1](); } catch (e) { result(e); } + } + + + // Each test should call this to say "I'm finished, run the next test." + // + function result(val) { + API[activeTestName] = val; + if (p.resultCallback) { p.resultCallback(activeTestName, val); } + runNextTest(); + return val; + } + + + // Invoked after all tests have run. + // + function completed() { + // Remove the test frame after a slight delay (otherwise Gecko spins). + Monocle.defer(removeTestFrame); + + if (typeof surveyCallback == "function") { + fn = surveyCallback; + surveyCallback = null; + fn(API); + } + } + + + // A bit of sugar for simplifying a detection pattern: does this + // function exist? + // + // Pass a string snippet of JavaScript to be evaluated. + // + function testForFunction(str) { + return function () { result(typeof eval(str) == "function"); } + } + + + // A bit of sugar to indicate that the detection function for this test + // hasn't been written yet... + // + // Pass the value you want assigned for the test until it is implemented. + // + function testNotYetImplemented(rslt) { + return function () { result(rslt); } + } + + + // Loads (or reloads) a hidden iframe so that we can test browser features. + // + // cb is the callback that is fired when the test frame's content is loaded. + // + // src is optional, in which case it defaults to 4. If provided, it can be + // a number (specifying the number of pages of default content), or a string, + // which will be loaded as a URL. + // + function loadTestFrame(cb, src) { + if (!testFrame) { testFrame = createTestFrame(); } + frameLoadCallback = cb; + + src = src || 4; + + if (typeof src == "number") { + var pgs = []; + for (var i = 1, ii = src; i <= ii; ++i) { + pgs.push("
    Page "+i+"
    "); + } + var divStyle = [ + "display:inline-block", + "line-height:"+testFrameSize+"px", + "width:"+testFrameSize+"px" + ].join(";"); + src = "javascript:'"+ + ''+ + ''+ + ''+pgs.join("")+''+ + "'"; + } + + testFrame.src = src; + } + + + // Creates the hidden test frame and returns it. + // + function createTestFrame() { + testFrameCntr = document.createElement('div'); + testFrameCntr.style.cssText = [ + "width:"+testFrameSize+"px", + "height:"+testFrameSize+"px", + "overflow:hidden", + "position:absolute", + "visibility:hidden" + ].join(";"); + document.body.appendChild(testFrameCntr); + + var fr = document.createElement('iframe'); + testFrameCntr.appendChild(fr); + fr.setAttribute("scrolling", "no"); + fr.style.cssText = [ + "width:100%", + "height:100%", + "border:none", + "background:#900" + ].join(";"); + fr.addEventListener( + "load", + function () { + if (!fr.contentDocument || !fr.contentDocument.body) { return; } + var bd = fr.contentDocument.body; + bd.style.cssText = ([ + "margin:0", + "padding:0", + "position:absolute", + "height:100%", + "width:100%", + "-webkit-column-width:"+testFrameSize+"px", + "-webkit-column-gap:0", + "-webkit-column-fill:auto", + "-moz-column-width:"+testFrameSize+"px", + "-moz-column-gap:0", + "-moz-column-fill:auto", + "-o-column-width:"+testFrameSize+"px", + "-o-column-gap:0", + "-o-column-fill:auto", + "column-width:"+testFrameSize+"px", + "column-gap:0", + "column-fill:auto" + ].join(";")); + if (bd.scrollHeight > testFrameSize) { + bd.style.cssText += ["min-width:200%", "overflow:hidden"].join(";"); + if (bd.scrollHeight <= testFrameSize) { + bd.className = "column-force"; + } else { + bd.className = "column-failed "+bd.scrollHeight; + } + } + frameLoadCallback(fr); + }, + false + ); + return fr; + } + + + function removeTestFrame() { + if (testFrameCntr && testFrameCntr.parentNode) { + testFrameCntr.parentNode.removeChild(testFrameCntr); + } + } + + + function columnedWidth(fr) { + var bd = fr.contentDocument.body; + var de = fr.contentDocument.documentElement; + return Math.max(bd.scrollWidth, de.scrollWidth); + } + + + var envTests = [ + + // TEST FOR REQUIRED CAPABILITIES + + ["supportsW3CEvents", testForFunction("window.addEventListener")], + ["supportsCustomEvents", testForFunction("document.createEvent")], + ["supportsColumns", function () { + result(css.supportsPropertyWithAnyPrefix('column-width')); + }], + ["supportsTransform", function () { + result(css.supportsProperty([ + 'transformProperty', + 'WebkitTransform', + 'MozTransform', + 'OTransform', + 'msTransform' + ])); + }], + + + // TEST FOR OPTIONAL CAPABILITIES + + // Does it do CSS transitions? + ["supportsTransition", function () { + result(css.supportsPropertyWithAnyPrefix('transition')) + }], + + // Can we find nodes in a document with an XPath? + // + ["supportsXPath", testForFunction("document.evaluate")], + + // Can we find nodes in a document natively with a CSS selector? + // + ["supportsQuerySelector", testForFunction("document.querySelector")], + + // Can we do 3d transforms? + // + ["supportsTransform3d", function () { + result( + css.supportsMediaQueryProperty('transform-3d') && + css.supportsProperty([ + 'perspectiveProperty', + 'WebkitPerspective', + 'MozPerspective', + 'OPerspective', + 'msPerspective' + ]) && + !Monocle.Browser.renders.slow // Some older browsers can't be trusted. + ); + }], + + + // Commonly-used browser functionality + ["supportsOfflineCache", function () { + result(typeof window.applicationCache != 'undefined'); + }], + + ["supportsLocalStorage", function () { + // NB: Some duplicitous early Android browsers claim to have + // localStorage, but calls to getItem() fail. + result( + typeof window.localStorage != "undefined" && + typeof window.localStorage.getItem == "function" + ) + }], + + + // CHECK OUT OUR CONTEXT + + // Does the device have a MobileSafari-style touch interface? + // + ["touch", function () { + result( + ('ontouchstart' in window) || + css.supportsMediaQueryProperty('touch-enabled') + ); + }], + + // Is the Reader embedded, or in the top-level window? + // + ["embedded", function () { result(top != self) }], + + + // TEST FOR CERTAIN RENDERING OR INTERACTION BUGS + + // iOS (at least up to version 4.1) makes a complete hash of touch events + // when an iframe is overlapped by other elements. It's a dog's breakfast. + // See test/bugs/ios-frame-touch-bug for details. + // + ["brokenIframeTouchModel", function () { + result(Monocle.Browser.iOSVersionBelow("4.2")); + }], + + // Webkit-based browsers put floated elements in the wrong spot when + // columns are used -- they appear way down where they would be if there + // were no columns. Presumably the float positions are calculated before + // the columns. A bug has been lodged, and it's fixed in recent WebKits. + // + ["floatsIgnoreColumns", function () { + if (!Monocle.Browser.is.WebKit) { return result(false); } + match = navigator.userAgent.match(/AppleWebKit\/([\d\.]+)/); + if (!match) { return result(false); } + return result(match[1] < "534.30"); + }], + + // The latest engines all agree that if a body is translated leftwards, + // its scrollWidth is shortened. But some older WebKits (notably iOS4) + // do not subtract translateX values from scrollWidth. In this case, + // we should not add the translate back when calculating the width. + // + ["widthsIgnoreTranslate", function () { + loadTestFrame(function (fr) { + var firstWidth = columnedWidth(fr); + var s = fr.contentDocument.body.style; + var props = css.toDOMProps("transform"); + for (var i = 0, ii = props.length; i < ii; ++i) { + s[props[i]] = "translateX(-600px)"; + } + var secondWidth = columnedWidth(fr); + for (i = 0, ii = props.length; i < ii; ++i) { + s[props[i]] = "none"; + } + result(secondWidth == firstWidth); + }); + }], + + // On Android browsers, if the component iframe has a relative width (ie, + // 100%), the width of the entire browser will keep expanding and expanding + // to fit the width of the body of the iframe (which, with columns, is + // massive). So, 100% is treated as "of the body content" rather than "of + // the parent dimensions". In this scenario, we need to give the component + // iframe a fixed width in pixels. + // + // In iOS, the frame is clipped by overflow:hidden, so this doesn't seem to + // be a problem. + // + ["relativeIframeExpands", function () { + result(navigator.userAgent.indexOf("Android 2") >= 0); + }], + + // iOS3 will pause JavaScript execution if it gets a style-change + a + // scroll change on a component body. Weirdly, this seems to break GBCR + // in iOS4. + // + ["scrollToApplyStyle", function () { + result(Monocle.Browser.iOSVersionBelow("4")); + }], + + + // TEST FOR OTHER QUIRKY BROWSER BEHAVIOUR + + // Older versions of WebKit (iOS3, Kindle3) need a min-width set on the + // body of the iframe at 200%. This forces columns. But when this + // min-width is set, it's more difficult to recognise 1 page components, + // so we generally don't want to force it unless we have to. + // + ["forceColumns", function () { + loadTestFrame(function (fr) { + var bd = fr.contentDocument.body; + result(bd.className ? true : false); + }); + }], + + // A component iframe's body is absolutely positioned. This means that + // the documentElement should have a height of 0, since it contains nothing + // other than an absolutely positioned element. + // + // But for some browsers (Gecko and Opera), the documentElement is as + // wide as the full columned content, and the body is only as wide as + // the iframe element (ie, the first column). + // + // It gets weirder. Gecko sometimes behaves like WebKit (not clipping the + // body) IF the component has been loaded via HTML/JS/Nodes, not URL. Still + // can't reproduce outside Monocle. + // + // FIXME: If we can figure out a reliable behaviour for Gecko, we should + // use it to precalculate the workaround. At the moment, this test isn't + // used, but it belongs in src/dimensions/columns.js#columnedDimensions(). + // + // ["iframeBodyWidthClipped", function () { + // loadTestFrame(function (fr) { + // var doc = fr.contentDocument; + // result( + // doc.body.scrollWidth <= testFrameSize && + // doc.documentElement.scrollWidth > testFrameSize + // ); + // }) + // }], + + // Finding the page that a given HTML node is on is typically done by + // calculating the offset of its rectange from the body's rectangle. + // + // But if this information isn't provided by the browser, we need to use + // node.scrollIntoView and check the scrollOffset. Basically iOS3 is the + // only target platform that doesn't give us the rectangle info. + // + ["findNodesByScrolling", function () { + result(typeof document.body.getBoundingClientRect !== "function"); + }], + + // In MobileSafari browsers, iframes are rendered at the width and height + // of their content, rather than having scrollbars. So in that case, it's + // the containing element (the "sheaf") that must be scrolled, not the + // iframe body. + // + ["sheafIsScroller", function () { + loadTestFrame(function (fr) { + result(fr.parentNode.scrollWidth > testFrameSize); + }); + }], + + // For some reason, iOS MobileSafari sometimes loses track of a page after + // slideOut -- it thinks it has an x-translation of 0, rather than -768 or + // whatever. So the page gets "stuck" there, until it is given a non-zero + // x-translation. The workaround is to set a non-zero duration on the jumpIn, + // which seems to force WebKit to recalculate the x of the page. Weird, yeah. + // + ["stickySlideOut", function () { + result(Monocle.Browser.is.MobileSafari); + }], + + + // Chrome and Firefox incorrectly clip text when the dimensions of + // a page are not an integer. IE10 clips text when the page dimensions + // are rounded. + // + ['roundPageDimensions', function () { + result(!Monocle.Browser.is.IE); + }], + + + + // In IE10, the element of the iframe's document has scrollbars, + // unless you set its style.overflow to 'hidden'. + // + ['documentElementHasScrollbars', function () { + result(Monocle.Browser.is.IE); + }], + + + // Older versions of iOS (<6) would render blank pages if they were + // off the screen when their layout/position was updated. + // + ['offscreenRenderingClipped', function () { + result(Monocle.Browser.iOSVersionBelow('6')); + }], + + + // Gecko is better at loading content with document.write than with + // javascript: URLs. With the latter, it tends to put cruft in history, + // and gets confused by . + ['loadHTMLWithDocWrite', function () { + result(Monocle.Browser.is.Gecko || Monocle.Browser.is.Opera); + }] + + ]; + + + function isCompatible() { + return ( + API.supportsW3CEvents && + API.supportsCustomEvents && + API.supportsColumns && + API.supportsTransform && + !API.brokenIframeTouchModel + ); + } + + + API.survey = survey; + API.isCompatible = isCompatible; + + return API; +} +; +// A class for manipulating CSS properties in a browser-engine-aware way. +// +Monocle.CSS = function () { + + var API = { constructor: Monocle.CSS } + var k = API.constants = API.constructor; + var p = API.properties = { + guineapig: document.createElement('div') + } + + + // Returns engine-specific properties, + // + // eg: + // + // toCSSProps('transform') + // + // ... in WebKit, this will return: + // + // ['transform', '-webkit-transform'] + // + function toCSSProps(prop) { + var props = [prop]; + var eng = k.engines.indexOf(Monocle.Browser.engine); + if (eng) { + var pf = k.prefixes[eng]; + if (pf) { + props.push(pf+prop); + } + } + return props; + } + + + // Returns an engine-specific CSS string. + // + // eg: + // + // toCSSDeclaration('column-width', '300px') + // + // ... in Mozilla, this will return: + // + // "column-width: 300px; -moz-column-width: 300px;" + // + function toCSSDeclaration(prop, val) { + var props = toCSSProps(prop); + for (var i = 0, ii = props.length; i < ii; ++i) { + props[i] += ": "+val+";"; + } + return props.join(""); + } + + + // Returns an array of DOM properties specific to this engine. + // + // eg: + // + // toDOMProps('column-width') + // + // ... in Opera, this will return: + // + // [columnWidth, OColumnWidth] + // + function toDOMProps(prop) { + var parts = prop.split('-'); + for (var i = parts.length; i > 0; --i) { + parts[i] = capStr(parts[i]); + } + + var props = [parts.join('')]; + var eng = k.engines.indexOf(Monocle.Browser.engine); + if (eng) { + var pf = k.domprefixes[eng]; + if (pf) { + parts[0] = capStr(parts[0]); + props.push(pf+parts.join('')); + } + } + return props; + } + + + // Is this exact property (or any in this array of properties) supported + // by this engine? + // + function supportsProperty(props) { + for (var i in props) { + if (p.guineapig.style[props[i]] !== undefined) { return true; } + } + return false; + } // Thanks modernizr! + + + + // Is this property (or a prefixed variant) supported by this engine? + // + function supportsPropertyWithAnyPrefix(prop) { + return supportsProperty(toDOMProps(prop)); + } + + + function supportsMediaQuery(query) { + var gpid = "monocle_guineapig"; + p.guineapig.id = gpid; + var st = document.createElement('style'); + st.textContent = query+'{#'+gpid+'{height:3px}}'; + (document.head || document.getElementsByTagName('head')[0]).appendChild(st); + document.documentElement.appendChild(p.guineapig); + + var result = p.guineapig.offsetHeight === 3; + + st.parentNode.removeChild(st); + p.guineapig.parentNode.removeChild(p.guineapig); + + return result; + } // Thanks modernizr! + + + function supportsMediaQueryProperty(prop) { + return supportsMediaQuery( + '@media (' + k.prefixes.join(prop+'),(') + 'monocle__)' + ); + } + + + function capStr(wd) { + return wd ? wd.charAt(0).toUpperCase() + wd.substr(1) : ""; + } + + + API.toCSSProps = toCSSProps; + API.toCSSDeclaration = toCSSDeclaration; + API.toDOMProps = toDOMProps; + API.supportsProperty = supportsProperty; + API.supportsPropertyWithAnyPrefix = supportsPropertyWithAnyPrefix; + API.supportsMediaQuery = supportsMediaQuery; + API.supportsMediaQueryProperty = supportsMediaQueryProperty; + + return API; +} + + +Monocle.CSS.engines = ["W3C", "WebKit", "Gecko", "Opera", "IE", "Konqueror"]; +Monocle.CSS.prefixes = ["", "-webkit-", "-moz-", "-o-", "-ms-", "-khtml-"]; +Monocle.CSS.domprefixes = ["", "Webkit", "Moz", "O", "ms", "Khtml"]; +// STUBS - simple debug functions and polyfills to normalise client +// execution environments. + + +// A little console stub if not initialized in a console-equipped browser. +// +if (typeof window.console == "undefined") { + window.console = { messages: [] } + window.console.log = function (msg) { + this.messages.push(msg); + } + window.console.warn = window.console.log; +} + + +// A simple version of console.dir that works on iOS. +// +window.console.compatDir = function (obj) { + var stringify = function (o) { + var parts = []; + for (x in o) { + parts.push(x + ": " + o[x]); + } + return parts.join(";\n"); + } + + var out = stringify(obj); + window.console.log(out); + return out; +} + + +// This is called by Monocle methods and practices that are no longer +// recommended and will soon be removed. +// +window.console.deprecation = function (msg) { + console.warn("[DEPRECATION]: "+msg); + if (typeof console.trace == "function") { + console.trace(); + } +} + + +// A convenient alias for setTimeout that assumes 0 if no timeout is specified. +// +Monocle.defer = function (fn, time) { + if (typeof fn == "function") { + return setTimeout(fn, time || 0); + } +} +; +Monocle.Browser = {}; + +// Compare the user-agent string to a string or regex pattern. +// +Monocle.Browser.uaMatch = function (test) { + var ua = navigator.userAgent; + if (typeof test == "string") { return ua.indexOf(test) >= 0; } + return !!ua.match(test); +} + + +// Detect the browser engine and set boolean flags for reference. +// +Monocle.Browser.is = { + IE: !!(window.attachEvent && !Monocle.Browser.uaMatch('Opera')), + Opera: Monocle.Browser.uaMatch('Opera'), + WebKit: Monocle.Browser.uaMatch(/Apple\s?WebKit/), + Gecko: Monocle.Browser.uaMatch('Gecko') && !Monocle.Browser.uaMatch('KHTML'), + MobileSafari: Monocle.Browser.uaMatch(/OS \d_.*AppleWebKit.*Mobile/) +} + + +// Set the browser engine string. +// +if (Monocle.Browser.is.IE) { + Monocle.Browser.engine = "IE"; +} else if (Monocle.Browser.is.Opera) { + Monocle.Browser.engine = "Opera"; +} else if (Monocle.Browser.is.WebKit) { + Monocle.Browser.engine = "WebKit"; +} else if (Monocle.Browser.is.Gecko) { + Monocle.Browser.engine = "Gecko"; +} else { + console.warn("Unknown engine; assuming W3C compliant."); + Monocle.Browser.engine = "W3C"; +} + + +// Detect the client platform (typically device/operating system). +// +Monocle.Browser.on = { + iPhone: Monocle.Browser.is.MobileSafari && screen.width == 320, + iPad: Monocle.Browser.is.MobileSafari && screen.width == 768, + UIWebView: ( + Monocle.Browser.is.MobileSafari && + !Monocle.Browser.uaMatch('Safari') && + !navigator.standalone + ), + BlackBerry: Monocle.Browser.uaMatch('BlackBerry'), + Android: ( + Monocle.Browser.uaMatch('Android') || + Monocle.Browser.uaMatch(/Linux;.*EBRD/) // Sony Readers + ), + MacOSX: ( + Monocle.Browser.uaMatch('Mac OS X') && + !Monocle.Browser.is.MobileSafari + ), + Kindle3: Monocle.Browser.uaMatch(/Kindle\/3/) +} + + +// It is only because MobileSafari is responsible for so much anguish that +// we special-case it here. Not a badge of honour. +// +if (Monocle.Browser.is.MobileSafari) { + (function () { + var ver = navigator.userAgent.match(/ OS ([\d_]+)/); + if (ver) { + Monocle.Browser.iOSVersion = ver[1].replace(/_/g, '.'); + } else { + console.warn("Unknown MobileSafari user agent: "+navigator.userAgent); + } + })(); +} +Monocle.Browser.iOSVersionBelow = function (strOrNum) { + return !!Monocle.Browser.iOSVersion && Monocle.Browser.iOSVersion < strOrNum; +} + + +// Some browser environments are too slow or too problematic for +// special animation effects. +// +// FIXME: These tests are too opinionated. Replace with more targeted tests. +// +Monocle.Browser.renders = (function () { + var ua = navigator.userAgent; + var caps = {}; + caps.eInk = Monocle.Browser.on.Kindle3; + caps.slow = ( + caps.eInk || + (Monocle.Browser.on.Android && !ua.match(/Chrome/)) || + Monocle.Browser.on.Blackberry || + ua.match(/NintendoBrowser/) + ); + return caps; +})(); + + +// A helper class for sniffing CSS features and creating CSS rules +// appropriate to the current rendering engine. +// +Monocle.Browser.css = new Monocle.CSS(); + + +// During Reader initialization, this method is called to create the +// "environment", which tests for the existence of various browser +// features and bugs, then invokes the callback to continue initialization. +// +// If the survey has already been conducted and the env exists, calls +// callback immediately. +// +Monocle.Browser.survey = function (callback) { + if (!Monocle.Browser.env) { + Monocle.Browser.env = new Monocle.Env(); + Monocle.Browser.env.survey(callback); + } else if (typeof callback == "function") { + callback(); + } +} +; +Gala = {} + + +// Register an event listener. +// +Gala.listen = function (elem, evtType, fn, useCapture) { + elem = Gala.$(elem); + if (elem.addEventListener) { + elem.addEventListener(evtType, fn, useCapture || false); + } else if (elem.attachEvent) { + if (evtType.indexOf(':') < 1) { + elem.attachEvent('on'+evtType, fn); + } else { + var h = (Gala.IE_REGISTRATIONS[elem] = Gala.IE_REGISTRATIONS[elem] || {}); + var a = (h[evtType] = h[evtType] || []); + a.push(fn); + } + } +} + + +// Remove an event listener. +// +Gala.deafen = function (elem, evtType, fn, useCapture) { + elem = Gala.$(elem); + if (elem.removeEventListener) { + elem.removeEventListener(evtType, fn, useCapture || false); + } else if (elem.detachEvent) { + if (evtType.indexOf(':') < 1) { + elem.detachEvent('on'+evtType, fn); + } else { + var h = (Gala.IE_REGISTRATIONS[elem] = Gala.IE_REGISTRATIONS[elem] || {}); + var a = (h[evtType] = h[evtType] || []); + for (var i = 0, ii = a.length; i < ii; ++i) { + if (a[i] == fn) { a.splice(i, 1); } + } + } + } +} + + +// Fire an event on the element. +// +// The data supplied to this function will be available in the event object in +// the 'm' property -- eg, alert(evt.m) --> 'foo' +// +Gala.dispatch = function (elem, evtType, data, cancelable) { + elem = Gala.$(elem); + if (elem.dispatchEvent) { + var evt = document.createEvent('Events'); + evt.initEvent(evtType, false, cancelable || false); + evt.m = data; + return elem.dispatchEvent(evt); + } else if (elem.attachEvent && evtType.indexOf(':') >= 0) { + if (!Gala.IE_REGISTRATIONS[elem]) { return true; } + var evtHandlers = Gala.IE_REGISTRATIONS[elem][evtType]; + if (!evtHandlers || evtHandlers.length < 1) { return true; } + var evt = { + type: evtType, + currentTarget: elem, + target: elem, + m: data, + defaultPrevented: false, + preventDefault: function () { evt.defaultPrevented = true; } + } + var q, processQueue = Gala.IE_INVOCATION_QUEUE.length == 0; + for (var i = 0, ii = evtHandlers.length; i < ii; ++i) { + q = { elem: elem, evtType: evtType, handler: evtHandlers[i], evt: evt } + Gala.IE_INVOCATION_QUEUE.push(q); + } + if (processQueue) { + while (q = Gala.IE_INVOCATION_QUEUE.shift()) { + //console.log("IE EVT on %s: '%s' with data: %s", q.elem, q.evtType, q.evt.m); + q.handler(q.evt); + } + } + return !(cancelable && evt.defaultPrevented); + } else { + console.warn('[GALA] Cannot dispatch non-namespaced events: '+evtType); + return true; + } +} + + +// Prevents the browser-default action on an event and stops it from +// propagating up the DOM tree. +// +Gala.stop = function (evt) { + evt = evt || window.event; + if (evt.preventDefault) { evt.preventDefault(); } + if (evt.stopPropagation) { evt.stopPropagation(); } + evt.returnValue = false; + evt.cancelBubble = true; + return false; +} + + +// Add a group of listeners, which is just a hash of { evtType: callback, ... } +// +Gala.listenGroup = function (elem, listeners, useCapture) { + for (evtType in listeners) { + Gala.listen(elem, evtType, listeners[evtType], useCapture || false); + } +} + + +// Remove a group of listeners. +// +Gala.deafenGroup = function (elem, listeners, useCapture) { + for (evtType in listeners) { + Gala.deafen(elem, evtType, listeners[evtType], useCapture || false); + } +} + + +// Replace a group of listeners with another group, re-using the same +// 'listeners' object -- a common pattern. +// +Gala.replaceGroup = function (elem, listeners, newListeners, useCapture) { + Gala.deafenGroup(elem, listeners, useCapture || false); + for (evtType in listeners) { delete listeners[evtType]; } + for (evtType in newListeners) { listeners[evtType] = newListeners[evtType]; } + Gala.listenGroup(elem, listeners, useCapture || false); + return listeners; +} + + +// Listen for a tap or a click event. +// +// Returns a 'listener' object that can be passed to Gala.deafenGroup(). +// +// If 'tapClass' is undefined, it defaults to 'tapping'. If it is a blank +// string, no class is assigned. +// +Gala.onTap = function (elem, fn, tapClass) { + elem = Gala.$(elem); + if (typeof tapClass == 'undefined') { tapClass = Gala.TAPPING_CLASS; } + var tapping = false; + var fns = { + start: function (evt) { + tapping = true; + if (tapClass) { elem.classList.add(tapClass); } + }, + move: function (evt) { + if (!tapping) { return; } + tapping = false; + if (tapClass) { elem.classList.remove(tapClass); } + }, + end: function (evt) { + if (!tapping) { return; } + fns.move(evt); + evt.currentTarget = evt.currentTarget || evt.srcElement; + fn(evt); + }, + noop: function (evt) {} + } + var noopOnClick = function (listeners) { + Gala.listen(elem, 'click', listeners.click = fns.noop); + } + Gala.listen(window, 'gala:contact:cancel', fns.move); + return Gala.onContact(elem, fns, false, noopOnClick); +} + + +// Register a series of functions to listen for the start, move, end +// events of a mouse or touch interaction. +// +// 'fns' argument is an object like: +// +// { +// 'start': function () { ... }, +// 'move': function () { ... }, +// 'end': function () { ... }, +// 'cancel': function () { ... } +// } +// +// All of the functions in this object are optional. +// +// Returns an object that can later be passed to Gala.deafenGroup. +// +Gala.onContact = function (elem, fns, useCapture, initCallback) { + elem = Gala.$(elem); + var listeners = null; + var inited = false; + + // If we see a touchstart event, register all these listeners. + var touchListeners = function () { + var l = {} + if (fns.start) { + l.touchstart = function (evt) { + if (evt.touches.length <= 1) { fns.start(evt); } + } + } + if (fns.move) { + l.touchmove = function (evt) { + if (evt.touches.length <= 1) { fns.move(evt); } + } + } + if (fns.end) { + l.touchend = function (evt) { + if (evt.touches.length <= 1) { fns.end(evt); } + } + } + if (fns.cancel) { + l.touchcancel = fns.cancel; + } + return l; + } + + // Whereas if we see a mousedown event, register all these listeners. + var mouseListeners = function () { + var l = {}; + if (fns.start) { + l.mousedown = function (evt) { if (evt.button < 2) { fns.start(evt); } } + } + if (fns.move) { + l.mousemove = fns.move; + } + if (fns.end) { + l.mouseup = function (evt) { if (evt.button < 2) { fns.end(evt); } } + } + // if (fns.cancel) { + // l.mouseout = function (evt) { + // obj = evt.relatedTarget || evt.fromElement; + // while (obj && (obj = obj.parentNode)) { if (obj == elem) { return; } } + // fns.cancel(evt); + // } + // } + return l; + } + + if (typeof Gala.CONTACT_MODE == 'undefined') { + var contactInit = function (evt, newListeners, mode) { + if (inited) { return; } + Gala.CONTACT_MODE = Gala.CONTACT_MODE || mode; + if (Gala.CONTACT_MODE != mode) { return; } + Gala.replaceGroup(elem, listeners, newListeners, useCapture); + if (typeof initCallback == 'function') { initCallback(listeners); } + if (listeners[evt.type]) { listeners[evt.type](evt); } + inited = true; + } + var touchInit = function (evt) { + contactInit(evt, touchListeners(), 'touch'); + } + var mouseInit = function (evt) { + contactInit(evt, mouseListeners(), 'mouse'); + } + listeners = { + 'touchstart': touchInit, + 'touchmove': touchInit, + 'touchend': touchInit, + 'touchcancel': touchInit, + 'mousedown': mouseInit, + 'mousemove': mouseInit, + 'mouseup': mouseInit, + 'mouseout': mouseInit + } + } else if (Gala.CONTACT_MODE == 'touch') { + listeners = touchListeners(); + } else if (Gala.CONTACT_MODE == 'mouse') { + listeners = mouseListeners(); + } + + Gala.listenGroup(elem, listeners); + if (typeof initCallback == 'function') { initCallback(listeners); } + return listeners; +} + + +// The Gala.Cursor object provides more detail coordinates for the contact +// event, and normalizes differences between touch and mouse coordinates. +// +// If you have a contact event listener, you can get the coordinates for it +// with: +// +// var cursor = new Gala.Cursor(evt); +// +Gala.Cursor = function (evt) { + var API = { constructor: Gala.Cursor } + + + function initialize() { + var ci = + evt.type.indexOf('mouse') == 0 ? evt : + ['touchstart', 'touchmove'].indexOf(evt.type) >= 0 ? evt.targetTouches[0] : + ['touchend', 'touchcancel'].indexOf(evt.type) >= 0 ? evt.changedTouches[0] : + null; + + // Basic coordinates (provided by the event). + API.pageX = ci.pageX; + API.pageY = ci.pageY; + API.clientX = ci.clientX; + API.clientY = ci.clientY; + API.screenX = ci.screenX; + API.screenY = ci.screenY; + + // Coordinates relative to the target element for the event. + var tgt = API.target = evt.target || evt.srcElement; + while (tgt.nodeType != 1 && tgt.parentNode) { tgt = tgt.parentNode; } + assignOffsetFor(tgt, 'offset'); + + // Coordinates relative to the element that the event was registered on. + var registrant = evt.currentTarget; + if (registrant && typeof registrant.offsetLeft != 'undefined') { + assignOffsetFor(registrant, 'registrant'); + } + } + + + function assignOffsetFor(elem, attr) { + var r; + if (elem.getBoundingClientRect) { + var er = elem.getBoundingClientRect(); + var dr = document.documentElement.getBoundingClientRect(); + r = { left: er.left - dr.left, top: er.top - dr.top } + } else { + r = { left: elem.offsetLeft, top: elem.offsetTop } + while (elem = elem.offsetParent) { + if (elem.offsetLeft || elem.offsetTop) { + r.left += elem.offsetLeft; + r.top += elem.offsetTop; + } + } + } + API[attr+'X'] = API.pageX - r.left; + API[attr+'Y'] = API.pageY - r.top; + } + + + initialize(); + + return API; +} + + +// A little utility to dereference ids into elements. You've seen this before. +// +Gala.$ = function (elem) { + if (typeof elem == 'string') { elem = document.getElementById(elem); } + return elem; +} + + + +// CONSTANTS +// +Gala.TAPPING_CLASS = 'tapping'; +Gala.IE_REGISTRATIONS = {} +Gala.IE_INVOCATION_QUEUE = [] +; +// A shortcut for creating a bookdata object from a 'data' hash. +// +// eg: +// +// Monocle.bookData({ components: ['intro.html', 'ch1.html', 'ch2.html'] }); +// +// All keys in the 'data' hash are optional: +// +// components: must be an array of component urls +// chapters: must be an array of nested chapters (the usual bookdata structure) +// metadata: must be a hash of key/values +// getComponentFn: override the default way to fetch components via id +// +Monocle.bookData = function (data) { + return { + getComponents: function () { + return data.components || ['anonymous']; + }, + getContents: function () { + return data.chapters || []; + }, + getComponent: data.getComponent || function (id) { + return { url: id } + }, + getMetaData: function (key) { + return (data.metadata || {})[key]; + }, + data: data + } +} + + +// A shortcut for creating a bookdata object from an array of element ids. +// +// eg: +// +// Monocle.bookDataFromIds(['part1', 'part2']); +// +Monocle.bookDataFromIds = function (elementIds) { + return Monocle.bookData({ + components: elementIds, + getComponent: function (cmptId) { + return { nodes: [document.getElementById(cmptId)] } + } + }); +} + + +// A shortcut for creating a bookdata object from an array of nodes. +// +// eg: +// +// Monocle.bookDataFromNodes([document.getElementById('content')]); +// +Monocle.bookDataFromNodes = function (nodes) { + return Monocle.bookData({ + getComponent: function (n) { return { 'nodes': nodes }; } + }); +} +; +Monocle.Factory = function (element, label, index, reader) { + + var API = { constructor: Monocle.Factory }; + var k = API.constants = API.constructor; + var p = API.properties = { + element: element, + label: label, + index: index, + reader: reader, + prefix: reader.properties.classPrefix || '' + } + + + // If index is null, uses the first available slot. If index is not null and + // the slot is not free, throws an error. + // + function initialize() { + if (!p.label) { return; } + // Append the element to the reader's graph of DOM elements. + var node = p.reader.properties.graph; + node[p.label] = node[p.label] || []; + if (typeof p.index == 'undefined' && node[p.label][p.index]) { + throw('Element already exists in graph: '+p.label+'['+p.index+']'); + } else { + p.index = p.index || node[p.label].length; + } + node[p.label][p.index] = p.element; + + // Add the label as a class name. + addClass(p.label); + } + + + // Finds an element that has been created in the context of the current + // reader, with the given label. If oIndex is not provided, returns first. + // If oIndex is provided (eg, n), returns the nth element with the label. + // + function find(oLabel, oIndex) { + if (!p.reader.properties.graph[oLabel]) { + return null; + } + return p.reader.properties.graph[oLabel][oIndex || 0]; + } + + + // Takes an elements and assimilates it into the reader -- essentially + // giving it a "dom" object of it's own. It will then be accessible via find. + // + // Note that (as per comments for initialize), if oIndex is provided and + // there is no free slot in the array for this label at that index, an + // error will be thrown. + // + function claim(oElement, oLabel, oIndex) { + return oElement.dom = new Monocle.Factory( + oElement, + oLabel, + oIndex, + p.reader + ); + } + + + // Create an element with the given label. + // + // The last argument (whether third or fourth) is the options hash. Your + // options are: + // + // class - the classname for the element. Must only be one name. + // html - the innerHTML for the element. + // text - the innerText for the element (an alternative to html, simpler). + // + // Returns the created element. + // + function make(tagName, oLabel, index_or_options, or_options) { + var oIndex, options; + if (arguments.length == 1) { + oLabel = null, + oIndex = 0; + options = {}; + } else if (arguments.length == 2) { + oIndex = 0; + options = {}; + } else if (arguments.length == 4) { + oIndex = arguments[2]; + options = arguments[3]; + } else if (arguments.length == 3) { + var lastArg = arguments[arguments.length - 1]; + if (typeof lastArg == "number") { + oIndex = lastArg; + options = {}; + } else { + oIndex = 0; + options = lastArg; + } + } + + var oElement = document.createElement(tagName); + claim(oElement, oLabel, oIndex); + if (options['class']) { + oElement.className += " "+p.prefix+options['class']; + } + if (options['html']) { + oElement.innerHTML = options['html']; + } + if (options['text']) { + oElement.appendChild(document.createTextNode(options['text'])); + } + + return oElement; + } + + + // Creates an element by passing all the given arguments to make. Then + // appends the element as a child of the current element. + // + function append(tagName, oLabel, index_or_options, or_options) { + var oElement = make.apply(this, arguments); + p.element.appendChild(oElement); + return oElement; + } + + + // Returns an array of [label, index, reader] for the given element. + // A simple way to introspect the arguments required for #find, for eg. + // + function address() { + return [p.label, p.index, p.reader]; + } + + + // Apply a set of style rules (hash or string) to the current element. + // See Monocle.Styles.applyRules for more info. + // + function setStyles(rules) { + return Monocle.Styles.applyRules(p.element, rules); + } + + + function setBetaStyle(property, value) { + return Monocle.Styles.affix(p.element, property, value); + } + + + // ClassName manipulation functions - with thanks to prototype.js! + + // Returns true if one of the current element's classnames matches name -- + // classPrefix aware (so don't concate the prefix onto it). + // + function hasClass(name) { + name = p.prefix + name; + var klass = p.element.className; + if (!klass) { return false; } + if (klass == name) { return true; } + return new RegExp("(^|\\s)"+name+"(\\s|$)").test(klass); + } + + + // Adds name to the classnames of the current element (prepending the + // reader's classPrefix first). + // + function addClass(name) { + if (hasClass(name)) { return; } + var gap = p.element.className ? ' ' : ''; + return p.element.className += gap+p.prefix+name; + } + + + // Removes (classPrefix+)name from the classnames of the current element. + // + function removeClass(name) { + var reName = new RegExp("(^|\\s+)"+p.prefix+name+"(\\s+|$)"); + var reTrim = /^\s+|\s+$/g; + var klass = p.element.className; + p.element.className = klass.replace(reName, ' ').replace(reTrim, ''); + return p.element.className; + } + + + API.find = find; + API.claim = claim; + API.make = make; + API.append = append; + API.address = address; + + API.setStyles = setStyles; + API.setBetaStyle = setBetaStyle; + API.hasClass = hasClass; + API.addClass = addClass; + API.removeClass = removeClass; + + initialize(); + + return API; +} +; +Monocle.Events = {}; + + +Monocle.Events.wrapper = function (fn) { + return function (evt) { evt.m = new Gala.Cursor(evt); fn(evt); } +} + + +Monocle.Events.listen = Gala.listen; + + +Monocle.Events.deafen = Gala.deafen; + + +Monocle.Events.dispatch = Gala.dispatch; + + +Monocle.Events.listenForTap = function (elem, fn, tapClass) { + return Gala.onTap(elem, Monocle.Events.wrapper(fn), tapClass); +} + + +Monocle.Events.deafenForTap = Gala.deafenGroup; + + +Monocle.Events.listenForContact = function (elem, fns, options) { + options = options || { useCapture: false }; + var wrappers = {}; + for (evtType in fns) { + wrappers[evtType] = Monocle.Events.wrapper(fns[evtType]); + } + return Gala.onContact(elem, wrappers, options.useCapture); +} + + +Monocle.Events.deafenForContact = Gala.deafenGroup; + + +// Listen for the next transition-end event on the given element, call +// the function, then deafen. +// +// Returns a function that can be used to cancel the listen early. +// +Monocle.Events.afterTransition = function (elem, fn) { + var evtName = "transitionend"; + if (Monocle.Browser.is.WebKit) { + evtName = 'webkitTransitionEnd'; + } else if (Monocle.Browser.is.Opera) { + evtName = 'oTransitionEnd'; + } + var l = null, cancel = null; + l = function () { fn(); cancel(); } + cancel = function () { Monocle.Events.deafen(elem, evtName, l); } + Monocle.Events.listen(elem, evtName, l); + return cancel; +} +; +Monocle.Styles = { + + // Takes a hash and returns a string. + rulesToString: function (rules) { + if (typeof rules != 'string') { + var parts = []; + for (var declaration in rules) { + parts.push(declaration+": "+rules[declaration]+";") + } + rules = parts.join(" "); + } + return rules; + }, + + + // Takes a hash or string of CSS property assignments and applies them + // to the element. + // + applyRules: function (elem, rules) { + rules = Monocle.Styles.rulesToString(rules); + elem.style.cssText += ';'+rules; + return elem.style.cssText; + }, + + + // Generates cross-browser properties for a given property. + // ie, affix(, 'transition', 'linear 100ms') would apply that value + // to webkitTransition for WebKit browsers, and to MozTransition for Gecko. + // + affix: function (elem, property, value) { + var target = elem.style ? elem.style : elem; + var props = Monocle.Browser.css.toDOMProps(property); + while (props.length) { target[props.shift()] = value; } + }, + + + setX: function (elem, x) { + var s = elem.style; + if (typeof x == "number") { x += "px"; } + var val = Monocle.Browser.env.supportsTransform3d ? + 'translate3d('+x+', 0, 0)' : + 'translateX('+x+')'; + val = (x == '0px') ? 'none' : val; + s.webkitTransform = s.MozTransform = s.OTransform = s.transform = val; + return x; + }, + + + setY: function (elem, y) { + var s = elem.style; + if (typeof y == "number") { y += "px"; } + var val = Monocle.Browser.env.supportsTransform3d ? + 'translate3d(0, '+y+', 0)' : + 'translateY('+y+')'; + val = (y == '0px') ? 'none' : val; + s.webkitTransform = s.MozTransform = s.OTransform = s.transform = val; + return y; + }, + + + getX: function (elem) { + var currStyle = document.defaultView.getComputedStyle(elem, null); + var re = /matrix\([^,]+,[^,]+,[^,]+,[^,]+,\s*([^,]+),[^\)]+\)/; + var props = Monocle.Browser.css.toDOMProps('transform'); + var matrix = null; + while (props.length && !matrix) { + matrix = currStyle[props.shift()]; + } + return parseInt(matrix.match(re)[1]); + }, + + + transitionFor: function (elem, prop, duration, timing, delay) { + var tProps = Monocle.Browser.css.toDOMProps('transition'); + var pProps = Monocle.Browser.css.toCSSProps(prop); + timing = timing || "linear"; + delay = (delay || 0)+"ms"; + for (var i = 0, ii = tProps.length; i < ii; ++i) { + var t = "none"; + if (duration) { + t = [pProps[i], duration+"ms", timing, delay].join(" "); + } + elem.style[tProps[i]] = t; + } + } + +} + + +// These rule definitions are more or less compulsory for Monocle to behave +// as expected. Which is why they appear here and not in the stylesheet. +// Adjust them if you know what you're doing. +// +Monocle.Styles.container = { + "position": "absolute", + "overflow": "hidden", + "top": "0", + "left": "0", + "bottom": "0", + "right": "0" +} + +Monocle.Styles.page = { + "position": "absolute", + "z-index": "1", + "-webkit-user-select": "none", + "-moz-user-select": "none", + "-ms-user-select": "none", + "user-select": "none", + "-webkit-transform": "translate3d(0,0,0)", + "visibility": "visible" + + /* + "background": "white", + "top": "0", + "left": "0", + "bottom": "0", + "right": "0" + */ +} + +Monocle.Styles.sheaf = { + "position": "absolute", + "overflow": "hidden" + + /* + "top": "0", + "left": "0", + "bottom": "0", + "right": "0" + */ +} + +Monocle.Styles.component = { + "width": "100%", + "height": "100%", + "border": "none", + "-webkit-user-select": "none", + "-moz-user-select": "none", + "-ms-user-select": "none", + "user-select": "none" +} + +Monocle.Styles.control = { + "z-index": "100", + "cursor": "pointer" +} + +Monocle.Styles.overlay = { + "position": "absolute", + "display": "none", + "width": "100%", + "height": "100%", + "z-index": "1000" +} +; +Monocle.Formatting = function (reader, optStyles, optScale) { + var API = { constructor: Monocle.Formatting }; + var k = API.constants = API.constructor; + var p = API.properties = { + reader: reader, + + // An array of style rules that are automatically applied to every page. + stylesheets: [], + + // A multiplier on the default font-size of each element in every + // component. If null, the multiplier is not applied (or it is removed). + fontScale: null + } + + + function initialize() { + p.fontScale = optScale; + clampStylesheets(optStyles); + p.reader.listen('monocle:componentmodify', persistOnComponentChange); + } + + + // Clamp page frames to a set of styles that reduce Monocle breakage. + // + function clampStylesheets(implStyles) { + var defCSS = k.DEFAULT_STYLE_RULES; + if (Monocle.Browser.env.floatsIgnoreColumns) { + defCSS.push("html#RS\\:monocle * { float: none !important; }"); + } + p.defaultStyles = addPageStyles(defCSS, false); + if (implStyles) { + p.initialStyles = addPageStyles(implStyles, false); + } + } + + + function persistOnComponentChange(evt) { + var doc = evt.m['document']; + doc.documentElement.id = p.reader.properties.systemId; + adjustFontScaleForDoc(doc, p.fontScale); + for (var i = 0; i < p.stylesheets.length; ++i) { + if (p.stylesheets[i]) { + addPageStylesheet(doc, i); + } + } + } + + + /* PAGE STYLESHEETS */ + + // API for adding a new stylesheet to all components. styleRules should be + // a string of CSS rules. restorePlace defaults to true. + // + // Returns a sheet index value that can be used with updatePageStyles + // and removePageStyles. + // + function addPageStyles(styleRules, restorePlace) { + return changingStylesheet(function () { + p.stylesheets.push(styleRules); + var sheetIndex = p.stylesheets.length - 1; + + var i = 0, cmpt = null; + while (cmpt = p.reader.dom.find('component', i++)) { + addPageStylesheet(cmpt.contentDocument, sheetIndex); + } + return sheetIndex; + }, restorePlace); + } + + + // API for updating the styleRules in an existing page stylesheet across + // all components. Takes a sheet index value obtained via addPageStyles. + // + function updatePageStyles(sheetIndex, styleRules, restorePlace) { + return changingStylesheet(function () { + p.stylesheets[sheetIndex] = styleRules; + if (typeof styleRules.join == "function") { + styleRules = styleRules.join("\n"); + } + + var i = 0, cmpt = null; + while (cmpt = p.reader.dom.find('component', i++)) { + var doc = cmpt.contentDocument; + var styleTag = doc.getElementById('monStylesheet'+sheetIndex); + if (!styleTag) { + console.warn('No such stylesheet: ' + sheetIndex); + return; + } + if (styleTag.styleSheet) { + styleTag.styleSheet.cssText = styleRules; + } else { + styleTag.replaceChild( + doc.createTextNode(styleRules), + styleTag.firstChild + ); + } + } + }, restorePlace); + } + + + // API for removing a page stylesheet from all components. Takes a sheet + // index value obtained via addPageStyles. + // + function removePageStyles(sheetIndex, restorePlace) { + return changingStylesheet(function () { + p.stylesheets[sheetIndex] = null; + var i = 0, cmpt = null; + while (cmpt = p.reader.dom.find('component', i++)) { + var doc = cmpt.contentDocument; + var styleTag = doc.getElementById('monStylesheet'+sheetIndex); + styleTag.parentNode.removeChild(styleTag); + } + }, restorePlace); + } + + + // Wraps all API-based stylesheet changes (add, update, remove) in a + // brace of custom events (stylesheetchanging/stylesheetchange), and + // recalculates component dimensions if specified (default to true). + // + function changingStylesheet(callback, restorePlace) { + restorePlace = (restorePlace === false) ? false : true; + if (restorePlace) { + dispatchChanging(); + } + var result = callback(); + if (restorePlace) { + p.reader.recalculateDimensions(true); + Monocle.defer(dispatchChange); + } else { + p.reader.recalculateDimensions(false); + } + return result; + } + + + function dispatchChanging() { + p.reader.dispatchEvent("monocle:stylesheetchanging", {}); + } + + + function dispatchChange() { + p.reader.dispatchEvent("monocle:stylesheetchange", {}); + } + + + // Private method for adding a stylesheet to a component. Used by + // addPageStyles. + // + function addPageStylesheet(doc, sheetIndex) { + var styleRules = p.stylesheets[sheetIndex]; + + if (!styleRules) { + return; + } + + if (!doc || !doc.documentElement) { + return; + } + + var head = doc.getElementsByTagName('head')[0]; + if (!head) { + head = doc.createElement('head'); + doc.documentElement.appendChild(head); + } + + if (typeof styleRules.join == "function") { + styleRules = styleRules.join("\n"); + } + + var styleTag = doc.createElement('style'); + styleTag.type = 'text/css'; + styleTag.id = "monStylesheet"+sheetIndex; + if (styleTag.styleSheet) { + styleTag.styleSheet.cssText = styleRules; + } else { + styleTag.appendChild(doc.createTextNode(styleRules)); + } + + head.appendChild(styleTag); + + return styleTag; + } + + + /* FONT SCALING */ + + function setFontScale(scale, restorePlace) { + p.fontScale = scale; + if (restorePlace) { + dispatchChanging(); + } + var i = 0, cmpt = null; + while (cmpt = p.reader.dom.find('component', i++)) { + adjustFontScaleForDoc(cmpt.contentDocument, scale); + } + if (restorePlace) { + p.reader.recalculateDimensions(true); + dispatchChange(); + } else { + p.reader.recalculateDimensions(false); + } + } + + + function adjustFontScaleForDoc(doc, scale) { + var elems = doc.getElementsByTagName('*'); + if (scale) { + scale = parseFloat(scale); + if (!doc.body.pfsSwept) { + sweepElements(doc, elems); + } + + // Iterate over each element, applying scale to the original + // font-size. If a proportional font sizing is already applied to + // the element, update existing cssText, otherwise append new cssText. + // + for (var j = 0, jj = elems.length; j < jj; ++j) { + var newFs = fsProperty(elems[j].pfsOriginal, scale); + if (elems[j].pfsApplied) { + replaceFontSizeInStyle(elems[j], newFs); + } else { + elems[j].style.cssText += newFs; + } + elems[j].pfsApplied = scale; + } + } else if (doc.body.pfsSwept) { + // Iterate over each element, removing proportional font-sizing flag + // and property from cssText. + for (var j = 0, jj = elems.length; j < jj; ++j) { + if (elems[j].pfsApplied) { + var oprop = elems[j].pfsOriginalProp; + var opropDec = oprop ? 'font-size: '+oprop+' ! important;' : ''; + replaceFontSizeInStyle(elems[j], opropDec); + elems[j].pfsApplied = null; + } + } + + // Establish new baselines in case classes have changed. + sweepElements(doc, elems); + } + } + + + function sweepElements(doc, elems) { + // Iterate over each element, looking at its font size and storing + // the original value against the element. + for (var i = 0, ii = elems.length; i < ii; ++i) { + var currStyle = doc.defaultView.getComputedStyle(elems[i], null); + var fs = parseFloat(currStyle.getPropertyValue('font-size')); + elems[i].pfsOriginal = fs; + elems[i].pfsOriginalProp = elems[i].style.fontSize; + } + doc.body.pfsSwept = true; + } + + + function fsProperty(orig, scale) { + return 'font-size: '+(orig*scale)+'px ! important;'; + } + + + function replaceFontSizeInStyle(elem, newProp) { + var lastFs = /font-size:[^;]/ + elem.style.cssText = elem.style.cssText.replace(lastFs, newProp); + } + + + API.addPageStyles = addPageStyles; + API.updatePageStyles = updatePageStyles; + API.removePageStyles = removePageStyles; + API.setFontScale = setFontScale; + + initialize(); + + return API; +} + + + +Monocle.Formatting.DEFAULT_STYLE_RULES = [ + "html#RS\\:monocle * {" + + "-webkit-font-smoothing: subpixel-antialiased;" + + "text-rendering: auto !important;" + + "word-wrap: break-word !important;" + + "overflow: visible !important;" + + "}", + "html#RS\\:monocle body {" + + "margin: 0 !important;"+ + "border: none !important;" + + "padding: 0 !important;" + + "width: 100% !important;" + + "position: absolute !important;" + + "-webkit-text-size-adjust: none;" + + "}", + "html#RS\\:monocle body * {" + + "max-width: 100% !important;" + + "}", + "html#RS\\:monocle img, html#RS\\:monocle video, html#RS\\:monocle object, html#RS\\:monocle svg {" + + "max-height: 95% !important;" + + "height: auto !important;" + + "}" +] +; +// READER +// +// +// The full DOM hierarchy created by Reader is: +// +// box +// -> container +// -> pages (the number of page elements is determined by the flipper) +// -> sheaf (basically just sets the margins) +// -> component (an iframe created by the current component) +// -> body (the document.body of the iframe) +// -> page controls +// -> standard controls +// -> overlay +// -> modal/popover controls +// +// +// Options: +// +// flipper: The class of page flipper to use. +// +// panels: The class of panels to use +// +// stylesheet: A string of CSS rules to apply to the contents of each +// component loaded into the reader. +// +// fontScale: a float to multiply against the default font-size of each +// element in each component. +// +// place: A book locus for the page to open to when the reader is +// initialized. (See comments at Book#pageNumberAt for more about +// the locus option). +// +// systemId: the id for root elements of components, defaults to "RS:monocle" +// +Monocle.Reader = function (node, bookData, options, onLoadCallback) { + + var API = { constructor: Monocle.Reader } + var k = API.constants = API.constructor; + var p = API.properties = { + // Initialization-completed flag. + initialized: false, + + // The active book. + book: null, + + // DOM graph of factory-generated objects. + graph: {}, + + // Id applied to the HTML element of each component, can be used to scope + // CSS rules. + systemId: (options ? options.systemId : null) || k.DEFAULT_SYSTEM_ID, + + // Prefix for classnames for any created element. + classPrefix: k.DEFAULT_CLASS_PREFIX, + + // Registered control objects (see addControl). Hashes of the form: + // { + // control: , + // elements: , + // controlType: + // } + controls: [], + + // After the reader has been resized, this resettable timer must expire + // the place is restored. + resizeTimer: null + } + + var dom; + + + // Inspects the browser environment and kicks off preparing the container. + // + function initialize() { + options = options || {} + + Monocle.Browser.survey(prepareBox); + } + + + // Sets up the container and internal elements. + // + function prepareBox() { + var box = node; + if (typeof box == "string") { box = document.getElementById(box); } + dom = API.dom = box.dom = new Monocle.Factory(box, 'box', 0, API); + + API.billboard = new Monocle.Billboard(API); + + if (!Monocle.Browser.env.isCompatible()) { + if (dispatchEvent("monocle:incompatible", {}, true)) { + fatalSystemMessage(k.COMPATIBILITY_INFO); + } + return; + } + + dispatchEvent("monocle:initializing", API); + + bookData = bookData || Monocle.bookDataFromNodes([box.cloneNode(true)]); + var bk = new Monocle.Book(bookData, options.preloadWindow || 1); + + box.innerHTML = ""; + + // Make sure the box div is absolutely or relatively positioned. + positionBox(); + + // Attach the page-flipping gadget. + attachFlipper(options.flipper); + + // Create the essential DOM elements. + createReaderElements(); + + // Create the selection object. + API.selection = new Monocle.Selection(API); + + // Create the formatting object. + API.formatting = new Monocle.Formatting( + API, + options.stylesheet, + options.fontScale + ); + + primeFrames(options.primeURL, function () { + // Make the reader elements look pretty. + applyStyles(); + + p.flipper.listenForInteraction(options.panels); + + setBook(bk, options.place, function () { + if (onLoadCallback) { onLoadCallback(API); } + dispatchEvent("monocle:loaded", API); + }); + }); + } + + + function positionBox() { + var currPosVal; + var box = dom.find('box'); + if (document.defaultView) { + var currStyle = document.defaultView.getComputedStyle(box, null); + currPosVal = currStyle.getPropertyValue('position'); + } else if (box.currentStyle) { + currPosVal = box.currentStyle.position + } + if (["absolute", "relative"].indexOf(currPosVal) == -1) { + box.style.position = "relative"; + } + } + + + function attachFlipper(flipperClass) { + if (!flipperClass) { + if (Monocle.Browser.renders.slow) { + flipperClass = Monocle.Flippers.Instant; + } else { + flipperClass = Monocle.Flippers.Slider; + } + } + + p.flipper = new flipperClass(API, null, p.readerOptions); + } + + + function createReaderElements() { + var cntr = dom.append('div', 'container'); + for (var i = 0; i < p.flipper.pageCount; ++i) { + var page = cntr.dom.append('div', 'page', i); + page.style.visibility = "hidden"; + page.m = { reader: API, pageIndex: i, place: null } + page.m.sheafDiv = page.dom.append('div', 'sheaf', i); + page.m.activeFrame = page.m.sheafDiv.dom.append('iframe', 'component', i); + page.m.activeFrame.m = { 'pageDiv': page }; + page.m.activeFrame.setAttribute('frameBorder', 0); + page.m.activeFrame.setAttribute('scrolling', 'no'); + p.flipper.addPage(page); + } + dom.append('div', 'overlay'); + dispatchEvent("monocle:loading", API); + } + + + // Opens the frame to a particular URL (usually 'about:blank'). + // + function primeFrames(url, callback) { + url = url || (Monocle.Browser.on.UIWebView ? "blank.html" : "about:blank"); + + var pageCount = 0; + + var cb = function (evt) { + var frame = evt.target || evt.srcElement; + Monocle.Events.deafen(frame, 'load', cb); + dispatchEvent( + 'monocle:frameprimed', + { frame: frame, pageIndex: pageCount } + ); + if ((pageCount += 1) == p.flipper.pageCount) { + Monocle.defer(callback); + } + } + + forEachPage(function (page) { + Monocle.Events.listen(page.m.activeFrame, 'load', cb); + page.m.activeFrame.src = url; + }); + } + + + function applyStyles() { + dom.find('container').dom.setStyles(Monocle.Styles.container); + forEachPage(function (page, i) { + page.dom.setStyles(Monocle.Styles.page); + dom.find('sheaf', i).dom.setStyles(Monocle.Styles.sheaf); + var cmpt = dom.find('component', i) + cmpt.dom.setStyles(Monocle.Styles.component); + }); + lockFrameWidths(); + dom.find('overlay').dom.setStyles(Monocle.Styles.overlay); + dispatchEvent('monocle:styles'); + } + + + function lockingFrameWidths() { + if (!Monocle.Browser.env.relativeIframeExpands) { return; } + for (var i = 0, cmpt; cmpt = dom.find('component', i); ++i) { + cmpt.style.display = "none"; + } + } + + + function lockFrameWidths() { + if (!Monocle.Browser.env.relativeIframeExpands) { return; } + for (var i = 0, cmpt; cmpt = dom.find('component', i); ++i) { + cmpt.style.width = cmpt.parentNode.offsetWidth+"px"; + cmpt.style.display = "block"; + } + } + + + // Apply the book, move to a particular place or just the first page, wait + // for everything to complete, then fire the callback. + // + function setBook(bk, place, callback) { + p.book = bk; + var pageCount = 0; + if (typeof callback == 'function') { + var watchers = { + 'monocle:componentchange': function (evt) { + dispatchEvent('monocle:firstcomponentchange', evt.m); + return (pageCount += 1) == p.flipper.pageCount; + }, + 'monocle:componentfailed': function (evt) { + fatalSystemMessage(k.LOAD_FAILURE_INFO); + return true; + }, + 'monocle:turn': function (evt) { + deafen('monocle:componentfailed', listener); + callback(); + return true; + } + } + var listener = function (evt) { + if (watchers[evt.type](evt)) { deafen(evt.type, listener); } + } + for (evtType in watchers) { listen(evtType, listener) } + } + p.flipper.moveTo(place || { page: 1 }, initialized); + } + + + function getBook() { + return p.book; + } + + + function initialized() { + p.initialized = true; + } + + + // Attempts to restore the place we were up to in the book before the + // reader was resized. + // + // The delay ensures that if we get multiple calls to this function in + // a short period, we don't do lots of expensive recalculations. + // + function resized() { + if (!p.initialized) { + console.warn('Attempt to resize book before initialization.'); + } + lockingFrameWidths(); + if (!dispatchEvent("monocle:resizing", {}, true)) { + return; + } + clearTimeout(p.resizeTimer); + p.resizeTimer = Monocle.defer(performResize, k.RESIZE_DELAY); + } + + + function performResize() { + lockFrameWidths(); + recalculateDimensions(true, afterResized); + } + + + function afterResized() { + dispatchEvent('monocle:resize'); + } + + + function recalculateDimensions(andRestorePlace, callback) { + if (!p.book) { return; } + dispatchEvent("monocle:recalculating"); + + var place, locus; + if (andRestorePlace !== false) { + var place = getPlace(); + var locus = { percent: place ? place.percentageThrough() : 0 }; + } + + forEachPage(function (pageDiv) { + pageDiv.m.activeFrame.m.component.updateDimensions(pageDiv); + }); + + var cb = function () { + dispatchEvent("monocle:recalculated"); + Monocle.defer(callback); + } + Monocle.defer(function () { locus ? p.flipper.moveTo(locus, cb) : cb; }); + } + + + // Returns the current page number in the book. + // + // The pageDiv argument is optional - typically defaults to whatever the + // flipper thinks is the "active" page. + // + function pageNumber(pageDiv) { + var place = getPlace(pageDiv); + return place ? (place.pageNumber() || 1) : 1; + } + + + // Returns the current "place" in the book -- ie, the page number, chapter + // title, etc. + // + // The pageDiv argument is optional - typically defaults to whatever the + // flipper thinks is the "active" page. + // + function getPlace(pageDiv) { + if (!p.initialized) { + console.warn('Attempt to access place before initialization.'); + } + return p.flipper.getPlace(pageDiv); + } + + + // Moves the current page as specified by the locus. See + // Monocle.Book#pageNumberAt for documentation on the locus argument. + // + // The callback argument is optional. + // + function moveTo(locus, callback) { + if (!p.initialized) { + console.warn('Attempt to move place before initialization.'); + } + if (!p.book.isValidLocus(locus)) { + dispatchEvent( + "monocle:notfound", + { href: locus ? locus.componentId : "anonymous" } + ); + return false; + } + var fn = callback; + if (!locus.direction) { + dispatchEvent('monocle:jumping', { locus: locus }); + fn = function () { + dispatchEvent('monocle:jump', { locus: locus }); + if (callback) { callback(); } + } + } + p.flipper.moveTo(locus, fn); + return true; + } + + + // Moves to the relevant element in the relevant component. + // + function skipToChapter(src) { + var locus = p.book.locusOfChapter(src); + return moveTo(locus); + } + + + // Valid types: + // - standard (an overlay above the pages) + // - page (within the page) + // - modal (overlay where click-away does nothing, for a single control) + // - hud (overlay that multiple controls can share) + // - popover (overlay where click-away removes the ctrl elements) + // - invisible + // + // Options: + // - hidden -- creates and hides the ctrl elements; + // use showControl to show them + // - container -- specify an existing DOM element to contain the control. + // + function addControl(ctrl, cType, options) { + for (var i = 0; i < p.controls.length; ++i) { + if (p.controls[i].control == ctrl) { + console.warn("Already added control: %o", ctrl); + return; + } + } + + options = options || {}; + + var ctrlData = { control: ctrl, elements: [], controlType: cType } + p.controls.push(ctrlData); + + var addControlTo = function (cntr) { + if (cntr == 'container') { + cntr = options.container || dom.find('container'); + if (typeof cntr == 'string') { cntr = document.getElementById(cntr); } + if (!cntr.dom) { dom.claim(cntr, 'controlContainer'); } + } else if (cntr == 'overlay') { + cntr = dom.find('overlay'); + } + if (typeof ctrl.createControlElements != 'function') { return; } + var ctrlElem = ctrl.createControlElements(cntr); + if (!ctrlElem) { return; } + cntr.appendChild(ctrlElem); + ctrlData.elements.push(ctrlElem); + Monocle.Styles.applyRules(ctrlElem, Monocle.Styles.control); + return ctrlElem; + } + + if (!cType || cType == 'standard' || cType == 'invisible') { + addControlTo('container'); + } else if (cType == 'page') { + forEachPage(addControlTo); + } else if (cType == 'modal' || cType == 'popover' || cType == 'hud') { + addControlTo('overlay'); + ctrlData.usesOverlay = true; + } else if (cType == 'invisible') { + addControlTo('container'); + } else { + console.warn('Unknown control type: ' + cType); + } + + if (options.hidden) { + hideControl(ctrl); + } else { + showControl(ctrl); + } + + if (typeof ctrl.assignToReader == 'function') { + ctrl.assignToReader(API); + } + + return ctrl; + } + + + function dataForControl(ctrl) { + for (var i = 0; i < p.controls.length; ++i) { + if (p.controls[i].control == ctrl) { + return p.controls[i]; + } + } + } + + + function hideControl(ctrl) { + var controlData = dataForControl(ctrl); + if (!controlData) { + console.warn("No data for control: " + ctrl); + return; + } + if (controlData.hidden) { + return; + } + for (var i = 0; i < controlData.elements.length; ++i) { + controlData.elements[i].style.display = "none"; + } + if (controlData.usesOverlay) { + var overlay = dom.find('overlay'); + overlay.style.display = "none"; + Monocle.Events.deafenForContact(overlay, overlay.listeners); + if (controlData.controlType != 'hud') { + dispatchEvent('monocle:modal:off'); + } + } + controlData.hidden = true; + if (ctrl.properties) { + ctrl.properties.hidden = true; + } + dispatchEvent('monocle:controlhide', { control: ctrl }, false); + } + + + function showControl(ctrl) { + var controlData = dataForControl(ctrl); + if (!controlData) { + console.warn("No data for control: " + ctrl); + return false; + } + + if (showingControl(ctrl)) { + return false; + } + + var overlay = dom.find('overlay'); + if (controlData.usesOverlay && controlData.controlType != "hud") { + for (var i = 0, ii = p.controls.length; i < ii; ++i) { + if (p.controls[i].usesOverlay && !p.controls[i].hidden) { + return false; + } + } + overlay.style.display = "block"; + dispatchEvent('monocle:modal:on'); + } + + for (var i = 0; i < controlData.elements.length; ++i) { + controlData.elements[i].style.display = "block"; + } + + if (controlData.controlType == "popover") { + var onControl = function (evt) { + var obj = evt.target; + do { + if (obj == controlData.elements[0]) { return true; } + } while (obj && (obj = obj.parentNode)); + return false; + } + overlay.listeners = Monocle.Events.listenForContact( + overlay, + { + start: function (evt) { if (!onControl(evt)) { hideControl(ctrl); } }, + move: function (evt) { if (!onControl(evt)) { evt.preventDefault(); } } + } + ); + } + controlData.hidden = false; + if (ctrl.properties) { + ctrl.properties.hidden = false; + } + dispatchEvent('monocle:controlshow', { control: ctrl }, false); + return true; + } + + + function showingControl(ctrl) { + var controlData = dataForControl(ctrl); + return controlData.hidden == false; + } + + + function dispatchEvent(evtType, data, cancelable) { + return Monocle.Events.dispatch(dom.find('box'), evtType, data, cancelable); + } + + + function listen(evtType, fn, useCapture) { + Monocle.Events.listen(dom.find('box'), evtType, fn, useCapture); + } + + + function deafen(evtType, fn) { + Monocle.Events.deafen(dom.find('box'), evtType, fn); + } + + + function visiblePages() { + return p.flipper.visiblePages ? + p.flipper.visiblePages() : + [dom.find('page')]; + } + + + function forEachPage(callback) { + for (var i = 0, ii = p.flipper.pageCount; i < ii; ++i) { + var page = dom.find('page', i); + callback(page, i); + } + } + + + /* The Reader PageStyles API is deprecated - it has moved to Formatting */ + + function addPageStyles(styleRules, restorePlace) { + console.deprecation("Use reader.formatting.addPageStyles instead."); + return API.formatting.addPageStyles(styleRules, restorePlace); + } + + + function updatePageStyles(sheetIndex, styleRules, restorePlace) { + console.deprecation("Use reader.formatting.updatePageStyles instead."); + return API.formatting.updatePageStyles(sheetIndex, styleRules, restorePlace); + } + + + function removePageStyles(sheetIndex, restorePlace) { + console.deprecation("Use reader.formatting.removePageStyles instead."); + return API.formatting.removePageStyles(sheetIndex, restorePlace); + } + + + function fatalSystemMessage(msg) { + var info = dom.make('div', 'book_fatality', { html: msg }); + var box = dom.find('box'); + var bbOrigin = [box.offsetWidth / 2, box.offsetHeight / 2]; + API.billboard.show(info, { closeButton: false, from: bbOrigin }); + } + + + API.getBook = getBook; + API.getPlace = getPlace; + API.moveTo = moveTo; + API.skipToChapter = skipToChapter; + API.resized = resized; + API.recalculateDimensions = recalculateDimensions; + API.addControl = addControl; + API.hideControl = hideControl; + API.showControl = showControl; + API.showingControl = showingControl; + API.dispatchEvent = dispatchEvent; + API.listen = listen; + API.deafen = deafen; + API.visiblePages = visiblePages; + + // Deprecated! + API.addPageStyles = addPageStyles; + API.updatePageStyles = updatePageStyles; + API.removePageStyles = removePageStyles; + + initialize(); + + return API; +} + + +Monocle.Reader.RESIZE_DELAY = Monocle.Browser.renders.slow ? 500 : 100; +Monocle.Reader.DEFAULT_SYSTEM_ID = 'RS:monocle' +Monocle.Reader.DEFAULT_CLASS_PREFIX = 'monelem_' +Monocle.Reader.DEFAULT_STYLE_RULES = Monocle.Formatting.DEFAULT_STYLE_RULES; +Monocle.Reader.COMPATIBILITY_INFO = + "

    Incompatible browser

    "+ + "

    Unfortunately, your browser isn't able to display this book. "+ + "If possible, try again in another browser or on another device.

    "; +Monocle.Reader.LOAD_FAILURE_INFO = + "

    Book could not be loaded

    "+ + "

    Sorry, parts of the book could not be retrieved.
    "+ + "Please check your connection and refresh to try again.

    "; +/* BOOK */ + +/* The Book handles movement through the content by the reader page elements. + * + * It's responsible for instantiating components as they are required, + * and for calculating which component and page number to move to (based on + * requests from the Reader). + * + */ + +Monocle.Book = function (dataSource, preloadWindow) { + + var API = { constructor: Monocle.Book } + var k = API.constants = API.constructor; + var p = API.properties = { + dataSource: dataSource, + preloadWindow: preloadWindow, + cmptLoadQueue: {}, + components: [], + chapters: {} // flat arrays of chapters per component + } + + + function initialize() { + p.componentIds = dataSource.getComponents(); + p.contents = dataSource.getContents(); + p.lastCIndex = p.componentIds.length - 1; + } + + + // Adjusts the given locus object to provide the page number within the + // current component. + // + // If the locus implies movement to another component, the locus + // 'componentId' property will be updated to point to this component, and + // the 'load' property will be set to true, which should be taken as a + // sign to call loadPageAt with a callback. + // + // The locus argument is an object that has one of the following properties: + // + // - page: positive integer. Counting up from the start of component. + // - pagesBack: negative integer. Counting back from the end of component. + // - percent: float indicating percentage through the component + // - direction: integer relative to the current page number for this pageDiv + // - position: string, one of "start" or "end", moves to corresponding point + // in the given component + // - anchor: an element id within the component + // - xpath: the node at this XPath within the component + // - selector: the first node at this CSS selector within the component + // + // The locus object can also specify a componentId. If it is not provided + // we default to the currently active component, and if that doesn't exist, + // we default to the very first component. + // + // The locus result will be an object with the following properties: + // + // - load: boolean, true if loading component required, false otherwise + // - componentId: component to load (current componentId if load is false) + // - if load is false: + // - page + // - if load is true: + // - one of page / pagesBack / percent / direction / position / anchor + // + function pageNumberAt(pageDiv, locus) { + locus.load = false; + var currComponent = pageDiv.m.activeFrame ? + pageDiv.m.activeFrame.m.component : + null; + var component = null; + var cIndex = p.componentIds.indexOf(locus.componentId); + if (cIndex < 0 && !currComponent) { + // No specified component, no current component. Load first component. + locus.load = true; + locus.componentId = p.componentIds[0]; + return locus; + } else if ( + cIndex < 0 && + locus.componentId && + currComponent.properties.id != locus.componentId + ) { + // Invalid component, say not found. + pageDiv.m.reader.dispatchEvent( + "monocle:notfound", + { href: locus.componentId } + ); + return null; + } else if (cIndex < 0) { + // No specified (or invalid) component, use current component. + component = currComponent; + locus.componentId = pageDiv.m.activeFrame.m.component.properties.id; + cIndex = p.componentIds.indexOf(locus.componentId); + } else if (!p.components[cIndex] || p.components[cIndex] != currComponent) { + // Specified component differs from current component. Load specified. + locus.load = true; + return locus; + } else { + component = currComponent; + } + + // If we're here, then the locus is based on the current component. + var result = { load: false, componentId: locus.componentId, page: 1 } + + // Get the current last page. + lastPageNum = component.lastPageNumber(); + + // Deduce the page number for the given locus. + if (typeof(locus.page) == "number") { + result.page = locus.page; + } else if (typeof(locus.pagesBack) == "number") { + result.page = lastPageNum + locus.pagesBack; + } else if (typeof(locus.percent) == "number") { + var place = new Monocle.Place(); + place.setPlace(component, 1); + result.page = place.pageAtPercentageThrough(locus.percent); + } else if (typeof(locus.direction) == "number") { + if (!pageDiv.m.place) { + console.warn("Can't move in a direction if pageDiv has no place."); + } + result.page = pageDiv.m.place.pageNumber(); + result.page += locus.direction; + } else if (typeof(locus.anchor) == "string") { + result.page = component.pageForChapter(locus.anchor, pageDiv); + } else if (typeof(locus.xpath) == "string") { + result.page = component.pageForXPath(locus.xpath, pageDiv); + } else if (typeof(locus.selector) == "string") { + result.page = component.pageForSelector(locus.selector, pageDiv); + } else if (typeof(locus.position) == "string") { + if (locus.position == "start") { + result.page = 1; + } else if (locus.position == "end") { + result.page = lastPageNum['new']; + } + } else { + console.warn("Unrecognised locus: " + locus); + } + + if (result.page < 1) { + if (cIndex == 0) { + // On first page of book. + result.page = 1; + result.boundarystart = true; + } else { + // Moving backwards from current component. + result.load = true; + result.componentId = p.componentIds[cIndex - 1]; + result.pagesBack = result.page; + result.page = null; + } + } else if (result.page > lastPageNum) { + if (cIndex == p.lastCIndex) { + // On last page of book. + result.page = lastPageNum; + result.boundaryend = true; + } else { + // Moving forwards from current component. + result.load = true; + result.componentId = p.componentIds[cIndex + 1]; + result.page -= lastPageNum; + } + } + + return result; + } + + + // Same as pageNumberAt, but if a load is not flagged, this will + // automatically update the pageDiv's place to the given pageNumber. + // + // If you call this (ie, from a flipper), you are effectively entering into + // a contract to move the frame offset to the given page returned in the + // locus if load is false. + // + function setPageAt(pageDiv, locus) { + locus = pageNumberAt(pageDiv, locus); + if (locus && !locus.load) { + var evtData = { locus: locus, page: pageDiv } + if (locus.boundarystart) { + pageDiv.m.reader.dispatchEvent('monocle:boundarystart', evtData); + } else if (locus.boundaryend) { + pageDiv.m.reader.dispatchEvent('monocle:boundaryend', evtData); + } else { + var component = p.components[p.componentIds.indexOf(locus.componentId)]; + pageDiv.m.place = pageDiv.m.place || new Monocle.Place(); + pageDiv.m.place.setPlace(component, locus.page); + + var evtData = { + page: pageDiv, + locus: locus, + pageNumber: pageDiv.m.place.pageNumber(), + componentId: locus.componentId + } + pageDiv.m.reader.dispatchEvent("monocle:pagechange", evtData); + } + } + return locus; + } + + + // Will load the given component into the pageDiv's frame, then invoke the + // callback with resulting locus (provided by pageNumberAt). + // + // If the resulting page number is outside the bounds of the new component, + // (ie, pageNumberAt again requests a load), this will recurse into further + // components until non-loading locus is returned by pageNumberAt. Then the + // callback will fire with that locus. + // + // As with setPageAt, if you call this you're obliged to move the frame + // offset to the given page in the locus passed to the callback. + // + function loadPageAt(pageDiv, locus, onLoad, onFail) { + var cIndex = p.componentIds.indexOf(locus.componentId); + if (!locus.load || cIndex < 0) { + locus = pageNumberAt(pageDiv, locus); + } + + if (!locus) { + return onFail ? onFail() : null; + } + + if (!locus.load) { + return onLoad(locus); + } + + var findPageNumber = function () { + locus = setPageAt(pageDiv, locus); + if (!locus) { + return onFail ? onFail() : null; + } else if (locus.load) { + loadPageAt(pageDiv, locus, onLoad, onFail) + } else { + onLoad(locus); + } + } + + var applyComponent = function (component) { + component.applyTo(pageDiv, findPageNumber); + for (var l = 1; l <= p.preloadWindow; ++l) { + deferredPreloadComponent(cIndex+l, l*k.PRELOAD_INTERVAL); + } + } + + loadComponent(cIndex, applyComponent, onFail, pageDiv); + } + + + // If your flipper doesn't care whether a component needs to be + // loaded before the page can be set, you can use this shortcut. + // + function setOrLoadPageAt(pageDiv, locus, onLoad, onFail) { + locus = setPageAt(pageDiv, locus); + if (!locus) { + if (onFail) { onFail(); } + } else if (locus.load) { + loadPageAt(pageDiv, locus, onLoad, onFail); + } else { + onLoad(locus); + } + } + + + // Fetches the component source from the dataSource. + // + // 'index' is the index of the component in the + // dataSource.getComponents array. + // + // 'onLoad' is invoked when the source is received. + // + // 'onFail' is optional, and is invoked if the source could not be fetched. + // + // 'pageDiv' is optional, and simply allows firing events on + // the reader object that has requested this component, ONLY if + // the source has not already been received. + // + function loadComponent(index, onLoad, onFail, pageDiv) { + if (p.components[index]) { + return onLoad(p.components[index]); + } + + var cmptId = p.components[index]; + var evtData = { 'page': pageDiv, 'component': cmptId, 'index': index }; + pageDiv.m.reader.dispatchEvent('monocle:componentloading', evtData); + + var onCmptLoad = function (cmpt) { + evtData['component'] = cmpt; + pageDiv.m.reader.dispatchEvent('monocle:componentloaded', evtData); + onLoad(cmpt); + } + + var onCmptFail = function (cmptId) { + console.warn("Failed to load component: "+cmptId); + pageDiv.m.reader.dispatchEvent('monocle:componentfailed', evtData); + if (onFail) { onFail(); } + } + + _loadComponent(index, onCmptLoad, onCmptFail); + } + + + function preloadComponent(index) { + if (p.components[index]) { return; } + var cmptId = p.componentIds[index]; + if (!cmptId) { return; } + if (p.cmptLoadQueue[cmptId]) { return; } + _loadComponent(index); + } + + + function deferredPreloadComponent(index, delay) { + Monocle.defer(function () { preloadComponent(index); }, delay); + } + + + function _loadComponent(index, successCallback, failureCallback) { + var cmptId = p.componentIds[index]; + var queueItem = { success: successCallback, failure: failureCallback }; + if (p.cmptLoadQueue[cmptId]) { + return p.cmptLoadQueue[cmptId] = queueItem; + } else { + p.cmptLoadQueue[cmptId] = queueItem; + } + + var onCmptFail = function () { + fireLoadQueue(cmptId, 'failure', cmptId); + } + + var onCmptLoad = function (cmptSource) { + if (cmptSource === false) { return onCmptFail(); } + p.components[index] = new Monocle.Component( + API, + cmptId, + index, + chaptersForComponent(cmptId), + cmptSource + ); + fireLoadQueue(cmptId, 'success', p.components[index]); + } + + var cmptSource = p.dataSource.getComponent(cmptId, onCmptLoad); + if (cmptSource && !p.components[index]) { + onCmptLoad(cmptSource); + } else if (cmptSource === false) { + onCmptFail(); + } + } + + + function fireLoadQueue(cmptId, cbName, args) { + if (typeof p.cmptLoadQueue[cmptId][cbName] == 'function') { + p.cmptLoadQueue[cmptId][cbName](args); + } + p.cmptLoadQueue[cmptId] = null; + } + + + // Returns an array of chapter objects that are found in the given component. + // + // A chapter object has this format: + // + // { + // title: "Chapter 1", + // fragment: null + // } + // + // The fragment property of a chapter object is either null (the chapter + // starts at the head of the component) or the fragment part of the URL + // (eg, "foo" in "index.html#foo"). + // + function chaptersForComponent(cmptId) { + if (p.chapters[cmptId]) { + return p.chapters[cmptId]; + } + p.chapters[cmptId] = []; + var matcher = new RegExp('^'+decodeURIComponent(cmptId)+"(\#(.+)|$)"); + var matches; + var recurser = function (chp) { + if (matches = decodeURIComponent(chp.src).match(matcher)) { + p.chapters[cmptId].push({ + title: chp.title, + fragment: matches[2] || null + }); + } + if (chp.children) { + for (var i = 0; i < chp.children.length; ++i) { + recurser(chp.children[i]); + } + } + } + + for (var i = 0; i < p.contents.length; ++i) { + recurser(p.contents[i]); + } + return p.chapters[cmptId]; + } + + + // Returns a locus for the chapter that has the URL given in the + // 'src' argument. + // + // See the comments at pageNumberAt for an explanation of locus objects. + // + function locusOfChapter(src) { + var matcher = new RegExp('^(.+?)(#(.*))?$'); + var matches = src.match(matcher); + if (!matches) { return null; } + var cmptId = componentIdMatching(matches[1]); + if (!cmptId) { return null; } + var locus = { componentId: cmptId } + matches[3] ? locus.anchor = matches[3] : locus.position = "start"; + return locus; + } + + + function isValidLocus(locus) { + if (!locus) { return false; } + if (locus.componentId && !componentIdMatching(locus.componentId)) { + return false; + } + return true; + } + + + function componentIdMatching(str) { + str = decodeURIComponent(str); + for (var i = 0, ii = p.componentIds.length; i < ii; ++i) { + if (decodeURIComponent(p.componentIds[i]) == str) { return str; } + } + return null; + } + + + function componentWeights() { + if (!p.weights) { + p.weights = dataSource.getMetaData('componentWeights') || []; + if (!p.weights.length) { + var cmptSize = 1.0 / p.componentIds.length; + for (var i = 0, ii = p.componentIds.length; i < ii; ++i) { + p.weights.push(cmptSize); + } + } + } + return p.weights; + } + + + API.getMetaData = dataSource.getMetaData; + API.pageNumberAt = pageNumberAt; + API.setPageAt = setPageAt; + API.loadPageAt = loadPageAt; + API.setOrLoadPageAt = setOrLoadPageAt; + API.chaptersForComponent = chaptersForComponent; + API.locusOfChapter = locusOfChapter; + API.isValidLocus = isValidLocus; + API.componentWeights = componentWeights; + + initialize(); + + return API; +} + + +// Legacy function. Deprecated. +// +Monocle.Book.fromNodes = function (nodes) { + console.deprecation("Book.fromNodes() will soon be removed."); + return new Monocle.Book(Monocle.bookDataFromNodes(nodes)); +} + +Monocle.Book.PRELOAD_INTERVAL = 1000; +// PLACE + +Monocle.Place = function () { + + var API = { constructor: Monocle.Place } + var k = API.constants = API.constructor; + var p = API.properties = { + component: null, + percent: null + } + + + function setPlace(cmpt, pageN) { + p.component = cmpt; + p.percent = pageN / cmpt.lastPageNumber(); + p.chapter = null; + } + + + function setPercentageThrough(cmpt, percent) { + p.component = cmpt; + p.percent = percent; + p.chapter = null; + } + + + function componentId() { + return p.component.properties.id; + } + + + // How far we are through the component at the "top of the page". + // + // 0 - start of book. 1.0 - end of book. + // + function percentAtTopOfPage() { + if (k.PAGE_ANCHOR == 'bottom') { + return p.percent - 1.0 / p.component.lastPageNumber(); + } else { + return p.percent; + } + } + + + function percentOnPage() { + return percentAtTopOfPage() + k.PAGE_ANCHOR_OFFSET / pagesInComponent(); + } + + + // How far we are through the component at the "bottom of the page". + // + function percentAtBottomOfPage() { + if (k.PAGE_ANCHOR == 'bottom') { + return p.percent; + } else { + return p.percent + 1.0 / p.component.lastPageNumber(); + } + } + + + // The page number at a given point (0: start, 1: end) within the component. + // + function pageAtPercentageThrough(percent) { + var pages = pagesInComponent(); + if (typeof percent != 'number') { percent = 0; } + return Math.max(Math.round(pages * percent), 1); + } + + + // The page number of this point within the component. + // + function pageNumber() { + return pageAtPercentageThrough(p.percent); + } + + + function pagesInComponent() { + return p.component.lastPageNumber(); + } + + + function chapterInfo() { + if (p.chapter) { + return p.chapter; + } + return p.chapter = p.component.chapterForPage(pageNumber()+1); + } + + + function chapterTitle() { + var chp = chapterInfo(); + return chp ? chp.title : null; + } + + + function chapterSrc() { + var src = componentId(); + var cinfo = chapterInfo(); + if (cinfo && cinfo.fragment) { + src += "#" + cinfo.fragment; + } + return src; + } + + + function getLocus(options) { + options = options || {}; + var locus = { + page: pageNumber(), + componentId: componentId() + } + if (options.direction) { + locus.page += options.direction; + } else { + locus.percent = percentAtBottomOfPage(); + } + return locus; + } + + + // Returns how far this place is in the entire book (0 - start, 1.0 - end). + // + function percentageOfBook() { + var book = p.component.properties.book; + var componentIds = book.properties.componentIds; + var weights = book.componentWeights(); + var cmptIndex = p.component.properties.index; + var pc = weights[cmptIndex] * p.percent; + for (var i = 0, ii = cmptIndex; i < ii; ++i) { pc += weights[i]; } + + // Note: This is a decent estimation of current page number and total + // number of pages, but it's very approximate. Could be improved by storing + // the page counts of all components accessed (since the dimensions of the + // reader last changed), and averaging the result across them. (You + // probably want to ignore calcs for components < 2 or 3 pages long, too. + // The bigger the component, the more accurate the calculation.) + // + // var bkPages = p.component.lastPageNumber() / weights[cmptIndex]; + // console.log('Page: '+ Math.floor(pc*bkPages)+ ' of '+ Math.floor(bkPages)); + + return pc; + } + + + function onFirstPageOfBook() { + return p.component.properties.index == 0 && pageNumber() == 1; + } + + + function onLastPageOfBook() { + return ( + p.component.properties.index == + p.component.properties.book.properties.lastCIndex && + pageNumber() == p.component.lastPageNumber() + ); + } + + + API.setPlace = setPlace; + API.setPercentageThrough = setPercentageThrough; + API.componentId = componentId; + API.percentAtTopOfPage = percentAtTopOfPage; + API.percentOnPage = percentOnPage; + API.percentAtBottomOfPage = percentAtBottomOfPage; + API.pageAtPercentageThrough = pageAtPercentageThrough; + API.pageNumber = pageNumber; + API.pagesInComponent = pagesInComponent; + API.chapterInfo = chapterInfo; + API.chapterTitle = chapterTitle; + API.chapterSrc = chapterSrc; + API.getLocus = getLocus; + API.percentageOfBook = percentageOfBook; + API.onFirstPageOfBook = onFirstPageOfBook; + API.onLastPageOfBook = onLastPageOfBook; + + API.percentageThrough = k.PAGE_ANCHOR == 'bottom' ? percentAtBottomOfPage : + k.PAGE_ANCHOR == 'offset' ? percentOnPage : + percentAtTopOfPage; + + return API; +} + + +// Can set this to 'top', 'offset' or 'bottom'. Old Monocle behaviour is 'bottom'. +// +Monocle.Place.PAGE_ANCHOR = 'offset'; +Monocle.Place.PAGE_ANCHOR_OFFSET = 0.1; + + +Monocle.Place.FromPageNumber = function (component, pageNumber) { + var place = new Monocle.Place(); + place.setPlace(component, pageNumber); + return place; +} + + +Monocle.Place.FromPercentageThrough = function (component, percent) { + var place = new Monocle.Place(); + place.setPercentageThrough(component, percent); + return place; +} + + +// We can't create a place from a percentage of the book, because the +// component may not have been loaded yet. But we can get a locus. +// +Monocle.Place.percentOfBookToLocus = function (reader, percent) { + var book = reader.getBook(); + var componentIds = book.properties.componentIds; + var weights = book.componentWeights(); + var cmptIndex = 0, cmptWeight = 0; + percent = Math.min(percent, 0.99999); + while (percent >= 0) { + cmptWeight = weights[cmptIndex]; + percent -= weights[cmptIndex]; + if (percent >= 0) { + cmptIndex += 1; + if (cmptIndex >= weights.length) { + console.error('Unable to calculate locus from percentage: '+percent); + return; + } + } + } + var cmptPercent = (percent + cmptWeight) / cmptWeight; + return { componentId: componentIds[cmptIndex], percent: cmptPercent } +} +; +/* COMPONENT */ + +// See the properties declaration for details of constructor arguments. +// +Monocle.Component = function (book, id, index, chapters, source) { + + var API = { constructor: Monocle.Component } + var k = API.constants = API.constructor; + var p = API.properties = { + // a back-reference to the public API of the book that owns this component + book: book, + + // the string that represents this component in the book's component array + id: id, + + // the position in the book's components array of this component + index: index, + + // The chapters argument is an array of objects that list the chapters that + // can be found in this component. A chapter object is defined as: + // + // { + // title: str, + // fragment: str, // optional anchor id + // percent: n // how far into the component the chapter begins + // } + // + // NOTE: the percent property is calculated by the component - you only need + // to pass in the title and the optional id string. + // + chapters: chapters, + + // the frame provided by dataSource.getComponent() for this component + source: source + } + + + // Makes this component the active component for the pageDiv. There are + // several strategies for this (see loadFrame). + // + // When the component has been loaded into the pageDiv's frame, the callback + // will be invoked with the pageDiv and this component as arguments. + // + function applyTo(pageDiv, callback) { + prepareSource(pageDiv.m.reader); + + var evtData = { 'page': pageDiv, 'source': p.source }; + pageDiv.m.reader.dispatchEvent('monocle:componentchanging', evtData); + + var onLoaded = function () { + setupFrame( + pageDiv, + pageDiv.m.activeFrame, + function () { callback(pageDiv, API) } + ); + } + + Monocle.defer(function () { loadFrame(pageDiv, onLoaded); }); + } + + + // Loads this component into the given frame, using one of the following + // strategies: + // + // * HTML - a HTML string + // * URL - a URL string + // * Nodes - an array of DOM body nodes (NB: no way to populate head) + // * Document - a DOM DocumentElement object + // + function loadFrame(pageDiv, callback) { + var frame = pageDiv.m.activeFrame; + + // We own this frame now. + frame.m.component = API; + + // Hide the frame while we're changing it. + frame.style.visibility = "hidden"; + + frame.whenDocumentReady = function () { + var doc = frame.contentDocument; + var evtData = { 'page': pageDiv, 'document': doc, 'component': API }; + pageDiv.m.reader.dispatchEvent('monocle:componentmodify', evtData); + frame.whenDocumentReady = null; + } + + if (p.source.html) { + return loadFrameFromHTML(p.source.html || p.source, frame, callback); + } else if (p.source.url) { + return loadFrameFromURL(p.source.url, frame, callback); + } else if (p.source.doc) { + return loadFrameFromDocument(p.source.doc, frame, callback); + } + } + + + // LOAD STRATEGY: HTML + // Loads a HTML string into the given frame, invokes the callback once loaded. + // + function loadFrameFromHTML(src, frame, callback) { + var fn = function () { + Monocle.Events.deafen(frame, 'load', fn); + frame.whenDocumentReady(); + Monocle.defer(callback); + } + Monocle.Events.listen(frame, 'load', fn); + if (Monocle.Browser.env.loadHTMLWithDocWrite) { + frame.contentDocument.open('text/html', 'replace'); + frame.contentDocument.write(src); + frame.contentDocument.close(); + } else { + frame.contentWindow['monCmptData'] = src; + frame.src = "javascript:window['monCmptData'];" + } + } + + + // LOAD STRATEGY: URL + // Loads the URL into the given frame, invokes callback once loaded. + // + function loadFrameFromURL(url, frame, callback) { + // If it's a relative path, we need to make it absolute. + if (!url.match(/^\//)) { + url = absoluteURL(url); + } + var onDocumentReady = function () { + Monocle.Events.deafen(frame, 'load', onDocumentReady); + frame.whenDocumentReady(); + } + var onDocumentLoad = function () { + Monocle.Events.deafen(frame, 'load', onDocumentLoad); + Monocle.defer(callback); + } + Monocle.Events.listen(frame, 'load', onDocumentReady); + Monocle.Events.listen(frame, 'load', onDocumentLoad); + frame.contentWindow.location.replace(url); + } + + + // LOAD STRATEGY: DOCUMENT + // Replaces the DocumentElement of the given frame with the given srcDoc. + // Invokes the callback when loaded. + // + function loadFrameFromDocument(srcDoc, frame, callback) { + var doc = frame.contentDocument; + + // WebKit has an interesting quirk. The tag must exist in the + // document being replaced, not the new document. + if (Monocle.Browser.is.WebKit) { + var srcBase = srcDoc.querySelector('base'); + if (srcBase) { + var head = doc.querySelector('head'); + if (!head) { + try { + head = doc.createElement('head'); + prependChild(doc.documentElement, head); + } catch (e) { + head = doc.body; + } + } + var base = doc.createElement('base'); + base.setAttribute('href', srcBase.href); + head.appendChild(base); + } + } + + doc.replaceChild( + doc.importNode(srcDoc.documentElement, true), + doc.documentElement + ); + + // NB: It's a significant problem with this load strategy that there's + // no indication when it is complete. + Monocle.defer(callback); + } + + + // Once a frame is loaded with this component, call this method to style + // and measure its contents. + // + function setupFrame(pageDiv, frame, callback) { + updateDimensions(pageDiv, function () { + frame.style.visibility = "visible"; + + // Find the place of any chapters in the component. + locateChapters(pageDiv); + + // Nothing can prevent iframe scrolling on Android, so we have to undo it. + if (Monocle.Browser.on.Android) { + Monocle.Events.listen(frame.contentWindow, 'scroll', function () { + frame.contentWindow.scrollTo(0,0); + }); + } + + // Announce that the component has changed. + var doc = frame.contentDocument; + var evtData = { 'page': pageDiv, 'document': doc, 'component': API }; + pageDiv.m.reader.dispatchEvent('monocle:componentchange', evtData); + + callback(); + }); + } + + + // Checks whether the pageDiv dimensions have changed. If they have, + // remeasures dimensions and returns true. Otherwise returns false. + // + function updateDimensions(pageDiv, callback) { + pageDiv.m.dimensions.update(function (pageLength) { + p.pageLength = pageLength; + if (typeof callback == "function") { callback() }; + }); + } + + + // Iterates over all the chapters that are within this component + // (according to the array we were provided on initialization) and finds + // their location (in percentage terms) within the text. + // + // Stores this percentage with the chapter object in the chapters array. + // + function locateChapters(pageDiv) { + if (p.chapters[0] && typeof p.chapters[0].percent == "number") { + return; + } + var doc = pageDiv.m.activeFrame.contentDocument; + for (var i = 0; i < p.chapters.length; ++i) { + var chp = p.chapters[i]; + chp.percent = 0; + if (chp.fragment) { + var node = doc.getElementById(chp.fragment); + chp.percent = pageDiv.m.dimensions.percentageThroughOfNode(node); + } + } + return p.chapters; + } + + + // For a given page number within the component, return the chapter that + // starts on or most-recently-before this page. + // + // Useful, for example, in displaying the current chapter title as a + // running head on the page. + // + function chapterForPage(pageN) { + var cand = null; + var percent = (pageN - 1) / p.pageLength; + for (var i = 0; i < p.chapters.length; ++i) { + if (percent >= p.chapters[i].percent) { + cand = p.chapters[i]; + } else { + return cand; + } + } + return cand; + } + + + // For a given chapter fragment (the bit after the hash + // in eg, "index.html#foo"), return the page number on which + // the chapter starts. If the fragment is null or blank, will + // return the first page of the component. + // + function pageForChapter(fragment, pageDiv) { + if (!fragment) { + return 1; + } + for (var i = 0; i < p.chapters.length; ++i) { + if (p.chapters[i].fragment == fragment) { + return percentToPageNumber(p.chapters[i].percent); + } + } + var doc = pageDiv.m.activeFrame.contentDocument; + var node = doc.getElementById(fragment); + var percent = pageDiv.m.dimensions.percentageThroughOfNode(node); + return percentToPageNumber(percent); + } + + + function pageForXPath(xpath, pageDiv) { + var doc = pageDiv.m.activeFrame.contentDocument; + var percent = 0; + if (Monocle.Browser.env.supportsXPath) { + var node = doc.evaluate(xpath, doc, null, 9, null).singleNodeValue; + if (node) { + percent = pageDiv.m.dimensions.percentageThroughOfNode(node); + } + } else { + console.warn("XPath not supported in this client."); + } + return percentToPageNumber(percent); + } + + + function pageForSelector(selector, pageDiv) { + var doc = pageDiv.m.activeFrame.contentDocument; + var percent = 0; + if (Monocle.Browser.env.supportsQuerySelector) { + var node = doc.querySelector(selector); + if (node) { + percent = pageDiv.m.dimensions.percentageThroughOfNode(node); + } + } else { + console.warn("querySelector not supported in this client."); + } + return percentToPageNumber(percent); + } + + + function percentToPageNumber(pc) { + return Math.floor(pc * p.pageLength) + 1; + } + + + // A public getter for p.pageLength. + // + function lastPageNumber() { + return p.pageLength; + } + + + function prepareSource(reader) { + if (p.sourcePrepared) { return; } + p.sourcePrepared = true; + + if (typeof p.source == "string") { + p.source = { html: p.source }; + } + + // If supplied as escaped javascript, unescape it to HTML by evalling it. + if (p.source.javascript) { + console.deprecation( + "Loading a component by 'javascript' is deprecated. " + + "Use { 'html': src } -- no need to escape or clean the string." + ); + var src = p.source.javascript; + src = src.replace(/\\n/g, "\n"); + src = src.replace(/\\r/g, "\r"); + src = src.replace(/\\'/g, "'"); + p.source = { html: src }; + } + + // If supplied as DOM nodes, convert to HTML by concatenating outerHTMLs. + if (p.source.nodes) { + var srcs = []; + for (var i = 0, ii = p.source.nodes.length; i < ii; ++i) { + var node = p.source.nodes[i]; + if (node.outerHTML) { + srcs.push(node.outerHTML); + } else { + var div = document.createElement('div'); + div.appendChild(node.cloneNode(true)); + srcs.push(div.innerHTML); + delete(div); + } + } + p.source = { html: srcs.join('') }; + } + + if (p.source.html && !p.source.html.match(new RegExp("", "im"))) { + var baseURI = computeBaseURI(reader); + if (baseURI) { + p.source.html = p.source.html.replace( + new RegExp("(]*>)", "im"), + '$1' + ); + } + } + + if (p.source.doc && !p.source.doc.querySelector('base')) { + var srcHead = p.source.doc.querySelector('head') || p.source.doc.body; + var baseURI = computeBaseURI(reader); + if (srcHead && baseURI) { + var srcBase = p.source.doc.createElement('base'); + srcBase.setAttribute('href', baseURI); + prependChild(srcHead, srcBase); + } + } + } + + + function computeBaseURI(reader) { + var evtData = { cmptId: p.id, cmptURI: absoluteURL(p.id) } + if (reader.dispatchEvent('monocle:component:baseuri', evtData, true)) { + return evtData.cmptURI; + } + } + + + function absoluteURL(url) { + var link = document.createElement('a'); + link.setAttribute('href', url); + result = link.href; + delete(link); + return result; + } + + + function prependChild(pr, el) { + pr.firstChild ? pr.insertBefore(el, pr.firstChild) : pr.appendChild(el); + } + + + API.applyTo = applyTo; + API.updateDimensions = updateDimensions; + API.chapterForPage = chapterForPage; + API.pageForChapter = pageForChapter; + API.pageForXPath = pageForXPath; + API.pageForSelector = pageForSelector; + API.lastPageNumber = lastPageNumber; + + return API; +} +; +Monocle.Selection = function (reader) { + var API = { constructor: Monocle.Selection }; + var k = API.constants = API.constructor; + var p = API.properties = { + reader: reader, + lastSelection: [] + }; + + + function initialize() { + if (k.SELECTION_POLLING_INTERVAL) { + setInterval(pollSelection, k.SELECTION_POLLING_INTERVAL); + } + } + + + function pollSelection() { + var index = 0, frame = null; + while (frame = reader.dom.find('component', index++)) { + if (frame.contentWindow) { + pollSelectionOnWindow(frame.contentWindow, index); + } + } + } + + + function pollSelectionOnWindow(win, index) { + var sel = win.getSelection(); + var lm = p.lastSelection[index] || {}; + var nm = p.lastSelection[index] = { + selected: anythingSelected(win), + range: sel.rangeCount ? sel.getRangeAt(0) : null, + string: sel.toString() + }; + if (nm.selected) { + nm.rangeStartContainer = nm.range.startContainer; + nm.rangeEndContainer = nm.range.endContainer; + nm.rangeStartOffset = nm.range.startOffset; + nm.rangeEndOffset = nm.range.endOffset; + if (!sameRange(nm, lm)) { + p.reader.dispatchEvent('monocle:selection', nm); + } + } else if (lm.selected) { + p.reader.dispatchEvent('monocle:deselection', lm); + } + } + + + function sameRange(m1, m2) { + return ( + m1.rangeStartContainer == m2.rangeStartContainer && + m1.rangeEndContainer == m2.rangeEndContainer && + m1.rangeStartOffset == m2.rangeStartOffset && + m1.rangeEndOffset == m2.rangeEndOffset + ); + } + + + // Given a window object, remove any user selections within. Trivial in + // most browsers, but involving major mojo on iOS. + // + function deselect() { + var index = 0, frame = null; + while (frame = reader.dom.find('component', index++)) { + deselectOnWindow(frame.contentWindow); + } + } + + + function deselectOnWindow(win) { + win = win || window; + if (!anythingSelected(win)) { return; } + + if (Monocle.Browser.iOSVersion && !Monocle.Browser.iOSVersionBelow(5)) { + preservingScale(function () { + preservingScrollPosition(function () { + var inp = document.createElement('input'); + inp.style.cssText = [ + 'position: absolute', + 'top: 0', + 'left: 0', + 'width: 0', + 'height: 0' + ].join(';'); + document.body.appendChild(inp); + inp.focus(); + document.body.removeChild(inp); + }) + }); + } + + var sel = win.getSelection(); + sel.removeAllRanges(); + win.document.body.scrollLeft = 0; + win.document.body.scrollTop = 0; + } + + + function preservingScrollPosition(fn) { + var sx = window.scrollX, sy = window.scrollY; + fn(); + window.scrollTo(sx, sy); + } + + + function preservingScale(fn) { + var head = document.querySelector('head'); + var ovp = head.querySelector('meta[name=viewport]'); + var createViewportMeta = function (content) { + var elem = document.createElement('meta'); + elem.setAttribute('name', 'viewport'); + elem.setAttribute('content', content); + head.appendChild(elem); + return elem; + } + + if (ovp) { + var ovpcontent = ovp.getAttribute('content'); + var re = /user-scalable\s*=\s*([^,$\s])*/; + var result = ovpcontent.match(re); + if (result && ['no', '0'].indexOf(result[1]) >= 0) { + fn(); + } else { + var nvpcontent = ovpcontent.replace(re, ''); + nvpcontent += nvpcontent ? ', ' : ''; + nvpcontent += 'user-scalable=no'; + head.removeChild(ovp); + var nvp = createViewportMeta(nvpcontent); + fn(); + head.removeChild(nvp); + head.appendChild(ovp); + } + } else { + var nvp = createViewportMeta('user-scalable=no'); + fn(); + nvp.setAttribute('content', 'user-scalable=yes'); + } + } + + + function anythingSelected(win) { + return !win.getSelection().isCollapsed; + } + + + API.deselect = deselect; + + + initialize(); + + return API; +} + + +Monocle.Selection.SELECTION_POLLING_INTERVAL = 250; +Monocle.Billboard = function (reader) { + var API = { constructor: Monocle.Billboard }; + var k = API.constants = API.constructor; + var p = API.properties = { + reader: reader, + cntr: null + }; + + + function show(urlOrElement, options) { + p.reader.dispatchEvent('monocle:modal:on'); + if (p.cntr) { return console.warn("Modal billboard already showing."); } + + var options = options || {}; + var elem = urlOrElement; + p.cntr = reader.dom.append('div', k.CLS.cntr); + if (typeof urlOrElement == 'string') { + var url = urlOrElement; + p.inner = elem = p.cntr.dom.append('iframe', k.CLS.inner); + elem.setAttribute('src', url); + } else { + p.inner = p.cntr.dom.append('div', k.CLS.inner); + p.inner.appendChild(elem); + } + p.dims = [ + elem.naturalWidth || elem.offsetWidth, + elem.naturalHeight || elem.offsetHeight + ]; + if (options.closeButton != false) { + var cBtn = p.cntr.dom.append('div', k.CLS.closeButton); + Monocle.Events.listenForTap(cBtn, hide); + } + align(options.align || 'left top'); + p.reader.listen('monocle:resize', align); + + shrink(options.from); + Monocle.defer(grow); + } + + + function hide(evt) { + shrink(); + Monocle.Events.afterTransition(p.cntr, remove); + } + + + function grow() { + Monocle.Styles.transitionFor(p.cntr, 'transform', k.ANIM_MS, 'ease-in-out'); + Monocle.Styles.affix(p.cntr, 'transform', 'translate(0, 0) scale(1)'); + } + + + function shrink(from) { + p.from = from || p.from || [0,0]; + var translate = 'translate('+p.from[0]+'px, '+p.from[1]+'px)'; + var scale = 'scale(0)'; + if (typeof p.from[2] === 'number') { + scale = 'scaleX('+(p.from[2] / p.cntr.offsetWidth)+') '; + scale += 'scaleY('+(p.from[3] / p.cntr.offsetHeight)+')'; + } + Monocle.Styles.affix(p.cntr, 'transform', translate+' '+scale); + } + + + function remove () { + p.cntr.parentNode.removeChild(p.cntr); + p.cntr = p.inner = null; + p.reader.deafen('monocle:resize', align); + p.reader.dispatchEvent('monocle:modal:off'); + } + + + function align(loc) { + p.alignment = (typeof loc == 'string') ? loc : p.alignment; + if (!p.alignment) { return; } + if (p.dims[0] > p.inner.offsetWidth || p.dims[1] > p.inner.offsetHeight) { + p.cntr.dom.addClass(k.CLS.oversized); + } else { + p.cntr.dom.removeClass(k.CLS.oversized); + } + + var s = p.alignment.split(/\s+/); + var l = 0, t = 0; + var w = (p.inner.scrollWidth - p.inner.offsetWidth); + var h = (p.inner.scrollHeight - p.inner.offsetHeight); + if (s[0].match(/^\d+$/)) { + l = Math.max(0, parseInt(s[0]) - (p.inner.offsetWidth / 2)); + } else if (s[0] == 'center') { + l = w / 2; + } else if (s[0] == 'right') { + l = w; + } + if (s[1] && s[1].match(/^\d+$/)) { + t = Math.max(0, parseInt(s[1]) - (p.inner.offsetHeight / 2)); + } else if (!s[1] || s[1] == 'center') { + t = h / 2; + } else if (s[1] == 'bottom') { + t = h; + } + p.inner.scrollLeft = l; + p.inner.scrollTop = t; + } + + + API.show = show; + API.hide = hide; + API.align= align; + + return API; +} + + +Monocle.Billboard.CLS = { + cntr: 'billboard_container', + inner: 'billboard_inner', + closeButton: 'billboard_close', + oversized: 'billboard_oversized' +} + +Monocle.Billboard.ANIM_MS = 400; +// A panel is an invisible column of interactivity. When contact occurs +// (mousedown, touchstart), the panel expands to the full width of its +// container, to catch all interaction events and prevent them from hitting +// other things. +// +// Panels are used primarily to provide hit zones for page flipping +// interactions, but you can do whatever you like with them. +// +// After instantiating a panel and adding it to the reader as a control, +// you can call listenTo() with a hash of methods for any of 'start', 'move' +// 'end' and 'cancel'. +// +Monocle.Controls.Panel = function () { + + var API = { constructor: Monocle.Controls.Panel } + var k = API.constants = API.constructor; + var p = API.properties = { + evtCallbacks: {} + } + + function createControlElements(cntr) { + p.div = cntr.dom.make('div', k.CLS.panel); + p.div.dom.setStyles(k.DEFAULT_STYLES); + Monocle.Events.listenForContact( + p.div, + { + 'start': start, + 'move': move, + 'end': end, + 'cancel': cancel + }, + { useCapture: false } + ); + return p.div; + } + + + function setDirection(dir) { + p.direction = dir; + } + + + function listenTo(evtCallbacks) { + p.evtCallbacks = evtCallbacks; + } + + + function deafen() { + p.evtCallbacks = {} + } + + + function start(evt) { + p.contact = true; + evt.m.offsetX += p.div.offsetLeft; + evt.m.offsetY += p.div.offsetTop; + expand(); + invoke('start', evt); + } + + + function move(evt) { + if (!p.contact) { + return; + } + invoke('move', evt); + } + + + function end(evt) { + if (!p.contact) { + return; + } + Monocle.Events.deafenForContact(p.div, p.listeners); + contract(); + p.contact = false; + invoke('end', evt); + } + + + function cancel(evt) { + if (!p.contact) { + return; + } + Monocle.Events.deafenForContact(p.div, p.listeners); + contract(); + p.contact = false; + invoke('cancel', evt); + } + + + function invoke(evtType, evt) { + if (p.evtCallbacks[evtType]) { + p.evtCallbacks[evtType](p.direction, evt.m.offsetX, evt.m.offsetY, API); + } + evt.preventDefault(); + } + + + function expand() { + if (p.expanded) { + return; + } + p.div.dom.addClass(k.CLS.expanded); + p.expanded = true; + } + + + function contract(evt) { + if (!p.expanded) { + return; + } + p.div.dom.removeClass(k.CLS.expanded); + p.expanded = false; + } + + + API.createControlElements = createControlElements; + API.listenTo = listenTo; + API.deafen = deafen; + API.expand = expand; + API.contract = contract; + API.setDirection = setDirection; + + return API; +} + + +Monocle.Controls.Panel.CLS = { + panel: 'panel', + expanded: 'controls_panel_expanded' +} +Monocle.Controls.Panel.DEFAULT_STYLES = { + position: 'absolute', + height: '100%' +} +; +// The simplest page-flipping interaction system: contact to the left half of +// the reader turns back one page, contact to the right half turns forward +// one page. +// +Monocle.Panels.TwoPane = function (flipper, evtCallbacks) { + + var API = { constructor: Monocle.Panels.TwoPane } + var k = API.constants = API.constructor; + var p = API.properties = {} + + + function initialize() { + p.panels = { + forwards: new Monocle.Controls.Panel(), + backwards: new Monocle.Controls.Panel() + } + + for (dir in p.panels) { + flipper.properties.reader.addControl(p.panels[dir]); + p.panels[dir].listenTo(evtCallbacks); + p.panels[dir].setDirection(flipper.constants[dir.toUpperCase()]); + var style = { "width": k.WIDTH }; + style[(dir == "forwards" ? "right" : "left")] = 0; + p.panels[dir].properties.div.dom.setStyles(style); + } + } + + + initialize(); + + return API; +} + +Monocle.Panels.TwoPane.WIDTH = "50%"; +// A three-pane system of page interaction. The left 33% turns backwards, the +// right 33% turns forwards, and contact on the middle third causes the +// system to go into "interactive mode". In this mode, the page-flipping panels +// are only active in the margins, and all of the actual text content of the +// book is selectable. The user can exit "interactive mode" by hitting the little +// IMode icon in the lower right corner of the reader. +// +Monocle.Panels.IMode = function (flipper, evtCallbacks) { + + var API = { constructor: Monocle.Panels.IMode } + var k = API.constants = API.constructor; + var p = API.properties = {} + + + function initialize() { + p.flipper = flipper; + p.reader = flipper.properties.reader; + p.panels = { + forwards: new Monocle.Controls.Panel(), + backwards: new Monocle.Controls.Panel() + } + p.divs = {} + + for (dir in p.panels) { + p.reader.addControl(p.panels[dir]); + p.divs[dir] = p.panels[dir].properties.div; + p.panels[dir].listenTo(evtCallbacks); + p.panels[dir].setDirection(flipper.constants[dir.toUpperCase()]); + p.divs[dir].style.width = "33%"; + p.divs[dir].style[dir == "forwards" ? "right" : "left"] = 0; + } + + p.panels.central = new Monocle.Controls.Panel(); + p.reader.addControl(p.panels.central); + p.divs.central = p.panels.central.properties.div; + p.divs.central.dom.setStyles({ left: "33%", width: "34%" }); + menuCallbacks({ end: modeOn }); + + for (dir in p.panels) { + p.divs[dir].dom.addClass('panels_imode_panel'); + p.divs[dir].dom.addClass('panels_imode_'+dir+'Panel'); + } + + p.toggleIcon = { + createControlElements: function (cntr) { + var div = cntr.dom.make('div', 'panels_imode_toggleIcon'); + Monocle.Events.listenForTap(div, modeOff); + return div; + } + } + p.reader.addControl(p.toggleIcon, null, { hidden: true }); + } + + + function menuCallbacks(callbacks) { + p.menuCallbacks = callbacks; + p.panels.central.listenTo(p.menuCallbacks); + } + + + function toggle() { + p.interactive ? modeOff() : modeOn(); + } + + + function modeOn() { + if (p.interactive) { + return; + } + + p.panels.central.contract(); + + var page = p.reader.visiblePages()[0]; + var sheaf = page.m.sheafDiv; + var bw = sheaf.offsetLeft; + var fw = page.offsetWidth - (sheaf.offsetLeft + sheaf.offsetWidth); + bw = Math.floor(((bw - 2) / page.offsetWidth) * 10000 / 100 ) + "%"; + fw = Math.floor(((fw - 2) / page.offsetWidth) * 10000 / 100 ) + "%"; + + startCameo(function () { + p.divs.forwards.style.width = fw; + p.divs.backwards.style.width = bw; + Monocle.Styles.affix(p.divs.central, 'transform', 'translateY(-100%)'); + }); + + p.reader.showControl(p.toggleIcon); + + p.interactive = true; + } + + + function modeOff() { + if (!p.interactive) { + return; + } + + p.panels.central.contract(); + + p.reader.selection.deselect(); + + startCameo(function () { + p.divs.forwards.style.width = "33%"; + p.divs.backwards.style.width = "33%"; + Monocle.Styles.affix(p.divs.central, 'transform', 'translateY(0)'); + }); + + p.reader.hideControl(p.toggleIcon); + + p.interactive = false; + } + + + function startCameo(fn) { + // Set transitions on the panels. + var trn = Monocle.Panels.IMode.CAMEO_DURATION+"ms ease-in"; + Monocle.Styles.affix(p.divs.forwards, 'transition', "width "+trn); + Monocle.Styles.affix(p.divs.backwards, 'transition', "width "+trn); + Monocle.Styles.affix(p.divs.central, 'transition', "-webkit-transform "+trn); + + // Temporarily disable listeners. + for (var pan in p.panels) { + p.panels[pan].deafen(); + } + + // Set the panels to opaque. + for (var div in p.divs) { + p.divs[div].style.opacity = 1; + } + + if (typeof WebkitTransitionEvent != "undefined") { + p.cameoListener = Monocle.Events.listen( + p.divs.central, + 'webkitTransitionEnd', + endCameo + ); + } else { + setTimeout(endCameo, k.CAMEO_DURATION); + } + fn(); + } + + + function endCameo() { + setTimeout(function () { + // Remove panel transitions. + var trn = "opacity linear " + Monocle.Panels.IMode.LINGER_DURATION + "ms"; + Monocle.Styles.affix(p.divs.forwards, 'transition', trn); + Monocle.Styles.affix(p.divs.backwards, 'transition', trn); + Monocle.Styles.affix(p.divs.central, 'transition', trn); + + // Set the panels to transparent. + for (var div in p.divs) { + p.divs[div].style.opacity = 0; + } + + // Re-enable listeners. + p.panels.forwards.listenTo(evtCallbacks); + p.panels.backwards.listenTo(evtCallbacks); + p.panels.central.listenTo(p.menuCallbacks); + }, Monocle.Panels.IMode.LINGER_DURATION); + + + if (p.cameoListener) { + Monocle.Events.deafen(p.divs.central, 'webkitTransitionEnd', endCameo); + } + } + + + API.toggle = toggle; + API.modeOn = modeOn; + API.modeOff = modeOff; + API.menuCallbacks = menuCallbacks; + + initialize(); + + return API; +} + +Monocle.Panels.IMode.CAMEO_DURATION = 250; +Monocle.Panels.IMode.LINGER_DURATION = 250; +Monocle.Panels.eInk = function (flipper, evtCallbacks) { + + var API = { constructor: Monocle.Panels.eInk } + var k = API.constants = API.constructor; + var p = API.properties = { + flipper: flipper + } + + + function initialize() { + p.panel = new Monocle.Controls.Panel(); + p.reader = p.flipper.properties.reader; + p.reader.addControl(p.panel); + + p.panel.listenTo({ end: function (panel, x) { + if (x < p.panel.properties.div.offsetWidth / 2) { + p.panel.setDirection(flipper.constants.BACKWARDS); + } else { + p.panel.setDirection(flipper.constants.FORWARDS); + } + evtCallbacks.end(panel, x); + } }); + + var s = p.panel.properties.div.style; + p.reader.listen("monocle:componentchanging", function () { + s.opacity = 1; + Monocle.defer(function () { s.opacity = 0 }, 40); + }); + s.width = "100%"; + s.background = "#000"; + s.opacity = 0; + + if (k.LISTEN_FOR_KEYS) { + Monocle.Events.listen(window.top.document, 'keyup', handleKeyEvent); + } + } + + + function handleKeyEvent(evt) { + var eventCharCode = evt.charCode || evt.keyCode; + var dir = null; + if (eventCharCode == k.KEYS["PAGEUP"]) { + dir = flipper.constants.BACKWARDS; + } else if (eventCharCode == k.KEYS["PAGEDOWN"]) { + dir = flipper.constants.FORWARDS; + } + if (dir) { + flipper.moveTo({ direction: dir }); + evt.preventDefault(); + } + } + + + initialize(); + + return API; +} + + +Monocle.Panels.eInk.LISTEN_FOR_KEYS = true; +Monocle.Panels.eInk.KEYS = { "PAGEUP": 33, "PAGEDOWN": 34 }; +// Provides page-flipping panels only in the margins of the book. This is not +// entirely suited to small screens with razor-thin margins, but is an +// appropriate panel class for larger screens (like, say, an iPad). +// +// Since the flipper hit zones are only in the margins, the actual text content +// of the book is always selectable. +// +Monocle.Panels.Marginal = function (flipper, evtCallbacks) { + + var API = { constructor: Monocle.Panels.Marginal } + var k = API.constants = API.constructor; + var p = API.properties = {} + + + function initialize() { + p.panels = { + forwards: new Monocle.Controls.Panel(), + backwards: new Monocle.Controls.Panel() + } + + for (dir in p.panels) { + flipper.properties.reader.addControl(p.panels[dir]); + p.panels[dir].listenTo(evtCallbacks); + p.panels[dir].setDirection(flipper.constants[dir.toUpperCase()]); + with (p.panels[dir].properties.div.style) { + dir == "forwards" ? right = 0 : left = 0; + } + } + setWidths(); + } + + + function setWidths() { + var page = flipper.properties.reader.dom.find('page'); + var sheaf = page.m.sheafDiv; + var bw = sheaf.offsetLeft; + var fw = page.offsetWidth - (sheaf.offsetLeft + sheaf.offsetWidth); + bw = Math.floor(((bw - 2) / page.offsetWidth) * 10000 / 100) + "%"; + fw = Math.floor(((fw - 2) / page.offsetWidth) * 10000 / 100) + "%"; + p.panels.forwards.properties.div.style.width = fw; + p.panels.backwards.properties.div.style.width = bw; + } + + + API.setWidths = setWidths; + + initialize(); + + return API; +} +; +Monocle.Panels.Magic = function (flipper, evtCallbacks) { + + var API = { constructor: Monocle.Panels.Magic } + var k = API.constants = API.constructor; + var p = API.properties = { + flipper: flipper, + evtCallbacks: evtCallbacks, + parts: {}, + action: {}, + contacts: [], + startListeners: [], + disabled: false + } + + + function initialize() { + p.reader = flipper.properties.reader; + p.parts = { + reader: p.reader.dom.find('box'), + cmpts: [] + } + for (var i = 0; i < p.flipper.pageCount; ++i) { + p.parts.cmpts.push(p.reader.dom.find('component', i)); + } + initListeners(); + + p.reader.listen('monocle:componentmodify', initListeners); + p.reader.listen('monocle:magic:init', initListeners); + p.reader.listen('monocle:magic:halt', haltListeners); + p.reader.listen('monocle:modal:on', disable); + p.reader.listen('monocle:modal:off', enable); + Monocle.Events.listen(window, 'gala:contact:cancel', resetAction); + } + + + function initListeners(evt) { + //console.log('magic:init'); + stopListening(); + startListening(); + } + + + function haltListeners(evt) { + //console.log('magic:halt'); + stopListening(); + } + + + function disable(evt) { + //console.log('modal:on - halting magic'); + stopListening(); + p.disabled = true; + } + + + function enable(evt) { + //console.log('modal:off - initing magic'); + p.disabled = false; + startListening(); + } + + + function startListening() { + if (p.disabled || p.startListeners.length) { return; } + + p.startListeners.push([ + p.parts.reader, + Monocle.Events.listenForContact( + p.parts.reader, + { 'start': translatorFunction(p.parts.reader, readerContactStart) } + ) + ]); + + for (var i = 0, ii = p.parts.cmpts.length; i < ii; ++i) { + p.startListeners.push([ + p.parts.cmpts[i].contentDocument.defaultView, + Monocle.Events.listenForContact( + p.parts.cmpts[i].contentDocument.defaultView, + { 'start': translatorFunction(p.parts.cmpts[i], cmptContactStart) } + ) + ]); + } + } + + + function stopListening() { + if (p.disabled || !p.startListeners.length) { return; } + for (var j = 0, jj = p.startListeners.length; j < jj; ++j) { + Monocle.Events.deafenForContact( + p.startListeners[j][0], + p.startListeners[j][1] + ); + } + p.startListeners = []; + } + + + function listenForMoveAndEnd(fnMove, fnEnd) { + listenOnElem( + document.defaultView, + translatorFunction(document.documentElement, fnMove), + translatorFunction(document.documentElement, fnEnd) + ); + for (var i = 0, ii = p.parts.cmpts.length; i < ii; ++i) { + listenOnElem( + p.parts.cmpts[i].contentDocument.defaultView, + translatorFunction(p.parts.cmpts[i], fnMove), + translatorFunction(p.parts.cmpts[i], fnEnd) + ); + } + } + + + function listenOnElem(elem, fnMove, fnEnd) { + var contactListeners = Monocle.Events.listenForContact( + elem, + { + 'move': fnMove, + 'end': function (evt) { deafenContactListeners(); fnEnd(evt); } + } + ); + p.contacts.push([elem, contactListeners]); + } + + + function deafenContactListeners() { + for (var i = 0, ii = p.contacts.length; i < ii; ++i) { + Monocle.Events.deafenForContact(p.contacts[i][0], p.contacts[i][1]); + } + p.contacts = []; + } + + + function readerContactStart(evt) { + listenForMoveAndEnd(readerContactMove, readerContactEnd); + p.action.startX = evt.m.readerX; + p.action.startY = evt.m.readerY; + p.action.screenX = evt.m.screenX; + p.action.screenY = evt.m.screenY; + p.action.dir = evt.m.readerX > halfway() ? k.FORWARDS : k.BACKWARDS; + p.action.handled = !dispatch('monocle:magic:contact:start', evt); + if (!p.action.handled) { invoke('start', evt); } + } + + + function readerContactMove(evt) { + if (p.action.handled) { + dispatch('monocle:magic:contact:move', evt); + } else { + invoke('move', evt); + } + // Can't prevent mousemove, so has no effect there. Preventing default + // for touchmove will override scrolling, while still allowing selection. + evt.preventDefault(); + } + + + function readerContactEnd(evt) { + p.action.endX = evt.m.readerX; + p.action.endY = evt.m.readerY; + if (dispatch('monocle:magic:contact', evt)) { invoke('end', evt); } + p.action = {}; + } + + + function cmptContactStart(evt) { + if (actionIsCancelled(evt)) { return resetAction(); } + p.action.startX = evt.m.readerX; + p.action.startY = evt.m.readerY; + p.action.screenX = evt.m.screenX; + p.action.screenY = evt.m.screenY; + listenForMoveAndEnd(cmptContactMove, cmptContactEnd); + } + + + function cmptContactMove(evt) { + if (actionIsEmpty()) { return; } + if (actionIsCancelled(evt)) { return resetAction(); } + + // Can't prevent mousemove, so has no effect there. Preventing default + // for touchmove will override scrolling, while still allowing selection. + evt.preventDefault(); + } + + + function cmptContactEnd(evt) { + if (actionIsEmpty()) { return; } + if (actionIsCancelled(evt)) { return resetAction(); } + p.action.endX = evt.m.readerX; + p.action.endY = evt.m.readerY; + if (Math.abs(p.action.endX - p.action.startX) < k.LEEWAY) { + p.action.dir = p.action.startX > halfway() ? k.FORWARDS : k.BACKWARDS; + } else { + p.action.dir = p.action.startX > p.action.endX ? k.FORWARDS : k.BACKWARDS; + } + + if (dispatch('monocle:magic:contact', evt)) { + invoke('start', evt); + invoke('end', evt); + } + p.action = {}; + } + + + // Adds two new properties to evt.m: + // - readerX + // - readerY + // + // Calculated as the offset of the click from the top left of reader element. + // + // Then calls the passed function. + // + function translatorFunction(registrant, callback) { + return function (evt) { + translatingReaderOffset(registrant, evt, callback); + } + } + + + function translatingReaderOffset(registrant, evt, callback) { + if (typeof p.action.screenX != 'undefined') { + evt.m.readerX = p.action.startX + (evt.m.screenX - p.action.screenX); + evt.m.readerY = p.action.startY + (evt.m.screenY - p.action.screenY); + } else { + var dr = document.documentElement.getBoundingClientRect(); + var rr = p.parts.reader.getBoundingClientRect(); + rr = { left: rr.left - dr.left, top: rr.top - dr.top } + + if (evt.view == window) { + evt.m.readerX = Math.round(evt.m.pageX - rr.left); + evt.m.readerY = Math.round(evt.m.pageY - rr.top); + } else { + var er = registrant.getBoundingClientRect(); + er = { left: er.left - dr.left, top: er.top - dr.top } + evt.m.readerX = Math.round((er.left - rr.left) + evt.m.clientX); + evt.m.readerY = Math.round((er.top - rr.top) + evt.m.clientY); + } + } + + callback(evt); + } + + + function halfway() { + return p.parts.reader.offsetWidth / 2; + } + + + function resetAction() { + p.action = {}; + deafenContactListeners(); + } + + + function actionIsCancelled(evt) { + var win = evt.target.ownerDocument.defaultView; + return (evt.defaultPrevented || !win.getSelection().isCollapsed); + } + + + function actionIsEmpty() { + return typeof p.action.startX == 'undefined'; + } + + + // Returns true if the event WAS NOT cancelled. + function dispatch(evtName, trigger) { + var rr = p.parts.reader.getBoundingClientRect(); + var evtData = { + trigger: trigger, + start: { x: p.action.startX, y: p.action.startY }, + end: { x: p.action.endX, y: p.action.endY }, + max: { x: rr.right - rr.left, y: rr.bottom - rr.top } + } + return p.reader.dispatchEvent(evtName, evtData, true); + } + + + function invoke(evtType, evt) { + if (p.evtCallbacks[evtType]) { + p.evtCallbacks[evtType](p.action.dir, evt.m.readerX, evt.m.readerY, API); + } + } + + + API.enable = enable; + API.disable = disable; + + initialize(); + + return API; +} + + +Monocle.Panels.Magic.LEEWAY = 3; +Monocle.Panels.Magic.FORWARDS = 1; +Monocle.Panels.Magic.BACKWARDS = -1; +Monocle.Dimensions.Columns = function (pageDiv) { + + var API = { constructor: Monocle.Dimensions.Columns } + var k = API.constants = API.constructor; + var p = API.properties = { + page: pageDiv, + reader: pageDiv.m.reader, + length: 0, + width: 0 + } + + // Logically, forceColumn browsers can't have a gap, because that would + // make the minWidth > 200%. But how much greater? Not worth the effort. + k.GAP = Monocle.Browser.env.forceColumns ? 0 : 20; + + function update(callback) { + setColumnWidth(); + Monocle.defer(function () { + p.length = columnCount(); + if (Monocle.DEBUG) { + console.log( + 'page['+p.page.m.pageIndex+'] -> '+p.length+ + ' ('+p.page.m.activeFrame.m.component.properties.id+')' + ); + } + callback(p.length); + }); + } + + + function setColumnWidth() { + var pdims = pageDimensions(); + var ce = columnedElement(); + + p.width = pdims.width; + + var rules = Monocle.Styles.rulesToString(k.STYLE["columned"]); + rules += Monocle.Browser.css.toCSSDeclaration('column-width', pdims.col+'px'); + rules += Monocle.Browser.css.toCSSDeclaration('column-gap', k.GAP+'px'); + rules += Monocle.Browser.css.toCSSDeclaration('column-fill', 'auto'); + rules += Monocle.Browser.css.toCSSDeclaration('transform', 'none'); + + if (Monocle.Browser.env.forceColumns && ce.scrollHeight > pdims.height) { + rules += Monocle.Styles.rulesToString(k.STYLE['column-force']); + if (Monocle.DEBUG) { + console.warn("Force columns ("+ce.scrollHeight+" > "+pdims.height+")"); + } + } + + if (ce.style.cssText != rules) { + // Update offset because we're translating to zero. + p.page.m.offset = 0; + + // IE10 hack. + if (Monocle.Browser.env.documentElementHasScrollbars) { + ce.ownerDocument.documentElement.style.overflow = 'hidden'; + } + + // Apply body style changes. + ce.style.cssText = rules; + + if (Monocle.Browser.env.scrollToApplyStyle) { + ce.scrollLeft = 0; + } + } + } + + + // Returns the element to which columns CSS should be applied. + // + function columnedElement() { + return p.page.m.activeFrame.contentDocument.body; + } + + + // Returns the width of the offsettable area of the columned element. By + // definition, the number of pages is always this divided by the + // width of a single page (eg, the client area of the columned element). + // + function columnedWidth() { + var bd = columnedElement(); + var de = p.page.m.activeFrame.contentDocument.documentElement; + + var w = Math.max(bd.scrollWidth, de.scrollWidth); + + // Add one because the final column doesn't have right gutter. + // w += k.GAP; + + if (!Monocle.Browser.env.widthsIgnoreTranslate && p.page.m.offset) { + w += p.page.m.offset; + } + return w; + } + + + function pageDimensions() { + var elem = p.page.m.sheafDiv; + var w = elem.clientWidth; + if (elem.getBoundingClientRect) { w = elem.getBoundingClientRect().width; } + if (Monocle.Browser.env.roundPageDimensions) { w = Math.round(w); } + return { col: w, width: w + k.GAP, height: elem.clientHeight } + } + + + function columnCount() { + return Math.ceil(columnedWidth() / pageDimensions().width) + } + + + function locusToOffset(locus) { + return pageDimensions().width * (locus.page - 1); + } + + + // Moves the columned element to the offset implied by the locus. + // + // The 'transition' argument is optional, allowing the translation to be + // animated. If not given, no change is made to the columned element's + // transition property. + // + function translateToLocus(locus, transition) { + var offset = locusToOffset(locus); + p.page.m.offset = offset; + translateToOffset(offset, transition); + return offset; + } + + + function translateToOffset(offset, transition) { + var ce = columnedElement(); + if (transition) { + Monocle.Styles.affix(ce, "transition", transition); + } + // NB: can't use setX as it causes a flicker on iOS. + Monocle.Styles.affix(ce, "transform", "translateX(-"+offset+"px)"); + } + + + function percentageThroughOfNode(target) { + if (!target) { return 0; } + var doc = p.page.m.activeFrame.contentDocument; + var offset = 0; + if (Monocle.Browser.env.findNodesByScrolling) { + // First, remove translation... + translateToOffset(0); + + // Store scroll offsets for all windows. + var win = s = p.page.m.activeFrame.contentWindow; + var scrollers = [ + [win, win.scrollX, win.scrollY], + [window, window.scrollX, window.scrollY] + ]; + //while (s != s.parent) { scrollers.push([s, s.scrollX]); s = s.parent; } + + if (Monocle.Browser.env.sheafIsScroller) { + var scroller = p.page.m.sheafDiv; + var x = scroller.scrollLeft; + target.scrollIntoView(); + offset = scroller.scrollLeft; + } else { + var scroller = win; + var x = scroller.scrollX; + target.scrollIntoView(); + offset = scroller.scrollX; + } + + // Restore scroll offsets for all windows. + while (s = scrollers.shift()) { + s[0].scrollTo(s[1], s[2]); + } + + // ... finally, replace translation. + translateToOffset(p.page.m.offset); + } else { + offset = target.getBoundingClientRect().left; + offset -= doc.body.getBoundingClientRect().left; + } + + // We know at least 1px will be visible, and offset should not be 0. + offset += 1; + + // Percent is the offset divided by the total width of the component. + var percent = offset / (p.length * p.width); + + // Page number would be offset divided by the width of a single page. + // var pageNum = Math.ceil(offset / pageDimensions().width); + + return percent; + } + + + API.update = update; + API.percentageThroughOfNode = percentageThroughOfNode; + + API.locusToOffset = locusToOffset; + API.translateToLocus = translateToLocus; + + return API; +} + + +Monocle.Dimensions.Columns.STYLE = { + // Most of these are already applied to body, but they're repeated here + // in case columnedElement() is ever anything other than body. + "columned": { + "margin": "0", + "padding": "0", + "height": "100%", + "width": "100%", + "position": "absolute" + }, + "column-force": { + "min-width": "200%", + "overflow": "hidden" + } +} +; +Monocle.Flippers.Slider = function (reader) { + + var API = { constructor: Monocle.Flippers.Slider } + var k = API.constants = API.constructor; + var p = API.properties = { + reader: reader, + pageCount: 2, + activeIndex: 1, + turnData: {}, + nextPageReady: true + } + + + function initialize() { + p.reader.listen("monocle:componentchanging", showWaitControl); + } + + + function addPage(pageDiv) { + pageDiv.m.dimensions = new Monocle.Dimensions.Columns(pageDiv); + + // BROWSERHACK: Firefox 4 is prone to beachballing on the first page turn + // unless a zeroed translateX has been applied to the page div. + Monocle.Styles.setX(pageDiv, 0); + } + + + function visiblePages() { + return [upperPage()]; + } + + + function listenForInteraction(panelClass) { + if (typeof panelClass != "function") { + panelClass = k.DEFAULT_PANELS_CLASS; + if (!panelClass) { + console.warn("Invalid panel class.") + } + } + p.panels = new panelClass( + API, + { + 'start': lift, + 'move': turning, + 'end': release, + 'cancel': release + } + ); + } + + + function getPlace(pageDiv) { + pageDiv = pageDiv || upperPage(); + return pageDiv.m ? pageDiv.m.place : null; + } + + + function moveTo(locus, callback) { + var cb = function () { + if (typeof callback == "function") { callback(); } + announceTurn(); + } + setPage(upperPage(), locus, function () { prepareNextPage(cb) }); + } + + + function setPage(pageDiv, locus, onLoad, onFail) { + p.reader.getBook().setOrLoadPageAt( + pageDiv, + locus, + function (locus) { + pageDiv.m.dimensions.translateToLocus(locus); + Monocle.defer(onLoad); + }, + onFail + ); + } + + + function upperPage() { + return p.reader.dom.find('page', p.activeIndex); + } + + + function lowerPage() { + return p.reader.dom.find('page', (p.activeIndex + 1) % 2); + } + + + function flipPages() { + upperPage().style.zIndex = 1; + lowerPage().style.zIndex = 2; + return p.activeIndex = (p.activeIndex + 1) % 2; + } + + + function lift(dir, boxPointX) { + if (p.turnData.lifting || p.turnData.releasing) { return; } + + p.reader.selection.deselect(); + + p.turnData.points = { + start: boxPointX, + min: boxPointX, + max: boxPointX + } + p.turnData.lifting = true; + + var place = getPlace(); + + if (dir == k.FORWARDS) { + if (place.onLastPageOfBook()) { + p.reader.dispatchEvent( + 'monocle:boundaryend', + { + locus: getPlace().getLocus({ direction : dir }), + page: upperPage() + } + ); + resetTurnData(); + return; + } + onGoingForward(boxPointX); + } else if (dir == k.BACKWARDS) { + if (place.onFirstPageOfBook()) { + p.reader.dispatchEvent( + 'monocle:boundarystart', + { + locus: getPlace().getLocus({ direction : dir }), + page: upperPage() + } + ); + resetTurnData(); + return; + } + onGoingBackward(boxPointX); + } else { + console.warn("Invalid direction: " + dir); + } + } + + + function turning(dir, boxPointX) { + if (!p.turnData.points) { return; } + if (p.turnData.lifting || p.turnData.releasing) { return; } + checkPoint(boxPointX); + slideToCursor(boxPointX, null, "0"); + } + + + function release(dir, boxPointX) { + if (!p.turnData.points) { + return; + } + if (p.turnData.lifting) { + p.turnData.releaseArgs = [dir, boxPointX]; + return; + } + if (p.turnData.releasing) { + return; + } + + checkPoint(boxPointX); + + p.turnData.releasing = true; + + if (dir == k.FORWARDS) { + if ( + p.turnData.points.tap || + p.turnData.points.start - boxPointX > 60 || + p.turnData.points.min >= boxPointX + ) { + // Completing forward turn + slideOut(afterGoingForward); + } else { + // Cancelling forward turn + slideIn(afterCancellingForward); + } + } else if (dir == k.BACKWARDS) { + if ( + p.turnData.points.tap || + boxPointX - p.turnData.points.start > 60 || + p.turnData.points.max <= boxPointX + ) { + // Completing backward turn + slideIn(afterGoingBackward); + } else { + // Cancelling backward turn + slideOut(afterCancellingBackward); + } + } else { + console.warn("Invalid direction: " + dir); + } + } + + + function checkPoint(boxPointX) { + p.turnData.points.min = Math.min(p.turnData.points.min, boxPointX); + p.turnData.points.max = Math.max(p.turnData.points.max, boxPointX); + p.turnData.points.tap = p.turnData.points.max - p.turnData.points.min < 10; + } + + + function onGoingForward(x) { + if (p.nextPageReady == false) { + prepareNextPage(function () { lifted(x); }, resetTurnData); + } else { + lifted(x); + } + } + + + function onGoingBackward(x) { + var lp = lowerPage(), up = upperPage(); + var onFail = function () { slideOut(afterCancellingBackward); } + + if (Monocle.Browser.env.offscreenRenderingClipped) { + // set lower to "the page before upper" + setPage( + lp, + getPlace(up).getLocus({ direction: k.BACKWARDS }), + function () { + // flip lower to upper, ready to slide in from left + flipPages(); + // move lower off the screen to the left + jumpOut(lp, function () { lifted(x); }); + }, + onFail + ); + } else { + jumpOut(lp, function () { + flipPages(); + setPage( + lp, + getPlace(up).getLocus({ direction: k.BACKWARDS }), + function () { lifted(x); }, + onFail + ); + }); + } + } + + + function afterGoingForward() { + var up = upperPage(), lp = lowerPage(); + flipPages(); + jumpIn(up, function () { prepareNextPage(announceTurn); }); + } + + + function afterGoingBackward() { + announceTurn(); + } + + + function afterCancellingForward() { + announceCancel(); + } + + + function afterCancellingBackward() { + flipPages(); // flip upper to lower + jumpIn(lowerPage(), function () { prepareNextPage(announceCancel); }); + } + + + // Prepares the lower page to show the next page after the current page, + // and calls onLoad when done. + // + // Note that if the next page is a new component, and it fails to load, + // onFail will be called. If onFail is not supplied, onLoad will be called. + // + function prepareNextPage(onLoad, onFail) { + setPage( + lowerPage(), + getPlace().getLocus({ direction: k.FORWARDS }), + onLoad, + function () { + onFail ? onFail() : onLoad(); + p.nextPageReady = false; + } + ); + } + + + function lifted(x) { + p.turnData.lifting = false; + p.reader.dispatchEvent('monocle:turning'); + var releaseArgs = p.turnData.releaseArgs; + if (releaseArgs) { + p.turnData.releaseArgs = null; + release(releaseArgs[0], releaseArgs[1]); + } else if (x) { + slideToCursor(x); + } + } + + + function announceTurn() { + p.nextPageReady = true; + p.reader.dispatchEvent('monocle:turn'); + resetTurnData(); + } + + + function announceCancel() { + p.reader.dispatchEvent('monocle:turn:cancel'); + resetTurnData(); + } + + + function resetTurnData() { + hideWaitControl(); + p.turnData = {}; + } + + + function setX(elem, x, options, callback) { + var duration, transition; + + if (!options.duration) { + duration = 0; + } else { + duration = parseInt(options.duration); + } + + if (Monocle.Browser.env.supportsTransition) { + Monocle.Styles.transitionFor( + elem, + 'transform', + duration, + options.timing, + options.delay + ); + + if (Monocle.Browser.env.supportsTransform3d) { + Monocle.Styles.affix(elem, 'transform', 'translate3d('+x+'px,0,0)'); + } else { + Monocle.Styles.affix(elem, 'transform', 'translateX('+x+'px)'); + } + + if (typeof callback == "function") { + if (duration && Monocle.Styles.getX(elem) != x) { + Monocle.Events.afterTransition(elem, callback); + } else { + Monocle.defer(callback); + } + } + } else { + // Old-school JS animation. + elem.currX = elem.currX || 0; + var completeTransition = function () { + elem.currX = x; + Monocle.Styles.setX(elem, x); + if (typeof callback == "function") { callback(); } + } + if (!duration) { + completeTransition(); + } else { + var stamp = (new Date()).getTime(); + var frameRate = 40; + var step = (x - elem.currX) * (frameRate / duration); + var stepFn = function () { + var destX = elem.currX + step; + var timeElapsed = ((new Date()).getTime() - stamp) >= duration; + var pastDest = (destX > x && elem.currX < x) || + (destX < x && elem.currX > x); + if (timeElapsed || pastDest) { + completeTransition(); + } else { + Monocle.Styles.setX(elem, destX); + elem.currX = destX; + setTimeout(stepFn, frameRate); + } + } + stepFn(); + } + } + } + + + function jumpIn(pageDiv, callback) { + opts = { duration: (Monocle.Browser.env.stickySlideOut ? 1 : 0) } + setX(pageDiv, 0, opts, callback); + } + + + function jumpOut(pageDiv, callback) { + setX(pageDiv, 0 - pageDiv.offsetWidth, { duration: 0 }, callback); + } + + + // NB: Slides are always done by the visible upper page. + + function slideIn(callback) { + setX(upperPage(), 0, slideOpts(), callback); + } + + + function slideOut(callback) { + setX(upperPage(), 0 - upperPage().offsetWidth, slideOpts(), callback); + } + + + function slideToCursor(cursorX, callback, duration) { + setX( + upperPage(), + Math.min(0, cursorX - upperPage().offsetWidth), + { duration: duration || k.FOLLOW_DURATION }, + callback + ); + } + + + function slideOpts() { + var opts = { timing: 'ease-in', duration: 320 } + var now = (new Date()).getTime(); + if (p.lastSlide && now - p.lastSlide < 1500) { opts.duration *= 0.5; } + p.lastSlide = now; + return opts; + } + + + function ensureWaitControl() { + if (p.waitControl) { return; } + p.waitControl = { + createControlElements: function (holder) { + return holder.dom.make('div', 'flippers_slider_wait'); + } + } + p.reader.addControl(p.waitControl, 'page'); + } + + + function showWaitControl() { + ensureWaitControl(); + p.reader.dom.find('flippers_slider_wait', 0).style.opacity = 1; + p.reader.dom.find('flippers_slider_wait', 1).style.opacity = 1; + } + + + function hideWaitControl() { + ensureWaitControl(); + p.reader.dom.find('flippers_slider_wait', 0).style.opacity = 0; + p.reader.dom.find('flippers_slider_wait', 1).style.opacity = 0; + } + + + // THIS IS THE CORE API THAT ALL FLIPPERS MUST PROVIDE. + API.pageCount = p.pageCount; + API.addPage = addPage; + API.getPlace = getPlace; + API.moveTo = moveTo; + API.listenForInteraction = listenForInteraction; + + // OPTIONAL API - WILL BE INVOKED (WHERE RELEVANT) IF PROVIDED. + API.visiblePages = visiblePages; + + initialize(); + + return API; +} + + +// Constants +Monocle.Flippers.Slider.DEFAULT_PANELS_CLASS = Monocle.Panels.TwoPane; +Monocle.Flippers.Slider.FORWARDS = 1; +Monocle.Flippers.Slider.BACKWARDS = -1; +Monocle.Flippers.Slider.FOLLOW_DURATION = 100; +Monocle.Flippers.Scroller = function (reader, setPageFn) { + + var API = { constructor: Monocle.Flippers.Scroller } + var k = API.constants = API.constructor; + var p = API.properties = { + pageCount: 1, + duration: 300 + } + + + function initialize() { + p.reader = reader; + p.setPageFn = setPageFn; + } + + + function addPage(pageDiv) { + pageDiv.m.dimensions = new Monocle.Dimensions.Columns(pageDiv); + } + + + function page() { + return p.reader.dom.find('page'); + } + + + function listenForInteraction(panelClass) { + if (typeof panelClass != "function") { + panelClass = k.DEFAULT_PANELS_CLASS; + } + p.panels = new panelClass( + API, + { + 'end': turn + } + ); + } + + + function turn(dir) { + if (p.turning) { return; } + p.reader.selection.deselect(); + moveTo({ page: getPlace().pageNumber() + dir}); + p.reader.dispatchEvent('monocle:turning'); + } + + + function getPlace() { + return page().m.place; + } + + + function moveTo(locus, callback) { + var fn = frameToLocus; + if (typeof callback == "function") { + fn = function (locus) { frameToLocus(locus); callback(locus); } + } + p.reader.getBook().setOrLoadPageAt(page(), locus, fn); + } + + + function frameToLocus(locus) { + if (locus.boundarystart || locus.boundaryend) { return; } + p.turning = true; + var dims = page().m.dimensions; + var fr = page().m.activeFrame; + var bdy = fr.contentDocument.body; + var anim = true; + if (p.activeComponent != fr.m.component) { + // No animation. + p.activeComponent = fr.m.component; + dims.translateToLocus(locus, "none"); + Monocle.defer(turned); + } else if (Monocle.Browser.env.supportsTransition) { + // Native animation. + dims.translateToLocus(locus, p.duration+"ms ease-in 0ms"); + Monocle.Events.afterTransition(bdy, turned); + } else { + // Old-school JS animation. + var x = dims.locusToOffset(locus); + var finalX = 0 - x; + var stamp = (new Date()).getTime(); + var frameRate = 40; + var currX = p.currX || 0; + var step = (finalX - currX) * (frameRate / p.duration); + var stepFn = function () { + var destX = currX + step; + if ( + (new Date()).getTime() - stamp > p.duration || + Math.abs(currX - finalX) <= Math.abs((currX + step) - finalX) + ) { + Monocle.Styles.setX(bdy, finalX); + turned(); + } else { + Monocle.Styles.setX(bdy, destX); + currX = destX; + setTimeout(stepFn, frameRate); + } + p.currX = destX; + } + stepFn(); + } + } + + + function turned() { + p.turning = false; + p.reader.dispatchEvent('monocle:turn'); + } + + + // THIS IS THE CORE API THAT ALL FLIPPERS MUST PROVIDE. + API.pageCount = p.pageCount; + API.addPage = addPage; + API.getPlace = getPlace; + API.moveTo = moveTo; + API.listenForInteraction = listenForInteraction; + + initialize(); + + return API; +} + +Monocle.Flippers.Scroller.speed = 200; // How long the animation takes +Monocle.Flippers.Scroller.rate = 20; // frame-rate of the animation +Monocle.Flippers.Scroller.FORWARDS = 1; +Monocle.Flippers.Scroller.BACKWARDS = -1; +Monocle.Flippers.Scroller.DEFAULT_PANELS_CLASS = Monocle.Panels.TwoPane; +Monocle.Flippers.Instant = function (reader) { + + var API = { constructor: Monocle.Flippers.Instant } + var k = API.constants = API.constructor; + var p = API.properties = { + pageCount: 1 + } + + + function initialize() { + p.reader = reader; + } + + + function addPage(pageDiv) { + pageDiv.m.dimensions = new Monocle.Dimensions.Columns(pageDiv); + } + + + function getPlace() { + return page().m.place; + } + + + function moveTo(locus, callback) { + var fn = frameToLocus; + if (typeof callback == "function") { + fn = function (locus) { frameToLocus(locus); callback(locus); } + } + p.reader.getBook().setOrLoadPageAt(page(), locus, fn); + } + + + function listenForInteraction(panelClass) { + if (typeof panelClass != "function") { + if (Monocle.Browser.on.Kindle3) { + panelClass = Monocle.Panels.eInk; + } + panelClass = panelClass || k.DEFAULT_PANELS_CLASS; + } + if (!panelClass) { throw("Panels not found."); } + p.panels = new panelClass(API, { 'end': turn }); + } + + + function page() { + return p.reader.dom.find('page'); + } + + + function turn(dir) { + p.reader.selection.deselect(); + moveTo({ page: getPlace().pageNumber() + dir}); + p.reader.dispatchEvent('monocle:turning'); + } + + + function frameToLocus(locus) { + page().m.dimensions.translateToLocus(locus); + Monocle.defer(function () { p.reader.dispatchEvent('monocle:turn'); }); + } + + + // THIS IS THE CORE API THAT ALL FLIPPERS MUST PROVIDE. + API.pageCount = p.pageCount; + API.addPage = addPage; + API.getPlace = getPlace; + API.moveTo = moveTo; + API.listenForInteraction = listenForInteraction; + + initialize(); + + return API; +} + +Monocle.Flippers.Instant.FORWARDS = 1; +Monocle.Flippers.Instant.BACKWARDS = -1; +Monocle.Flippers.Instant.DEFAULT_PANELS_CLASS = Monocle.Panels.TwoPane; + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/monocle/scripts/monoctrl.js b/resources/monocle/scripts/monoctrl.js new file mode 100644 index 000000000..5e7155265 --- /dev/null +++ b/resources/monocle/scripts/monoctrl.js @@ -0,0 +1,985 @@ +Monocle.Controls.Contents = function (reader) { + + var API = { constructor: Monocle.Controls.Contents } + var k = API.constants = API.constructor; + var p = API.properties = { + reader: reader + } + + + function createControlElements() { + var div = reader.dom.make('div', 'controls_contents_container'); + contentsForBook(div, reader.getBook()); + return div; + } + + + function contentsForBook(div, book) { + while (div.hasChildNodes()) { + div.removeChild(div.firstChild); + } + var list = div.dom.append('ol', 'controls_contents_list'); + + var contents = book.properties.contents; + for (var i = 0; i < contents.length; ++i) { + chapterBuilder(list, contents[i], 0); + } + } + + + function chapterBuilder(list, chp, padLvl) { + var index = list.childNodes.length; + var li = list.dom.append('li', 'controls_contents_chapter', index); + var span = li.dom.append( + 'span', + 'controls_contents_chapterTitle', + index, + { html: chp.title } + ); + span.style.paddingLeft = padLvl + "em"; + + var invoked = function () { + p.reader.skipToChapter(chp.src); + p.reader.hideControl(API); + } + + Monocle.Events.listenForTap(li, invoked, 'controls_contents_chapter_active'); + + if (chp.children) { + for (var i = 0; i < chp.children.length; ++i) { + chapterBuilder(list, chp.children[i], padLvl + 1); + } + } + } + + + API.createControlElements = createControlElements; + + return API; +} +; +Monocle.Controls.Magnifier = function (reader) { + + var API = { constructor: Monocle.Controls.Magnifier } + var k = API.constants = API.constructor; + var p = API.properties = { + buttons: [], + magnified: false + } + + + function initialize() { + p.reader = reader; + } + + + function createControlElements(holder) { + var btn = holder.dom.make('div', 'controls_magnifier_button'); + btn.smallA = btn.dom.append('span', 'controls_magnifier_a', { text: 'A' }); + btn.largeA = btn.dom.append('span', 'controls_magnifier_A', { text: 'A' }); + p.buttons.push(btn); + Monocle.Events.listenForTap(btn, toggleMagnification); + return btn; + } + + + function toggleMagnification(evt) { + var opacities; + p.magnified = !p.magnified; + if (p.magnified) { + opacities = [0.3, 1]; + p.reader.formatting.setFontScale(k.MAGNIFICATION, true); + } else { + opacities = [1, 0.3]; + p.reader.formatting.setFontScale(null, true); + } + + for (var i = 0; i < p.buttons.length; i++) { + p.buttons[i].smallA.style.opacity = opacities[0]; + p.buttons[i].largeA.style.opacity = opacities[1]; + } + } + + API.createControlElements = createControlElements; + + initialize(); + + return API; +} + + +Monocle.Controls.Magnifier.MAGNIFICATION = 1.2; +// A panel is an invisible column of interactivity. When contact occurs +// (mousedown, touchstart), the panel expands to the full width of its +// container, to catch all interaction events and prevent them from hitting +// other things. +// +// Panels are used primarily to provide hit zones for page flipping +// interactions, but you can do whatever you like with them. +// +// After instantiating a panel and adding it to the reader as a control, +// you can call listenTo() with a hash of methods for any of 'start', 'move' +// 'end' and 'cancel'. +// +Monocle.Controls.Panel = function () { + + var API = { constructor: Monocle.Controls.Panel } + var k = API.constants = API.constructor; + var p = API.properties = { + evtCallbacks: {} + } + + function createControlElements(cntr) { + p.div = cntr.dom.make('div', k.CLS.panel); + p.div.dom.setStyles(k.DEFAULT_STYLES); + Monocle.Events.listenForContact( + p.div, + { + 'start': start, + 'move': move, + 'end': end, + 'cancel': cancel + }, + { useCapture: false } + ); + return p.div; + } + + + function setDirection(dir) { + p.direction = dir; + } + + + function listenTo(evtCallbacks) { + p.evtCallbacks = evtCallbacks; + } + + + function deafen() { + p.evtCallbacks = {} + } + + + function start(evt) { + p.contact = true; + evt.m.offsetX += p.div.offsetLeft; + evt.m.offsetY += p.div.offsetTop; + expand(); + invoke('start', evt); + } + + + function move(evt) { + if (!p.contact) { + return; + } + invoke('move', evt); + } + + + function end(evt) { + if (!p.contact) { + return; + } + Monocle.Events.deafenForContact(p.div, p.listeners); + contract(); + p.contact = false; + invoke('end', evt); + } + + + function cancel(evt) { + if (!p.contact) { + return; + } + Monocle.Events.deafenForContact(p.div, p.listeners); + contract(); + p.contact = false; + invoke('cancel', evt); + } + + + function invoke(evtType, evt) { + if (p.evtCallbacks[evtType]) { + p.evtCallbacks[evtType](p.direction, evt.m.offsetX, evt.m.offsetY, API); + } + evt.preventDefault(); + } + + + function expand() { + if (p.expanded) { + return; + } + p.div.dom.addClass(k.CLS.expanded); + p.expanded = true; + } + + + function contract(evt) { + if (!p.expanded) { + return; + } + p.div.dom.removeClass(k.CLS.expanded); + p.expanded = false; + } + + + API.createControlElements = createControlElements; + API.listenTo = listenTo; + API.deafen = deafen; + API.expand = expand; + API.contract = contract; + API.setDirection = setDirection; + + return API; +} + + +Monocle.Controls.Panel.CLS = { + panel: 'panel', + expanded: 'controls_panel_expanded' +} +Monocle.Controls.Panel.DEFAULT_STYLES = { + position: 'absolute', + height: '100%' +} +; +Monocle.Controls.PlaceSaver = function (bookId) { + + var API = { constructor: Monocle.Controls.PlaceSaver } + var k = API.constants = API.constructor; + var p = API.properties = {} + + + function initialize() { + applyToBook(bookId); + } + + + function assignToReader(reader) { + p.reader = reader; + p.reader.listen('monocle:turn', savePlaceToCookie); + } + + + function applyToBook(bookId) { + p.bkTitle = bookId.toLowerCase().replace(/[^a-z0-9]/g, ''); + p.prefix = k.COOKIE_NAMESPACE + p.bkTitle + "."; + } + + + function setCookie(key, value, days) { + var expires = ""; + if (days) { + var d = new Date(); + d.setTime(d.getTime() + (days * 24 * 60 * 60 * 1000)); + expires = "; expires="+d.toGMTString(); + } + var path = "; path=/"; + document.cookie = p.prefix + key + "=" + value + expires + path; + return value; + } + + + function getCookie(key) { + if (!document.cookie) { + return null; + } + var regex = new RegExp(p.prefix + key + "=(.+?)(;|$)"); + var matches = document.cookie.match(regex); + if (matches) { + return matches[1]; + } else { + return null; + } + } + + + function savePlaceToCookie() { + var place = p.reader.getPlace(); + setCookie( + "component", + encodeURIComponent(place.componentId()), + k.COOKIE_EXPIRES_IN_DAYS + ); + setCookie( + "percent", + place.percentageThrough(), + k.COOKIE_EXPIRES_IN_DAYS + ); + } + + + function savedPlace() { + var locus = { + componentId: getCookie('component'), + percent: getCookie('percent') + } + if (locus.componentId && locus.percent) { + locus.componentId = decodeURIComponent(locus.componentId); + locus.percent = parseFloat(locus.percent); + return locus; + } else { + return null; + } + } + + + function restorePlace() { + var locus = savedPlace(); + if (locus) { + p.reader.moveTo(locus); + } + } + + + API.assignToReader = assignToReader; + API.savedPlace = savedPlace; + API.restorePlace = restorePlace; + + initialize(); + + return API; +} + +Monocle.Controls.PlaceSaver.COOKIE_NAMESPACE = "monocle.controls.placesaver."; +Monocle.Controls.PlaceSaver.COOKIE_EXPIRES_IN_DAYS = 7; // Set to 0 for session-based expiry. +; +Monocle.Controls.Scrubber = function (reader) { + + var API = { constructor: Monocle.Controls.Scrubber } + var k = API.constants = API.constructor; + var p = API.properties = {} + + + function initialize() { + p.reader = reader; + p.reader.listen('monocle:turn', updateNeedles); + updateNeedles(); + } + + + function pixelToPlace(x, cntr) { + if (!p.componentIds) { + p.componentIds = p.reader.getBook().properties.componentIds; + p.componentWidth = 100 / p.componentIds.length; + } + var pc = (x / cntr.offsetWidth) * 100; + var cmpt = p.componentIds[Math.floor(pc / p.componentWidth)]; + var cmptPc = ((pc % p.componentWidth) / p.componentWidth); + return { componentId: cmpt, percentageThrough: cmptPc }; + } + + + function placeToPixel(place, cntr) { + if (!p.componentIds) { + p.componentIds = p.reader.getBook().properties.componentIds; + p.componentWidth = 100 / p.componentIds.length; + } + var componentIndex = p.componentIds.indexOf(place.componentId()); + var pc = p.componentWidth * componentIndex; + pc += place.percentageThrough() * p.componentWidth; + return Math.round((pc / 100) * cntr.offsetWidth); + } + + + function updateNeedles() { + if (p.hidden || !p.reader.dom.find(k.CLS.container)) { + return; + } + var place = p.reader.getPlace(); + var x = placeToPixel(place, p.reader.dom.find(k.CLS.container)); + var needle, i = 0; + for (var i = 0, needle; needle = p.reader.dom.find(k.CLS.needle, i); ++i) { + setX(needle, x - needle.offsetWidth / 2); + p.reader.dom.find(k.CLS.trail, i).style.width = x + "px"; + } + } + + + function setX(node, x) { + var cntr = p.reader.dom.find(k.CLS.container); + x = Math.min(cntr.offsetWidth - node.offsetWidth, x); + x = Math.max(x, 0); + Monocle.Styles.setX(node, x); + } + + + function createControlElements(holder) { + var cntr = holder.dom.make('div', k.CLS.container); + var track = cntr.dom.append('div', k.CLS.track); + var needleTrail = cntr.dom.append('div', k.CLS.trail); + var needle = cntr.dom.append('div', k.CLS.needle); + var bubble = cntr.dom.append('div', k.CLS.bubble); + + var cntrListeners, bodyListeners; + + var moveEvt = function (evt, x) { + evt.preventDefault(); + x = (typeof x == "number") ? x : evt.m.registrantX; + var place = pixelToPlace(x, cntr); + setX(needle, x - needle.offsetWidth / 2); + var book = p.reader.getBook(); + var chps = book.chaptersForComponent(place.componentId); + var cmptIndex = p.componentIds.indexOf(place.componentId); + var chp = chps[Math.floor(chps.length * place.percentageThrough)]; + if (cmptIndex > -1 && book.properties.components[cmptIndex]) { + var actualPlace = Monocle.Place.FromPercentageThrough( + book.properties.components[cmptIndex], + place.percentageThrough + ); + chp = actualPlace.chapterInfo() || chp; + } + + if (chp) { + bubble.innerHTML = chp.title; + } + setX(bubble, x - bubble.offsetWidth / 2); + + p.lastX = x; + return place; + } + + var endEvt = function (evt) { + var place = moveEvt(evt, p.lastX); + p.reader.moveTo({ + percent: place.percentageThrough, + componentId: place.componentId + }); + Monocle.Events.deafenForContact(cntr, cntrListeners); + Monocle.Events.deafenForContact(document.body, bodyListeners); + bubble.style.display = "none"; + } + + var startFn = function (evt) { + bubble.style.display = "block"; + moveEvt(evt); + cntrListeners = Monocle.Events.listenForContact( + cntr, + { move: moveEvt } + ); + bodyListeners = Monocle.Events.listenForContact( + document.body, + { end: endEvt } + ); + } + + Monocle.Events.listenForContact(cntr, { start: startFn }); + + return cntr; + } + + + API.createControlElements = createControlElements; + API.updateNeedles = updateNeedles; + + initialize(); + + return API; +} + +Monocle.Controls.Scrubber.CLS = { + container: 'controls_scrubber_container', + track: 'controls_scrubber_track', + needle: 'controls_scrubber_needle', + trail: 'controls_scrubber_trail', + bubble: 'controls_scrubber_bubble' +} +; +Monocle.Controls.Spinner = function (reader) { + + var API = { constructor: Monocle.Controls.Spinner } + var k = API.constants = API.constructor; + var p = API.properties = { + reader: reader, + divs: [], + repeaters: {}, + showForPages: [] + } + + + function createControlElements(cntr) { + var anim = cntr.dom.make('div', 'controls_spinner_anim'); + anim.dom.append('div', 'controls_spinner_inner'); + p.divs.push(anim); + return anim; + } + + + function registerSpinEvent(startEvtType, stopEvtType) { + var label = startEvtType; + p.reader.listen(startEvtType, function (evt) { spin(label, evt) }); + p.reader.listen(stopEvtType, function (evt) { spun(label, evt) }); + } + + + // Registers spin/spun event handlers for certain time-consuming events. + // + function listenForUsualDelays() { + registerSpinEvent('monocle:componentloading', 'monocle:componentloaded'); + registerSpinEvent('monocle:componentchanging', 'monocle:componentchange'); + registerSpinEvent('monocle:resizing', 'monocle:resize'); + registerSpinEvent('monocle:jumping', 'monocle:jump'); + registerSpinEvent('monocle:recalculating', 'monocle:recalculated'); + p.reader.listen('monocle:notfound', forceSpun); + p.reader.listen('monocle:componentfailed', forceSpun); + } + + + // Displays the spinner. Both arguments are optional. + // + function spin(label, evt) { + label = label || k.GENERIC_LABEL; + p.repeaters[label] = true; + p.reader.showControl(API); + + // If the delay is on a page other than the page we've been assigned to, + // don't show the animation. p.global ensures that if an event affects + // all pages, the animation is always shown, even if other events in this + // spin cycle are page-specific. + var page = (evt && evt.m && evt.m.page) ? evt.m.page : null; + if (page && p.divs.length > 1) { + p.showForPages[page.m.pageIndex] = true; + } else { + p.global = true; + p.reader.dispatchEvent('monocle:modal:on'); + } + for (var i = 0; i < p.divs.length; ++i) { + var show = (p.global || p.showForPages[i]) ? true : false; + p.divs[i].dom[show ? 'removeClass' : 'addClass']('dormant'); + } + } + + + // Stops displaying the spinner. Both arguments are optional. + // + function spun(label, evt) { + label = label || k.GENERIC_LABEL; + p.repeaters[label] = false; + for (var l in p.repeaters) { + if (p.repeaters[l]) { return; } + } + forceSpun(); + } + + + function forceSpun() { + if (p.global) { p.reader.dispatchEvent('monocle:modal:off'); } + p.global = false; + p.repeaters = {}; + p.showForPages = []; + for (var i = 0; i < p.divs.length; ++i) { + p.divs[i].dom.addClass('dormant'); + } + } + + + API.createControlElements = createControlElements; + API.registerSpinEvent = registerSpinEvent; + API.listenForUsualDelays = listenForUsualDelays; + API.spin = spin; + API.spun = spun; + API.forceSpun = forceSpun; + + return API; +} + +Monocle.Controls.Spinner.GENERIC_LABEL = "generic"; +Monocle.Controls.Stencil = function (reader, behaviorClasses) { + + var API = { constructor: Monocle.Controls.Stencil } + var k = API.constants = API.constructor; + var p = API.properties = { + reader: reader, + behaviors: [], + components: {}, + masks: [] + } + + + // Create the stencil container and listen for draw/update events. + // + function createControlElements(holder) { + behaviorClasses = behaviorClasses || k.DEFAULT_BEHAVIORS; + for (var i = 0, ii = behaviorClasses.length; i < ii; ++i) { + addBehavior(behaviorClasses[i]); + } + p.container = holder.dom.make('div', k.CLS.container); + p.reader.listen('monocle:turning', hide); + p.reader.listen('monocle:turn:cancel', show); + p.reader.listen('monocle:turn', update); + p.reader.listen('monocle:stylesheetchange', update); + p.reader.listen('monocle:resize', update); + update(); + return p.container; + } + + + // Pass this method an object that responds to 'findElements(doc)' with + // an array of DOM elements for that document, and to 'fitMask(elem, mask)'. + // + // After you have added all your behaviors this way, you would typically + // call update() to make them take effect immediately. + // + function addBehavior(bhvrClass) { + var bhvr = new bhvrClass(API); + if (typeof bhvr.findElements != 'function') { + console.warn('Missing "findElements" method for behavior: %o', bhvr); + } + if (typeof bhvr.fitMask != 'function') { + console.warn('Missing "fitMask" method for behavior: %o', bhvr); + } + p.behaviors.push(bhvr); + } + + + // Resets any pre-calculated rectangles for the active component, + // recalculates them, and forces masks to be "drawn" (moved into the new + // rectangular locations). + // + function update() { + var visPages = p.reader.visiblePages(); + if (!visPages || !visPages.length) { return; } + var pageDiv = visPages[0]; + var cmptId = pageComponentId(pageDiv); + if (!cmptId) { return; } + p.components[cmptId] = null; + calculateRectangles(pageDiv); + draw(); + } + + + function hide() { + p.container.style.display = 'none'; + } + + + function show() { + p.container.style.display = 'block'; + } + + + // Removes any existing masks. + function clear() { + while (p.container.childNodes.length) { + p.container.removeChild(p.container.lastChild); + } + } + + + // Aligns the stencil container to the shape of the page, then moves the + // masks to sit above any currently visible rectangles. + // + function draw() { + var pageDiv = p.reader.visiblePages()[0]; + var cmptId = pageComponentId(pageDiv); + if (!p.components[cmptId]) { + return; + } + + // Position the container. + alignToComponent(pageDiv); + + // Clear old masks. + clear(); + + // Layout the masks. + if (!p.disabled) { + show(); + var rects = p.components[cmptId]; + if (rects && rects.length) { + layoutRectangles(pageDiv, rects); + } + } + } + + + // Iterate over all the
    elements in the active component, and + // create an array of rectangular points corresponding to their positions. + // + function calculateRectangles(pageDiv) { + var cmptId = pageComponentId(pageDiv); + if (!p.components[cmptId]) { + p.components[cmptId] = []; + } else { + return; + } + + var doc = pageDiv.m.activeFrame.contentDocument; + var offset = getOffset(pageDiv); + + for (var b = 0, bb = p.behaviors.length; b < bb; ++b) { + var bhvr = p.behaviors[b]; + var elems = bhvr.findElements(doc); + for (var i = 0; i < elems.length; ++i) { + var elem = elems[i]; + if (elem.getClientRects) { + var r = elem.getClientRects(); + for (var j = 0; j < r.length; j++) { + p.components[cmptId].push({ + element: elem, + behavior: bhvr, + left: Math.ceil(r[j].left + offset.l), + top: Math.ceil(r[j].top), + width: Math.floor(r[j].width), + height: Math.floor(r[j].height) + }); + } + } + } + } + + return p.components[cmptId]; + } + + + // Update location of visible rectangles - creating as required. + // + function layoutRectangles(pageDiv, rects) { + var offset = getOffset(pageDiv); + var visRects = []; + for (var i = 0; i < rects.length; ++i) { + if (rectVisible(rects[i], offset.l, offset.l + offset.w)) { + visRects.push(rects[i]); + } + } + + for (i = 0; i < visRects.length; ++i) { + var r = visRects[i]; + var cr = { + left: r.left - offset.l, + top: r.top, + width: r.width, + height: r.height + }; + var mask = createMask(r.element, r.behavior); + mask.dom.setStyles({ + display: 'block', + left: cr.left+"px", + top: cr.top+"px", + width: cr.width+"px", + height: cr.height+"px", + position: 'absolute' + }); + mask.stencilRect = cr; + } + } + + + // Find the offset position in pixels from the left of the current page. + // + function getOffset(pageDiv) { + return { + l: pageDiv.m.offset || 0, + w: pageDiv.m.dimensions.properties.width + }; + } + + + // Is this area presently on the screen? + // + function rectVisible(rect, l, r) { + return rect.left >= l && rect.left < r; + } + + + // Returns the active component id for the given page, or the current + // page if no argument passed in. + // + function pageComponentId(pageDiv) { + pageDiv = pageDiv || p.reader.visiblePages()[0]; + if (!pageDiv.m.activeFrame.m.component) { return; } + return pageDiv.m.activeFrame.m.component.properties.id; + } + + + // Positions the stencil container over the active frame. + // + function alignToComponent(pageDiv) { + cmpt = pageDiv.m.activeFrame.parentNode; + p.container.dom.setStyles({ + left: cmpt.offsetLeft+"px", + top: cmpt.offsetTop+"px" + }); + } + + + function createMask(element, bhvr) { + var mask = p.container.dom.append(bhvr.maskTagName || 'div', k.CLS.mask); + Monocle.Events.listenForContact(mask, { + start: function () { p.reader.dispatchEvent('monocle:magic:halt'); }, + move: function (evt) { evt.preventDefault(); }, + end: function () { p.reader.dispatchEvent('monocle:magic:init'); } + }); + bhvr.fitMask(element, mask); + return mask; + } + + + // Make the active masks visible (by giving them a class -- override style + // in monoctrl.css). + // + function toggleHighlights() { + var cls = k.CLS.highlights; + if (p.container.dom.hasClass(cls)) { + p.container.dom.removeClass(cls); + } else { + p.container.dom.addClass(cls); + } + } + + + function disable() { + p.disabled = true; + draw(); + } + + + function enable() { + p.disabled = false; + draw(); + } + + + function filterElement(elem, behavior) { + if (typeof behavior.filterElement == 'function') { + return behavior.filterElement(elem); + } + return elem; + } + + + function maskAssigned(elem, mask, behavior) { + if (typeof behavior.maskAssigned == 'function') { + return behavior.maskAssigned(elem, mask); + } + return false; + } + + + API.createControlElements = createControlElements; + API.addBehavior = addBehavior; + API.draw = draw; + API.update = update; + API.toggleHighlights = toggleHighlights; + + return API; +} + + +Monocle.Controls.Stencil.CLS = { + container: 'controls_stencil_container', + mask: 'controls_stencil_mask', + highlights: 'controls_stencil_highlighted' +} + + + +Monocle.Controls.Stencil.Links = function (stencil) { + var API = { constructor: Monocle.Controls.Stencil.Links } + + // Optionally specify the HTML tagname of the mask. + API.maskTagName = 'a'; + + // Returns an array of all the elements in the given doc that should + // be covered with a stencil mask for interactivity. + // + // (Hint: doc.querySelectorAll() is your friend.) + // + API.findElements = function (doc) { + return doc.querySelectorAll('a[href]'); + } + + + // Return an element. It should usually be a child of the container element, + // with a className of the given maskClass. You set up the interactivity of + // the mask element here. + // + API.fitMask = function (link, mask) { + var hrefObject = deconstructHref(link); + + if (hrefObject.internal) { + mask.setAttribute('href', 'javascript:"Skip to chapter"'); + mask.onclick = function (evt) { + stencil.properties.reader.skipToChapter(hrefObject.internal); + evt.preventDefault(); + return false; + } + } else { + mask.setAttribute('href', hrefObject.external); + mask.setAttribute('target', '_blank'); + mask.onclick = function (evt) { return true; } + } + + link.onclick = function (evt) { + evt.preventDefault(); + return false; + } + } + + + // Returns an object with either: + // + // - an 'external' property -- an absolute URL with a protocol, + // host & etc, which should be treated as an external resource (eg, + // open in new window) + // + // OR + // + // - an 'internal' property -- a relative URL (with optional hash anchor), + // that is treated as a link to component in the book + // + // A weird but useful property of tags is that while + // link.getAttribute('href') will return the actual string value of the + // attribute (eg, 'foo.html'), link.href will return the absolute URL (eg, + // 'http://example.com/monocles/foo.html'). + // + function deconstructHref(elem) { + var loc = document.location; + var origin = loc.protocol+'//'+loc.host; + var href = elem.href; + var path = href.substring(origin.length); + var ext = { external: href }; + + // Anchor tags with 'target' attributes are always external URLs. + if (elem.getAttribute('target')) { + return ext; + } + // URLs with a different protocol or domain are always external. + //console.log("Domain test: %s <=> %s", origin, href); + if (href.indexOf(origin) != 0) { + return ext; + } + + // If it is in a sub-path of the current path, it's internal. + var topPath = loc.pathname.replace(/[^\/]*\.[^\/]+$/,''); + if (topPath[topPath.length - 1] != '/') { + topPath += '/'; + } + //console.log("Sub-path test: %s <=> %s", topPath, path); + if (path.indexOf(topPath) == 0) { + return { internal: path.substring(topPath.length) } + } + + // If it's a root-relative URL and it's in our list of component ids, + // it's internal. + var cmptIds = stencil.properties.reader.getBook().properties.componentIds; + for (var i = 0, ii = cmptIds.length; i < ii; ++i) { + //console.log("Component test: %s <=> %s", cmptIds[i], path); + if (path.indexOf(cmptIds[i]) == 0) { + return { internal: path } + } + } + + // Otherwise it's external. + return ext; + } + + + return API; +} + + +Monocle.Controls.Stencil.DEFAULT_BEHAVIORS = [Monocle.Controls.Stencil.Links]; diff --git a/resources/monocle/styles/monocore.css b/resources/monocle/styles/monocore.css new file mode 100644 index 000000000..02b495171 --- /dev/null +++ b/resources/monocle/styles/monocore.css @@ -0,0 +1,195 @@ +/*=========================================================================== + +This is a base-level Monocle stylesheet. It assumes no class-prefix has been +given to the Reader during initialisation - if one has, you can copy and +modify this stylesheet accordingly. + +---------------------------------------------------------------------------*/ + +/* The reader object that holds pretty much everything. + * (A direct child of the element passed to reader initialisation). */ + +div.monelem_container { + background-color: black; +} + + +/* The div that mimics a leaf of paper in a book. */ +div.monelem_page { + background: white; + top: 0; + left: 0; + bottom: 3px; + right: 5px; + border-right: 1px solid #999; +} + + +/* The div within the page that determines page margins. */ +div.monelem_sheaf { + top: 1em; + left: 1em; + bottom: 1em; + right: 1em; +} + + +/* The iframe within the page that loads the content of the book. */ +div.monelem_component { +} + + +/* A panel that sits above the entire reader object, holding controls. */ +div.monelem_overlay { +} + + +/* A full-size panel to display an announcement (iframe or div) */ +div.monelem_billboard_container { + background: #FFF; + position: absolute; + top: 0; + left: 0; + height: 100%; + width: 100%; + z-index: 2000; + -webkit-transform: scale(0); + -moz-transform: scale(0); + transform: scale(0); + -webkit-transform-origin: -0 -0; + -moz-transform-origin: -0 -0; + transform-origin: -0 -0; +} + +.monelem_billboard_inner { + height: 100%; + width: 100%; + border: none; + overflow: auto; + /*-webkit-overflow-scrolling: touch;*/ /* This is sexy, but crashy. */ +} + +div.monelem_billboard_inner { + min-width: 100%; + min-height: 100%; + text-align: center; + vertical-align: middle; + display: -webkit-box; + -webkit-box-pack: center; + -webkit-box-align: center; +} + + +div.monelem_billboard_close { + position: absolute; + top: 0; + right: 0; + width: 50px; + height: 30px; + color: white; + background: #C00; + cursor: pointer; + border-bottom-left-radius: 4px; + text-shadow: 1px 1px 1px #900; + font: 9pt Helvetica Neue, Helvetica, sans-serif; +} + +div.monelem_billboard_close:after { + display: block; + content: 'Close'; + width: 100%; + line-height: 30px; + text-align: center; +} + +div.monelem_book_fatality { + font-family: Helvetica Neue, Helvetica, sans-serif; + margin: 0 auto; + max-width: 75%; +} + +div.monelem_book_fatality p { + line-height: 1.4; +} + + +/*=========================================================================== + PANELS +---------------------------------------------------------------------------*/ + + +.monelem_panels_imode_panel { + background: rgba(255,255,255,0.7); + opacity: 0; +} + +.monelem_panels_imode_backwardsPanel { + -webkit-box-shadow: 1px 1px 3px #777; + -moz-box-shadow: 1px 1px 3px #777; + box-shadow: 1px 1px 3px #777; +} + +.monelem_panels_imode_forwardsPanel { + -webkit-box-shadow: -1px 1px 3px #777; + -moz-box-shadow: -1px 1px 3px #777; + box-shadow: -1px 1px 3px #777; +} + +.monelem_panels_imode_centralPanel { +} + +.monelem_panels_imode_toggleIcon { + position: absolute; + right: 0; + bottom: 0; + width: 50px; + height: 50px; + background-repeat: no-repeat; + background-position: center center; +} + +/* If you modify this you could significantly change the way panels work. */ +div.monelem_controls_panel_expanded { + left: 0 !important; + width: 100% !important; + z-index: 1001 !important; +} + +/*=========================================================================== + Flippers +---------------------------------------------------------------------------*/ + +div.monelem_flippers_slider_wait { + position: absolute; + right: 0px; + top: 0px; + width: 92px; + height: 112px; + background-repeat: no-repeat; + -webkit-background-size: 100%; + -moz-background-size: 100%; + background-size: 100%; +} + +@media screen and (max-width: 640px) { + div.monelem_flippers_slider_wait { + width: 61px; + height: 75px; + } +} + + +/*=========================================================================== + DATA URIs + + These are data-uri packed images, inlined for loading speed and simplicity. + Placed at the end of this file because they're visually noisy... +---------------------------------------------------------------------------*/ + +div.monelem_panels_imode_toggleIcon { + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB8AAAAaCAYAAABPY4eKAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1%2B%2FAAAABV0RVh0Q3JlYXRpb24gVGltZQAzMC82LzEwBMfmVwAAABx0RVh0U29mdHdhcmUAQWRvYmUgRmlyZXdvcmtzIENTNXG14zYAAANYSURBVEiJtdZbiNVVFMfxj8cx85JkIGlqSESgOGA9WIQgGmTRUyRaYFJDnUWYGV2eyiCpkIbEKJI1UqYvUkmFDxFBgpghonajSDCM7hcxLSnt4ulh%2F2c4HufMTOH8Xs75%2F%2Ffa67v3%2Bu%2B91hphGJWZNUzCXJyKiHd6xxqNhhGDTB6NOViAyzARY3EaP%2BNL7MCBiPi9Ze4leBlTsR9jcCnuiYgDbeGZeV4F7EINe7EP3%2BJ49W4GrsZ8NPAGXouIk5k5F93YFhHPVT5H4kbcjaX1ev3kWfDMPB9P4ko8ERE7BopONWcOVmMc1uBRrG8Oc5Ptq1hdr9cPdrQMTMUWfBQRCweD9ioiPsQtmbkeu7G8P3ClsZSI98EzcxqeUsLXM1RwZs7ErRiJKXgQN2Tmzoj4qsV2Hn7BYcq369UaHIqI5yPizyGCx2MPfsRVOBoR6%2FA%2BNmXmqCbbm%2FAiMiJO9cEzcwEuwLODwMZk5oXVLYA6PouIF%2FC6cvBgI37D0mreStyJroh4r9df785XYGtEHG8Hfnjb1w08Xu2qq3regtOZuaka2whV5NZieWY%2BhkV4ICJ2N%2FusZeYMJQm8NdCuuxdPH4HENGzsXjx9REQcqRxvR2dEfNBrHxF7lHywGPXW7085cEvwZkScHAheaRz%2BwngcqyAnlEPan%2Fbh5oj4rr%2FBDlyOXUMA%2Fx%2F9oFytM5SZs3t6epbWlOtxeJjg%2BzEmMye3vF%2BCYx2YhdFnTTs3OoQT2JqZ3TiC2zETyzrwrnIwhkMTqwVsxW24GLsiYmWj0dCBo2gNy7nSRfgpIjZjM6WU1ut1lHt%2BGLOHCd6J79sN1pSkMSUzJwwD%2FBoD5I9aRHyiFIVFQ3D2j1KR%2Fh7MMDPnY1JE7GwLr3434N5BnI3GFRiFzuai0Ub34aWBDGr0pcKPM%2FPpqovpT11KoVinNAvXt1lkLTNXKFesXU1HUz3HI0plWqW0QGcoIjYoERpMy7AS17b2da06o43KzLF4RanRzwwx3%2FfOHYW7lL5ubUR83p9do9Ho%2B99fDzcZDynfdxPejog%2FBoCOxHW4AxOwKiK%2BaGc%2FILzJ6ULcXznciwM4qFSzCUob3Km0UCeU3W5v5%2B8%2FwZsWMQvzlN1Nq8C%2F4ht8qkRm72B%2B%2BoP%2FC0sEOftJmUbfAAAAAElFTkSuQmCC); +} + +div.monelem_flippers_slider_wait { + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFwAAABwCAMAAACkX%2BcnAAAB0VBMVEUAAACDg4OEhISFhYWGhoaHh4eIiIiJiIiJiYmKioqLi4uMjIyNjY2Ojo6Pj4%2BQkJCRkZGSkpKTk5OUlJSVlZWWlpaXl5eYmJiZmZmampqbm5ucnJycnJ2dnZ2dnZ6dnZ%2Benp6enp%2Bfn5%2Bfn6CgoKCgoKGhoKChoaGioqKjo6OkpKSlpaWmpaWmpqaoqKiqqqqrq6usrKytra2urq6wsLCxsbGzs7O0tLS0tLW1tbW1tba1tbe2tri4uLi4uLm4uLq6ury7u7y8vLy8vL28vL%2B9vb2%2Bvr6%2Bvr%2B%2Fv7%2B%2Fv8HAwMDAwMLAwMPBwcPCwsPExMTExMXFxcXGxsbHx8fIyMjJycrOztDOztHPz9DPz9HR0dTS0tTT09TT09XU1NbU1NfV1dfW1tjW1tnX19fX19rY2Nra2tva2tzd3eDe3t7f39%2Fh4eHi4uLl5enn5%2Bnp6ezp6e3q6u3q6u7r6%2B7r6%2B%2Fs7O%2Fs7PDt7fDt7fHu7vHu7vLv7%2B%2Fv7%2FLv7%2FPw8PDw8PPw8PTx8fTx8fXy8vXy8vbz8%2Fbz8%2Ff09Pf09Pj19fj19fn29vn39%2Fn39%2Fr4%2BPr4%2BPv5%2Bfv6%2Bvv6%2Bvz7%2B%2Fz7%2B%2F38%2FP39%2Ff39%2Ff7%2B%2Fv7%2B%2Fv%2F%2F%2F%2F%2BHSJEZAAAAAXRSTlMAQObYZgAAA5dJREFUaN61lk1uE0EQhd%2BrsQlREAgkFkQKLJByteQU3IIdd2OBYIFASFmAFLurWPT0uOfXme6aWUXy6PNL9XPXR3z6DSI93wQ0GkHjzweapM%2B%2Btn8SMAERPzKQQKN7IDRhD2APgkbumucvXp24T3s%2BH47H7%2F9U1AxmpvaDzV5IUMBfD0CbQXYPly93K%2BEiwneqphpMVc3e7p492zciQhGKNN2bX%2F42shJOEQFIQgAKgfgdpvFz7d58%2FPO4Fn5PiggBAUkAYhoUMJipwU5vhsfjWjhESMTsBChQVVMDYICadfjD4VAAFyGYZVcN7Vzar4iP6frkd5RuLjG7WlCFwdSy4ICtPlBAKJLNhYBq6HKf8IHrx4J7IQX5maqFLHeC3yrWwyEiFACSzlTVVFNuzQZTAG%2BrLoQwVT1kubvGF4wlVj2vi2isuvWrbiXJIUISYKwL5qpuWgbvXQHxSCeqbiXwvOrpClC1QdXViuAQUnpXgE1U%2FSb%2BUwVVF7JfdTWN2G4uFyiaeZz6oOpB1drzTF0sSw6ySdc5Y%2FZe1SPeCpPfS6p6yq4arK16V5eyAwWEp6oTEKpqewXEygBW9iMabzsAZjqoOkuTL227tjJvSg8UaG%2FGhW33obSK8d4dVj1eAV3VrXQsuBtXvd12XdWteCxg2nbobbuU2xQsHst42zHe6lllypOnbcdUeZ62HUzNoOXJz4vdpZXDz4rde5TDz4rdsQ6%2BLHZNxVjOip3VJD8ndjVtOSt2rEp%2BRuxCHXxZ7G6tCr4sdhUX1xPETmvhC2KndWNZFjtUjmVR7KRyLItiF2qTL4ndtdXCF8Tuqhq%2BIHaonfmi2Ek1fEHsQjV8YdtVt2VR7DzgM2J36QCfFbsbB%2Fi82MEBPit2HvBZsfMYy6zYuSSfq7oLfE7sLpzgk2J37QKfETt1gc%2BJnQ98Rux84NNiJ07wSbELTvBpsXOCT4rdRz%2F4WOzMCz4pdl7wKbGDG3xC7NzGMiV2jvCx2PnNfELsbvzgY7FrHOFjsXOEj7YdHeFjsfOF96sePOFjsXOED8XutSt8sO2uXOFDsfOFD6ruCx9U3Rc%2BEDt3eC52zvC%2B2DnD%2B2LnDe9V3RveEzt3eC527vBc7NzhudhtAe%2BuAH94VnV%2FeCZ2G8BzscMmUxdgi5lnYrcF%2FCR2wCZHSvftP9x2m8DTttsEnsRuK7hs8%2FPPxG4beCt2G8HbbbcNPG67reAUEfwHRePBMkvuZ4wAAAAASUVORK5CYII%3D); +} diff --git a/resources/monocle/styles/monoctrl.css b/resources/monocle/styles/monoctrl.css new file mode 100644 index 000000000..89e8ab687 --- /dev/null +++ b/resources/monocle/styles/monoctrl.css @@ -0,0 +1,169 @@ +/*=========================================================================== + CONTROLS + + The standard Monocle stylesheet for the optional Monocle controls. See + comments for monocore.css, which apply here too. +---------------------------------------------------------------------------*/ + +/* Contents */ + +div.monelem_controls_contents_container { + position: absolute; + width: 75%; + height: 75%; + left: 12.5%; + top: 12.5%; + background: #EEE; + border: 2px solid #F7F7F7; + border-radius: 9px; + overflow-y: auto; + -webkit-overflow-scrolling: touch; + -moz-border-radius: 9px; + -webkit-border-radius: 9px; + box-shadow: 1px 2px 6px rgba(0,0,0,0.5); + -moz-box-shadow: 1px 2px 6px rgba(0,0,0,0.5); + -webkit-box-shadow: 1px 2px 6px rgba(0,0,0,0.5); +} + +ol.monelem_controls_contents_list { + margin: 6px; + padding: 0; +} + +li.monelem_controls_contents_chapter { + list-style: none; + line-height: 220%; + padding-left: 1em; + padding-right: 2em; + border-bottom: 2px groove #FEFEFE; + cursor: pointer; +} + +li.monelem_controls_contents_chapter_active { + background: #999; + color: white; +} + +/* Magnifier */ + +.monelem_controls_magnifier_button { + cursor: pointer; + color: #555; + position: absolute; + top: 2px; + right: 10px; + padding: 0 2px; +} + +.monelem_controls_magnifier_a { + font-size: 11px; +} + +.monelem_controls_magnifier_A { + font-size: 18px; + opacity: 0.3; +} + + +/* Spinner */ + +.monelem_controls_spinner_anim { + position: absolute; + width: 100%; + height: 100%; + background-color: white; + background-repeat: no-repeat; + background-position: center center; +} +.monelem_controls_spinner_anim.monelem_dormant { + width: 0; + height: 0; +} + + +/* Scrubber */ + +div.monelem_controls_scrubber_container { + position: absolute; + left: 1em; + right: 1em; + bottom: 4px; + height: 30px; + background: rgba(255,255,255,0.8); +} + +div.monelem_controls_scrubber_track { + margin-top: 10px; + height: 5px; + border: 1px solid #999; + cursor: pointer; +} + +div.monelem_controls_scrubber_needle { + position: absolute; + width: 14px; + height: 14px; + top: 5px; + background: #CCC; + border: 1px solid #999; + border-radius: 8px; + -moz-border-radius: 8px; + -webkit-border-radius: 8px; +} + +div.monelem_controls_scrubber_trail { + position: absolute; + background: #DDD; + top: 11px; + left: 1px; + height: 5px; +} + +div.monelem_controls_scrubber_bubble { + display: none; + position: absolute; + padding: 1em; + min-width: 20%; + max-width: 30%; + bottom: 2.5em; + background: rgba(0, 0, 0, 0.9); + color: #CCC; + font: bold 12px Lucida Grande, Tahoma, Helvetica, Arial, sans-serif; + white-space: nowrap; + text-overflow: ellipsis; + overflow: hidden; + border-radius: 10px; + -moz-border-radius: 10px; + -webkit-border-radius: 10px; +} + + +/* Stencil */ +div.monelem_controls_stencil_container { + position: absolute; + top: 0; + left: 0; + width: 0; + height: 0; +} + +.monelem_controls_stencil_mask { + display: block; + position: absolute; +} + +div.monelem_controls_stencil_highlighted .monelem_controls_stencil_mask { + background: rgba(0,0,255,0.15); +} + + +/*=========================================================================== + DATA URIs + + These are data-uri packed images, inlined for loading speed and simplicity. + Placed at the end of this file because they're visually noisy... +---------------------------------------------------------------------------*/ + +div.monelem_controls_spinner_anim { + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAAA0CAMAAAANBM47AAAAA3NCSVQICAjb4U/gAAAACXBIWXMAAAsSAAALEgHS3X78AAAAHHRFWHRTb2Z0d2FyZQBBZG9iZSBGaXJld29ya3MgQ1M1cbXjNgAAABV0RVh0Q3JlYXRpb24gVGltZQAxNy81LzEwnOhoKAAAAE5QTFRFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAxKKmWQAAABp0Uk5TAAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBl0wLilAAAC8klEQVQYGZXBB2LjOAADQFCimtVFEoD//9HLbrJxipzoZoBToYptUwV8V/Xrsc8RP6i7aduPXHI69mWIAR9UY6Is5rnCuTBsWXeLkijbTFOLf7okW6R8zxEnwphskfIrifJdW4u/RtlpbGLsdjoHfDNkSZTSNg192w3jchSJEtcawCRzDvgjLPINX1SbSSvNXcC7eNuLXpQuTFbp8CZkH/isyS68H0PAF+0iUzxoNni33HPAR51UxDHgRLObslLEw3TPFT7oKPqIeOImURs+WJ0CHlqKXgLOxL4NgyRqxbuqeMNDXURPOBNWSokquRRP+GeVOzwcLlpwJmx3WVJuY2ZRi1ezfOBhdNGGU52ZhrloBzqSucKLerdLxLtIKlc4Nd9LA6wuNTC5aAbQZzs3eFhE9Tg3mw2wqkQgHCZrTJK3iIcoasMTvXX0E30EAK2k+Wbrho8mky2eCLslSz3+2ERKucVHIZsbnqp2WWXEX60ossMnrakeP+jGocabg9SGzyaXHHDRpOIO/zRjDWCTNlzVsLjFm4bODapE33BZoke8mVy8oqXY4rLNXvFmEnXDKJYaly3SjlchkSOwiCngstFMeDXLE4CVygGX3e6FawUgzFIKANbiHHDZ7U4qL7c5SWzxYqFywGXjvVD3F3Zu8ccs5gqXzeYx7CTTWOOvnmTEZZu0ItSxrvAmZrrHZYme8dkhLbiqLkUDPlvMA1cNIiM+613Y4KJNSviiprTgmrrQM75arVzhkllUxFetqBlXVEXa8d0hMeKCxVSH73rRG37XidpxZlXRiN9UhYUtztRFVI+fhUPFE851KlSHn4TNxTueGU2yx3PVbipVeGpxIaeAJ2IynRv8YHEp3iNOjRRdGvxotGjONb7pD7M4RfyiK6ZclhYf1bdDprRW+FW9SZSUlqGtq1BVTTftRaKce1zS7bIpWyW/oK0i38tU4apupWyRsijKVhoj/o+6W45cJEoqaR+bgP8txH5a1nUZ2gq/+Q/51T5MhuG3fQAAAABJRU5ErkJggg==); +} diff --git a/resources/simonpioli/sortelements/README.md b/resources/simonpioli/sortelements/README.md new file mode 100644 index 000000000..44b124244 --- /dev/null +++ b/resources/simonpioli/sortelements/README.md @@ -0,0 +1,35 @@ +sort +--- + +The sort plugin is a very basic low-level element sorting function that allows you to sort DOM elements with a custom comparator (similar to `Array.prototype.sort`). + +Assuming the following markup: + +
      +
    • Banana
    • +
    • Carrot
    • +
    • Apple
    • +
    + +You could sort the items alphabetically like so: + + $('li').sortElements(function(a, b){ + return $(a).text() > $(b).text() ? 1 : -1; + }); + +That would result in: + +
      +
    • Apple
    • +
    • Banana
    • +
    • Carrot
    • +
    + +It also let's you specify what element will be sorted. The current collection's elements will be those referred to as `a` and `b` on each call of the comparator, but you might not want those elements to be the ones to move. E.g. you might want it to be a parent. For example, when sorting a table column, you would sort by the `` elements, but the elements you actually want to move within the DOM are the `` (each ``'s parent): + + $('td').sortElements(myComparator, function(){ + // Return a reference to the desired element: + return this.parentNode; + }); + +See more info here: [http://james.padolsey.com/javascript/sorting-elements-with-jquery/](http://james.padolsey.com/javascript/sorting-elements-with-jquery/). \ No newline at end of file diff --git a/js/jquery.sortElements.js b/resources/simonpioli/sortelements/jquery.sortElements.js similarity index 65% rename from js/jquery.sortElements.js rename to resources/simonpioli/sortelements/jquery.sortElements.js index bf1902d10..1cd6bf879 100644 --- a/js/jquery.sortElements.js +++ b/resources/simonpioli/sortelements/jquery.sortElements.js @@ -1,69 +1,69 @@ -/** - * jQuery.fn.sortElements - * -------------- - * @author James Padolsey (http://james.padolsey.com) - * @version 0.11 - * @updated 18-MAR-2010 - * -------------- - * @param Function comparator: - * Exactly the same behaviour as [1,2,3].sort(comparator) - * - * @param Function getSortable - * A function that should return the element that is - * to be sorted. The comparator will run on the - * current collection, but you may want the actual - * resulting sort to occur on a parent or another - * associated element. - * - * E.g. $('td').sortElements(comparator, function(){ - * return this.parentNode; - * }) - * - * The 's parent () will be sorted instead - * of the itself. - */ -jQuery.fn.sortElements = (function(){ - - var sort = [].sort; - - return function(comparator, getSortable) { - - getSortable = getSortable || function(){return this;}; - - var placements = this.map(function(){ - - var sortElement = getSortable.call(this), - parentNode = sortElement.parentNode, - - // Since the element itself will change position, we have - // to have some way of storing it's original position in - // the DOM. The easiest way is to have a 'flag' node: - nextSibling = parentNode.insertBefore( - document.createTextNode(''), - sortElement.nextSibling - ); - - return function() { - - if (parentNode === this) { - throw new Error( - "You can't sort elements if any one is a descendant of another." - ); - } - - // Insert before flag: - parentNode.insertBefore(this, nextSibling); - // Remove flag: - parentNode.removeChild(nextSibling); - - }; - - }); - - return sort.call(this, comparator).each(function(i){ - placements[i].call(getSortable.call(this)); - }); - - }; - +/** +* jQuery.fn.sortElements +* -------------- +* @author James Padolsey (http://james.padolsey.com) +* @version 0.11 +* @updated 18-MAR-2010 +* -------------- +* @param Function comparator: +* Exactly the same behaviour as [1,2,3].sort(comparator) +* +* @param Function getSortable +* A function that should return the element that is +* to be sorted. The comparator will run on the +* current collection, but you may want the actual +* resulting sort to occur on a parent or another +* associated element. +* +* E.g. $('td').sortElements(comparator, function(){ +* return this.parentNode; +* }) +* +* The 's parent () will be sorted instead +* of the itself. +*/ +jQuery.fn.sortElements = (function(){ + + var sort = [].sort; + + return function(comparator, getSortable) { + + getSortable = getSortable || function(){return this;}; + + var placements = this.map(function(){ + + var sortElement = getSortable.call(this), + parentNode = sortElement.parentNode, + + // Since the element itself will change position, we have + // to have some way of storing it's original position in + // the DOM. The easiest way is to have a 'flag' node: + nextSibling = parentNode.insertBefore( + document.createTextNode(''), + sortElement.nextSibling + ); + + return function() { + + if (parentNode === this) { + throw new Error( + "You can't sort elements if any one is a descendant of another." + ); + } + + // Insert before flag: + parentNode.insertBefore(this, nextSibling); + // Remove flag: + parentNode.removeChild(nextSibling); + + }; + + }); + + return sort.call(this, comparator).each(function(i){ + placements[i].call(getSortable.call(this)); + }); + + }; + })(); \ No newline at end of file diff --git a/resources/transliteration-data/x00.php b/resources/transliteration-data/x00.php new file mode 100644 index 000000000..8db608fc9 --- /dev/null +++ b/resources/transliteration-data/x00.php @@ -0,0 +1,44 @@ + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 0x90 => '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 0xA0 => ' ', '!', 'C/', 'PS', '$?', 'Y=', '|', 'SS', '"', '(c)', 'a', '<<', '!', '', '(r)', '-', + 0xB0 => 'deg', '+-', '2', '3', '\'', 'u', 'P', '*', ',', '1', 'o', '>>', '1/4', '1/2', '3/4', '?', + 0xC0 => 'A', 'A', 'A', 'A', 'A', 'A', 'AE', 'C', 'E', 'E', 'E', 'E', 'I', 'I', 'I', 'I', + 0xD0 => 'D', 'N', 'O', 'O', 'O', 'O', 'O', 'x', 'O', 'U', 'U', 'U', 'U', 'Y', 'Th', 'ss', + 0xE0 => 'a', 'a', 'a', 'a', 'a', 'a', 'ae', 'c', 'e', 'e', 'e', 'e', 'i', 'i', 'i', 'i', + 0xF0 => 'd', 'n', 'o', 'o', 'o', 'o', 'o', '/', 'o', 'u', 'u', 'u', 'u', 'y', 'th', 'y', +]; + +// Overrides for Danish input. +$variant['da'] = [ + 0xC5 => 'Aa', + 0xC6 => 'Ae', + 0xD8 => 'Oe', + 0xE5 => 'aa', + 0xE6 => 'ae', + 0xF8 => 'oe', +]; + +// Overrides for German input. +$variant['de'] = [ + 0xC4 => 'Ae', + 0xD6 => 'Oe', + 0xDC => 'Ue', + 0xE4 => 'ae', + 0xF6 => 'oe', + 0xFC => 'ue', + 0xDF => 'ss', +]; + +// Overrides for Spanish input. +$variant['es'] = [ + 0xE1 => 'a', + 0xE9 => 'e', + 0xED => 'i', + 0xF3 => 'o', + 0xFA => 'u', + 0xF1 => 'n', +]; diff --git a/resources/transliteration-data/x01.php b/resources/transliteration-data/x01.php new file mode 100644 index 000000000..885ede596 --- /dev/null +++ b/resources/transliteration-data/x01.php @@ -0,0 +1,36 @@ + 'A', 'a', 'A', 'a', 'A', 'a', 'C', 'c', 'C', 'c', 'C', 'c', 'C', 'c', 'D', 'd', + 0x10 => 'D', 'd', 'E', 'e', 'E', 'e', 'E', 'e', 'E', 'e', 'E', 'e', 'G', 'g', 'G', 'g', + 0x20 => 'G', 'g', 'G', 'g', 'H', 'h', 'H', 'h', 'I', 'i', 'I', 'i', 'I', 'i', 'I', 'i', + 0x30 => 'I', 'i', 'IJ', 'ij', 'J', 'j', 'K', 'k', 'k', 'L', 'l', 'L', 'l', 'L', 'l', 'L', + 0x40 => 'l', 'L', 'l', 'N', 'n', 'N', 'n', 'N', 'n', '\'n', 'NG', 'ng', 'O', 'o', 'O', 'o', + 0x50 => 'O', 'o', 'OE', 'oe', 'R', 'r', 'R', 'r', 'R', 'r', 'S', 's', 'S', 's', 'S', 's', + 0x60 => 'S', 's', 'T', 't', 'T', 't', 'T', 't', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', + 0x70 => 'U', 'u', 'U', 'u', 'W', 'w', 'Y', 'y', 'Y', 'Z', 'z', 'Z', 'z', 'Z', 'z', 's', + 0x80 => 'b', 'B', 'B', 'b', '6', '6', 'O', 'C', 'c', 'D', 'D', 'D', 'd', 'd', '3', '@', + 0x90 => 'E', 'F', 'f', 'G', 'G', 'hv', 'I', 'I', 'K', 'k', 'l', 'l', 'W', 'N', 'n', 'O', + 0xA0 => 'O', 'o', 'OI', 'oi', 'P', 'p', 'YR', '2', '2', 'SH', 'sh', 't', 'T', 't', 'T', 'U', + 0xB0 => 'u', 'Y', 'V', 'Y', 'y', 'Z', 'z', 'ZH', 'ZH', 'zh', 'zh', '2', '5', '5', 'ts', 'w', + 0xC0 => '|', '||', '|=', '!', 'DZ', 'Dz', 'dz', 'LJ', 'Lj', 'lj', 'NJ', 'Nj', 'nj', 'A', 'a', 'I', + 0xD0 => 'i', 'O', 'o', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', '@', 'A', 'a', + 0xE0 => 'A', 'a', 'AE', 'ae', 'G', 'g', 'G', 'g', 'K', 'k', 'O', 'o', 'O', 'o', 'ZH', 'zh', + 0xF0 => 'j', 'DZ', 'D', 'dz', 'G', 'g', 'HV', 'W', 'N', 'n', 'A', 'a', 'AE', 'ae', 'O', 'o', +]; + +// Overrides for Esperanto input. +$variant['eo'] = [ + 0x08 => 'Cx', + 0x09 => 'cx', + 0x1C => 'Gx', + 0x1D => 'gx', + 0x24 => 'Hx', + 0x25 => 'hx', + 0x34 => 'Jx', + 0x35 => 'jx', + 0x5C => 'Sx', + 0x5D => 'sx', + 0x6C => 'Ux', + 0x6D => 'ux', +]; diff --git a/resources/transliteration-data/x02.php b/resources/transliteration-data/x02.php new file mode 100644 index 000000000..64e8c5e85 --- /dev/null +++ b/resources/transliteration-data/x02.php @@ -0,0 +1,20 @@ + 'A', 'a', 'A', 'a', 'E', 'e', 'E', 'e', 'I', 'i', 'I', 'i', 'O', 'o', 'O', 'o', + 0x10 => 'R', 'r', 'R', 'r', 'U', 'u', 'U', 'u', 'S', 's', 'T', 't', 'Y', 'y', 'H', 'h', + 0x20 => 'N', 'd', 'OU', 'ou', 'Z', 'z', 'A', 'a', 'E', 'e', 'O', 'o', 'O', 'o', 'O', 'o', + 0x30 => 'O', 'o', 'Y', 'y', 'l', 'n', 't', 'j', 'db', 'qp', 'A', 'C', 'c', 'L', 'T', 's', + 0x40 => 'z', '?', '?', 'B', 'U', 'V', 'E', 'e', 'J', 'j', 'Q', 'q', 'R', 'r', 'Y', 'y', + 0x50 => 'a', 'a', 'a', 'b', 'o', 'c', 'd', 'd', 'e', '@', '@', 'e', 'e', 'e', 'e', 'j', + 0x60 => 'g', 'g', 'g', 'g', 'u', 'Y', 'h', 'h', 'i', 'i', 'I', 'l', 'l', 'l', 'lZ', 'W', + 0x70 => 'W', 'm', 'n', 'n', 'n', 'o', 'OE', 'O', 'F', 'R', 'R', 'R', 'R', 'r', 'r', 'R', + 0x80 => 'R', 'R', 's', 'S', 'j', 'S', 'S', 't', 't', 'U', 'U', 'v', '^', 'W', 'Y', 'Y', + 0x90 => 'z', 'z', 'Z', 'Z', '?', '?', '?', 'C', '@', 'B', 'E', 'G', 'H', 'j', 'k', 'L', + 0xA0 => 'q', '?', '?', 'dz', 'dZ', 'dz', 'ts', 'tS', 'tC', 'fN', 'ls', 'lz', 'WW', ']]', 'h', 'h', + 0xB0 => 'k', 'h', 'j', 'r', 'r', 'r', 'r', 'w', 'y', '\'', '"', '`', '\'', '`', '`', '\'', + 0xC0 => '?', '?', '<', '>', '^', 'V', '^', 'V', '\'', '-', '/', '\\', ',', '_', '\\', '/', + 0xD0 => ':', '.', '`', '\'', '^', 'V', '+', '-', 'V', '.', '@', ',', '~', '"', 'R', 'X', + 0xE0 => 'G', 'l', 's', 'x', '?', '', '', '', '', '', '', '', 'V', '=', '"', null, + 0xF0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, +]; diff --git a/resources/transliteration-data/x03.php b/resources/transliteration-data/x03.php new file mode 100644 index 000000000..7f28a7f97 --- /dev/null +++ b/resources/transliteration-data/x03.php @@ -0,0 +1,20 @@ + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 0x10 => '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 0x20 => '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 0x30 => '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 0x40 => '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', null, + 0x50 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0x60 => '', '', '', null, null, null, null, null, null, null, null, null, null, null, null, null, + 0x70 => null, null, null, null, '\'', ',', null, null, null, null, '', null, null, null, '?', null, + 0x80 => null, null, null, null, '', '', 'A', ';', 'E', 'I', 'I', null, 'O', null, 'U', 'O', + 0x90 => 'I', 'A', 'V', 'G', 'D', 'E', 'Z', 'I', 'Th', 'I', 'K', 'L', 'M', 'N', 'X', 'O', + 0xA0 => 'P', 'R', null, 'S', 'T', 'Y', 'F', 'H', 'Ps', 'O', 'I', 'Y', 'a', 'e', 'i', 'i', + 0xB0 => 'y', 'a', 'v', 'g', 'd', 'e', 'z', 'i', 'th', 'i', 'k', 'l', 'm', 'n', 'x', 'o', + 0xC0 => 'p', 'r', 's', 's', 't', 'y', 'f', 'h', 'ps', 'o', 'i', 'y', 'o', 'y', 'o', null, + 0xD0 => 'b', 'th', 'U', 'U', 'U', 'ph', 'p', '&', null, null, 'St', 'st', 'W', 'w', 'Q', 'q', + 0xE0 => 'Sp', 'sp', 'Sh', 'sh', 'F', 'f', 'Kh', 'kh', 'H', 'h', 'G', 'g', 'CH', 'ch', 'Ti', 'ti', + 0xF0 => 'k', 'r', 'c', 'j', null, null, null, null, null, null, null, null, null, null, null, null, +]; diff --git a/resources/transliteration-data/x04.php b/resources/transliteration-data/x04.php new file mode 100644 index 000000000..ea8279555 --- /dev/null +++ b/resources/transliteration-data/x04.php @@ -0,0 +1,56 @@ + 'Jo', 'Yo', 'Dj', 'Gj', 'Ie', 'Dz', 'I', 'Yi', 'J', 'Lj', 'Nj', 'Tsh', 'Kj', 'I', 'U', 'Dzh', + 0x10 => 'A', 'B', 'V', 'G', 'D', 'E', 'Zh', 'Z', 'I', 'Y', 'K', 'L', 'M', 'N', 'O', 'P', + 0x20 => 'R', 'S', 'T', 'U', 'F', 'H', 'C', 'Ch', 'Sh', 'Shch', '', 'Y', '', 'E', 'Yu', 'Ya', + 0x30 => 'a', 'b', 'v', 'g', 'd', 'e', 'zh', 'z', 'i', 'y', 'k', 'l', 'm', 'n', 'o', 'p', + 0x40 => 'r', 's', 't', 'u', 'f', 'h', 'c', 'ch', 'sh', 'shch', '', 'y', '', 'e', 'yu', 'ya', + 0x50 => 'je', 'yo', 'dj', 'gj', 'ie', 'dz', 'i', 'yi', 'j', 'lj', 'nj', 'tsh', 'kj', 'i', 'u', 'dzh', + 0x60 => 'O', 'o', 'E', 'e', 'Ie', 'ie', 'E', 'e', 'Ie', 'ie', 'O', 'o', 'Io', 'io', 'Ks', 'ks', + 0x70 => 'Ps', 'ps', 'F', 'f', 'Y', 'y', 'Y', 'y', 'u', 'u', 'O', 'o', 'O', 'o', 'Ot', 'ot', + 0x80 => 'Q', 'q', '*1000*', '', '', '', '', null, '*100.000*', '*1.000.000*', null, null, '"', '"', 'R\'', 'r\'', + 0x90 => 'G\'', 'g\'', 'G\'', 'g\'', 'G\'', 'g\'', 'Zh\'', 'zh\'', 'Z\'', 'z\'', 'K\'', 'k\'', 'K\'', 'k\'', 'K\'', 'k\'', + 0xA0 => 'K\'', 'k\'', 'N\'', 'n\'', 'Ng', 'ng', 'P\'', 'p\'', 'Kh', 'kh', 'S\'', 's\'', 'T\'', 't\'', 'U', 'u', + 0xB0 => 'U\'', 'u\'', 'Kh\'', 'kh\'', 'Tts', 'tts', 'Ch\'', 'ch\'', 'Ch\'', 'ch\'', 'H', 'h', 'Ch', 'ch', 'Ch\'', 'ch\'', + 0xC0 => '`', 'Zh', 'zh', 'K\'', 'k\'', null, null, 'N\'', 'n\'', null, null, 'Ch', 'ch', null, null, null, + 0xD0 => 'a', 'a', 'A', 'a', 'Ae', 'ae', 'Ie', 'ie', '@', '@', '@', '@', 'Zh', 'zh', 'Z', 'z', + 0xE0 => 'Dz', 'dz', 'I', 'i', 'I', 'i', 'O', 'o', 'O', 'o', 'O', 'o', 'E', 'e', 'U', 'u', + 0xF0 => 'U', 'u', 'U', 'u', 'Ch', 'ch', null, null, 'Y', 'y', null, null, null, null, null, null, +]; + +// Overrides for Kyrgyz input. +$variant['kg'] = [ + 0x01 => 'E', + 0x16 => 'C', + 0x19 => 'J', + 0x25 => 'X', + 0x26 => 'TS', + 0x29 => 'SCH', + 0x2E => 'JU', + 0x2F => 'JA', + 0x36 => 'c', + 0x39 => 'j', + 0x45 => 'x', + 0x46 => 'ts', + 0x49 => 'sch', + 0x4E => 'ju', + 0x4F => 'ja', + 0x51 => 'e', + 0xA2 => 'H', + 0xA3 => 'h', + 0xAE => 'W', + 0xAF => 'w', + 0xE8 => 'Q', + 0xE9 => 'q', +]; + +// Overrides for Ukrainian input. +$variant['uk'] = [ + 0x90 => 'G', + 0x91 => 'g', + 0x04 => 'YE', + 0x54 => 'ye', + 0x18 => 'Y', + 0x38 => 'y', +]; diff --git a/resources/transliteration-data/x05.php b/resources/transliteration-data/x05.php new file mode 100644 index 000000000..bd95f5d32 --- /dev/null +++ b/resources/transliteration-data/x05.php @@ -0,0 +1,20 @@ + null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0x10 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0x20 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0x30 => null, 'A', 'B', 'G', 'D', 'E', 'Z', 'E', 'E', 'T`', 'Zh', 'I', 'L', 'Kh', 'Ts', 'K', + 0x40 => 'H', 'Dz', 'Gh', 'Ch', 'M', 'Y', 'N', 'Sh', 'O', 'Ch`', 'P', 'J', 'Rh', 'S', 'V', 'T', + 0x50 => 'R', 'Ts`', 'W', 'P`', 'K`', 'O', 'F', null, null, '<', '\'', '/', '!', ',', '?', '.', + 0x60 => null, 'a', 'b', 'g', 'd', 'e', 'z', 'e', 'e', 't`', 'zh', 'i', 'l', 'kh', 'ts', 'k', + 0x70 => 'h', 'dz', 'gh', 'ch', 'm', 'y', 'n', 'sh', 'o', 'ch`', 'p', 'j', 'rh', 's', 'v', 't', + 0x80 => 'r', 'ts`', 'w', 'p`', 'k`', 'o', 'f', 'ew', null, '.', '-', null, null, null, null, null, + 0x90 => null, '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 0xA0 => '', '', null, '', '', '', '', '', '', '', '', '', '', '', '', '', + 0xB0 => '@', 'e', 'a', 'o', 'i', 'e', 'e', 'a', 'a', 'o', null, 'u', '\'', '', '', '', + 0xC0 => '', '', '', ':', '', null, null, null, null, null, null, null, null, null, null, null, + 0xD0 => '', 'b', 'g', 'd', 'h', 'v', 'z', 'kh', 't', 'y', 'k', 'k', 'l', 'm', 'm', 'n', + 0xE0 => 'n', 's', '`', 'p', 'p', 'ts', 'ts', 'q', 'r', 'sh', 't', null, null, null, null, null, + 0xF0 => 'V', 'oy', 'i', '\'', '"', null, null, null, null, null, null, null, null, null, null, null, +]; diff --git a/resources/transliteration-data/x06.php b/resources/transliteration-data/x06.php new file mode 100644 index 000000000..2f4e6297f --- /dev/null +++ b/resources/transliteration-data/x06.php @@ -0,0 +1,20 @@ + null, null, null, null, null, null, null, null, null, null, null, null, ',', null, null, null, + 0x10 => null, null, null, null, null, null, null, null, null, null, null, ';', null, null, null, '?', + 0x20 => null, '', 'a', '\'', 'w\'', '', 'y\'', '', 'b', '@', 't', 'th', 'j', 'H', 'kh', 'd', + 0x30 => 'dh', 'r', 'z', 's', 'sh', 'S', 'D', 'T', 'Z', '`', 'G', null, null, null, null, null, + 0x40 => '', 'f', 'q', 'k', 'l', 'm', 'n', 'h', 'w', '~', 'y', 'an', 'un', 'in', 'a', 'u', + 0x50 => 'i', 'W', '', '', '\'', '\'', null, null, null, null, null, null, null, null, null, null, + 0x60 => '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '%', '.', ',', '*', null, null, + 0x70 => '', '\'', '\'', '\'', '', '\'', '\'w', '\'u', '\'y', 'tt', 'tth', 'b', 't', 'T', 'p', 'th', + 0x80 => 'bh', '\'h', 'H', 'ny', 'dy', 'H', 'ch', 'cch', 'dd', 'D', 'D', 'Dt', 'dh', 'ddh', 'd', 'D', + 0x90 => 'D', 'rr', 'R', 'R', 'R', 'R', 'R', 'R', 'j', 'R', 'S', 'S', 'S', 'S', 'S', 'T', + 0xA0 => 'GH', 'F', 'F', 'F', 'v', 'f', 'ph', 'Q', 'Q', 'kh', 'k', 'K', 'K', 'ng', 'K', 'g', + 0xB0 => 'G', 'N', 'G', 'G', 'G', 'L', 'L', 'L', 'L', 'N', 'N', 'N', 'N', 'N', 'h', 'Ch', + 0xC0 => 'hy', 'h', 'H', '@', 'W', 'oe', 'oe', 'u', 'yu', 'yu', 'W', 'v', 'y', 'Y', 'Y', 'W', + 0xD0 => '', '', 'y', 'y\'', '.', 'ae', '', '', '', '', '', '', '', '@', '#', '', + 0xE0 => '', '', '', '', '', '', '', '', '', '^', '', '', '', '', null, null, + 0xF0 => '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'Sh', 'D', 'Gh', '&', '+m', null, +]; diff --git a/resources/transliteration-data/x07.php b/resources/transliteration-data/x07.php new file mode 100644 index 000000000..42ad9cfb5 --- /dev/null +++ b/resources/transliteration-data/x07.php @@ -0,0 +1,20 @@ + '//', '/', ',', '!', '!', '-', ',', ',', ';', '?', '~', '{', '}', '*', null, '', + 0x10 => '\'', '', 'b', 'g', 'g', 'd', 'd', 'h', 'w', 'z', 'H', 't', 't', 'y', 'yh', 'k', + 0x20 => 'l', 'm', 'n', 's', 's', '`', 'p', 'p', 'S', 'q', 'r', 'sh', 't', null, null, null, + 0x30 => 'a', 'a', 'a', 'A', 'A', 'A', 'e', 'e', 'e', 'E', 'i', 'i', 'u', 'u', 'u', 'o', + 0x40 => '', '`', '\'', '', '', 'X', 'Q', '@', '@', '|', '+', null, null, null, null, null, + 0x50 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0x60 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0x70 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0x80 => 'h', 'sh', 'n', 'r', 'b', 'L', 'k', '\'', 'v', 'm', 'f', 'dh', 'th', 'l', 'g', 'ny', + 0x90 => 's', 'd', 'z', 't', 'y', 'p', 'j', 'ch', 'tt', 'hh', 'kh', 'th', 'z', 'sh', 's', 'd', + 0xA0 => 't', 'z', '`', 'gh', 'q', 'w', 'a', 'aa', 'i', 'ee', 'u', 'oo', 'e', 'ey', 'o', 'oa', + 0xB0 => '', null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0xC0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0xD0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0xE0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0xF0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, +]; diff --git a/resources/transliteration-data/x09.php b/resources/transliteration-data/x09.php new file mode 100644 index 000000000..3e6da2c13 --- /dev/null +++ b/resources/transliteration-data/x09.php @@ -0,0 +1,20 @@ + null, 'N', 'N', 'H', null, 'a', 'aa', 'i', 'ii', 'u', 'uu', 'R', 'L', 'eN', 'e', 'e', + 0x10 => 'ai', 'oN', 'o', 'o', 'au', 'k', 'kh', 'g', 'gh', 'ng', 'c', 'ch', 'j', 'jh', 'ny', 'tt', + 0x20 => 'tth', 'dd', 'ddh', 'nn', 't', 'th', 'd', 'dh', 'n', 'nnn', 'p', 'ph', 'b', 'bh', 'm', 'y', + 0x30 => 'r', 'rr', 'l', 'l', 'lll', 'v', 'sh', 'ss', 's', 'h', null, null, '\'', '\'', 'aa', 'i', + 0x40 => 'ii', 'u', 'uu', 'R', 'RR', 'eN', 'e', 'e', 'ai', 'oN', 'o', 'o', 'au', '', null, null, + 0x50 => 'AUM', '\'', '\'', '`', '\'', null, null, null, 'q', 'khh', 'ghh', 'z', 'dddh', 'rh', 'f', 'yy', + 0x60 => 'RR', 'LL', 'L', 'LL', ' / ', ' // ', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 0x70 => '.', null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0x80 => null, 'N', 'N', 'H', null, 'a', 'aa', 'i', 'ii', 'u', 'uu', 'R', 'RR', null, null, 'e', + 0x90 => 'ai', null, null, 'o', 'au', 'k', 'kh', 'g', 'gh', 'ng', 'c', 'ch', 'j', 'jh', 'ny', 'tt', + 0xA0 => 'tth', 'dd', 'ddh', 'nn', 't', 'th', 'd', 'dh', 'n', null, 'p', 'ph', 'b', 'bh', 'm', 'y', + 0xB0 => 'r', null, 'l', null, null, null, 'sh', 'ss', 's', 'h', null, null, '\'', null, 'aa', 'i', + 0xC0 => 'ii', 'u', 'uu', 'R', 'RR', null, null, 'e', 'ai', null, null, 'o', 'au', '', null, null, + 0xD0 => null, null, null, null, null, null, null, '+', null, null, null, null, 'rr', 'rh', null, 'yy', + 0xE0 => 'RR', 'LL', 'L', 'LL', null, null, '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 0xF0 => 'r\'', 'r`', 'Rs', 'Rs', '1/', '2/', '3/', '4/', ' 1 - 1/', '/16', '', null, null, null, null, null, +]; diff --git a/resources/transliteration-data/x0a.php b/resources/transliteration-data/x0a.php new file mode 100644 index 000000000..26cbffb80 --- /dev/null +++ b/resources/transliteration-data/x0a.php @@ -0,0 +1,20 @@ + null, null, 'N', null, null, 'a', 'aa', 'i', 'ii', 'u', 'uu', null, null, null, null, 'ee', + 0x10 => 'ai', null, null, 'oo', 'au', 'k', 'kh', 'g', 'gh', 'ng', 'c', 'ch', 'j', 'jh', 'ny', 'tt', + 0x20 => 'tth', 'dd', 'ddh', 'nn', 't', 'th', 'd', 'dh', 'n', null, 'p', 'ph', 'b', 'bb', 'm', 'y', + 0x30 => 'r', null, 'l', 'll', null, 'v', 'sh', null, 's', 'h', null, null, '\'', null, 'aa', 'i', + 0x40 => 'ii', 'u', 'uu', null, null, null, null, 'ee', 'ai', null, null, 'oo', 'au', '', null, null, + 0x50 => null, null, null, null, null, null, null, null, null, 'khh', 'ghh', 'z', 'rr', null, 'f', null, + 0x60 => null, null, null, null, null, null, '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 0x70 => 'N', 'H', '', '', 'G.E.O.', null, null, null, null, null, null, null, null, null, null, null, + 0x80 => null, 'N', 'N', 'H', null, 'a', 'aa', 'i', 'ii', 'u', 'uu', 'R', null, 'eN', null, 'e', + 0x90 => 'ai', 'oN', null, 'o', 'au', 'k', 'kh', 'g', 'gh', 'ng', 'c', 'ch', 'j', 'jh', 'ny', 'tt', + 0xA0 => 'tth', 'dd', 'ddh', 'nn', 't', 'th', 'd', 'dh', 'n', null, 'p', 'ph', 'b', 'bh', 'm', 'ya', + 0xB0 => 'r', null, 'l', 'll', null, 'v', 'sh', 'ss', 's', 'h', null, null, '\'', '\'', 'aa', 'i', + 0xC0 => 'ii', 'u', 'uu', 'R', 'RR', 'eN', null, 'e', 'ai', 'oN', null, 'o', 'au', '', null, null, + 0xD0 => 'AUM', null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0xE0 => 'RR', null, null, null, null, null, '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 0xF0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, +]; diff --git a/resources/transliteration-data/x0b.php b/resources/transliteration-data/x0b.php new file mode 100644 index 000000000..fee354d02 --- /dev/null +++ b/resources/transliteration-data/x0b.php @@ -0,0 +1,20 @@ + null, 'N', 'N', 'H', null, 'a', 'aa', 'i', 'ii', 'u', 'uu', 'R', 'L', null, null, 'e', + 0x10 => 'ai', null, null, 'o', 'au', 'k', 'kh', 'g', 'gh', 'ng', 'c', 'ch', 'j', 'jh', 'ny', 'tt', + 0x20 => 'tth', 'dd', 'ddh', 'nn', 't', 'th', 'd', 'dh', 'n', null, 'p', 'ph', 'b', 'bh', 'm', 'y', + 0x30 => 'r', null, 'l', 'll', null, '', 'sh', 'ss', 's', 'h', null, null, '\'', '\'', 'aa', 'i', + 0x40 => 'ii', 'u', 'uu', 'R', null, null, null, 'e', 'ai', null, null, 'o', 'au', '', null, null, + 0x50 => null, null, null, null, null, null, '+', '+', null, null, null, null, 'rr', 'rh', null, 'yy', + 0x60 => 'RR', 'LL', null, null, null, null, '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 0x70 => '', null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0x80 => null, null, 'N', 'H', null, 'a', 'aa', 'i', 'ii', 'u', 'uu', null, null, null, 'e', 'ee', + 0x90 => 'ai', null, 'o', 'oo', 'au', 'k', null, null, null, 'ng', 'c', null, 'j', null, 'ny', 'tt', + 0xA0 => null, null, null, 'nn', 't', null, null, null, 'n', 'nnn', 'p', null, null, null, 'm', 'y', + 0xB0 => 'r', 'rr', 'l', 'll', 'lll', 'v', null, 'ss', 's', 'h', null, null, null, null, 'aa', 'i', + 0xC0 => 'ii', 'u', 'uu', null, null, null, 'e', 'ee', 'ai', null, 'o', 'oo', 'au', '', null, null, + 0xD0 => null, null, null, null, null, null, null, '+', null, null, null, null, null, null, null, null, + 0xE0 => null, null, null, null, null, null, '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 0xF0 => '+10+', '+100+', '+1000+', null, null, null, null, null, null, null, null, null, null, null, null, null, +]; diff --git a/resources/transliteration-data/x0c.php b/resources/transliteration-data/x0c.php new file mode 100644 index 000000000..82b3ed9d3 --- /dev/null +++ b/resources/transliteration-data/x0c.php @@ -0,0 +1,20 @@ + null, 'N', 'N', 'H', null, 'a', 'aa', 'i', 'ii', 'u', 'uu', 'R', 'L', null, 'e', 'ee', + 0x10 => 'ai', null, 'o', 'oo', 'au', 'k', 'kh', 'g', 'gh', 'ng', 'c', 'ch', 'j', 'jh', 'ny', 'tt', + 0x20 => 'tth', 'dd', 'ddh', 'nn', 't', 'th', 'd', 'dh', 'n', null, 'p', 'ph', 'b', 'bh', 'm', 'y', + 0x30 => 'r', 'rr', 'l', 'll', null, 'v', 'sh', 'ss', 's', 'h', null, null, null, null, 'aa', 'i', + 0x40 => 'ii', 'u', 'uu', 'R', 'RR', null, 'e', 'ee', 'ai', null, 'o', 'oo', 'au', '', null, null, + 0x50 => null, null, null, null, null, '+', '+', null, null, null, null, null, null, null, null, null, + 0x60 => 'RR', 'LL', null, null, null, null, '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 0x70 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0x80 => null, null, 'N', 'H', null, 'a', 'aa', 'i', 'ii', 'u', 'uu', 'R', 'L', null, 'e', 'ee', + 0x90 => 'ai', null, 'o', 'oo', 'au', 'k', 'kh', 'g', 'gh', 'ng', 'c', 'ch', 'j', 'jh', 'ny', 'tt', + 0xA0 => 'tth', 'dd', 'ddh', 'nn', 't', 'th', 'd', 'dh', 'n', null, 'p', 'ph', 'b', 'bh', 'm', 'y', + 0xB0 => 'r', 'rr', 'l', 'll', null, 'v', 'sh', 'ss', 's', 'h', null, null, null, null, 'aa', 'i', + 0xC0 => 'ii', 'u', 'uu', 'R', 'RR', null, 'e', 'ee', 'ai', null, 'o', 'oo', 'au', '', null, null, + 0xD0 => null, null, null, null, null, '+', '+', null, null, null, null, null, null, null, 'lll', null, + 0xE0 => 'RR', 'LL', null, null, null, null, '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 0xF0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, +]; diff --git a/resources/transliteration-data/x0d.php b/resources/transliteration-data/x0d.php new file mode 100644 index 000000000..3e9c8d337 --- /dev/null +++ b/resources/transliteration-data/x0d.php @@ -0,0 +1,20 @@ + null, null, 'N', 'H', null, 'a', 'aa', 'i', 'ii', 'u', 'uu', 'R', 'L', null, 'e', 'ee', + 0x10 => 'ai', null, 'o', 'oo', 'au', 'k', 'kh', 'g', 'gh', 'ng', 'c', 'ch', 'j', 'jh', 'ny', 'tt', + 0x20 => 'tth', 'dd', 'ddh', 'nn', 't', 'th', 'd', 'dh', 'n', null, 'p', 'ph', 'b', 'bh', 'm', 'y', + 0x30 => 'r', 'rr', 'l', 'll', 'lll', 'v', 'sh', 'ss', 's', 'h', null, null, null, null, 'aa', 'i', + 0x40 => 'ii', 'u', 'uu', 'R', null, null, 'e', 'ee', 'ai', '', 'o', 'oo', 'au', '', null, null, + 0x50 => null, null, null, null, null, null, null, '+', null, null, null, null, null, null, null, null, + 0x60 => 'RR', 'LL', null, null, null, null, '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 0x70 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0x80 => null, null, 'N', 'H', null, 'a', 'aa', 'ae', 'aae', 'i', 'ii', 'u', 'uu', 'R', 'RR', 'L', + 0x90 => 'LL', 'e', 'ee', 'ai', 'o', 'oo', 'au', null, null, null, 'k', 'kh', 'g', 'gh', 'ng', 'nng', + 0xA0 => 'c', 'ch', 'j', 'jh', 'ny', 'jny', 'nyj', 'tt', 'tth', 'dd', 'ddh', 'nn', 'nndd', 't', 'th', 'd', + 0xB0 => 'dh', 'n', null, 'nd', 'p', 'ph', 'b', 'bh', 'm', 'mb', 'y', 'r', null, 'l', null, null, + 0xC0 => 'v', 'sh', 'ss', 's', 'h', 'll', 'f', null, null, null, '', null, null, null, null, 'aa', + 0xD0 => 'ae', 'aae', 'i', 'ii', 'u', null, 'uu', null, 'R', 'e', 'ee', 'ai', 'o', 'oo', 'au', 'L', + 0xE0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0xF0 => null, null, 'RR', 'LL', ' . ', null, null, null, null, null, null, null, null, null, null, null, +]; diff --git a/resources/transliteration-data/x0e.php b/resources/transliteration-data/x0e.php new file mode 100644 index 000000000..cd6e7d16f --- /dev/null +++ b/resources/transliteration-data/x0e.php @@ -0,0 +1,20 @@ + null, 'k', 'kh', 'kh', 'kh', 'kh', 'kh', 'ng', 'cch', 'ch', 'ch', 'ch', 'ch', 'y', 'd', 't', + 0x10 => 'th', 'th', 'th', 'n', 'd', 't', 'th', 'th', 'th', 'n', 'b', 'p', 'ph', 'f', 'ph', 'f', + 0x20 => 'ph', 'm', 'y', 'r', 'R', 'l', 'L', 'w', 's', 's', 's', 'h', 'l', '`', 'h', '~', + 0x30 => 'a', 'a', 'aa', 'am', 'i', 'ii', 'ue', 'uue', 'u', 'uu', '\'', null, null, null, null, 'Bh.', + 0x40 => 'e', 'ae', 'o', 'ai', 'ai', 'ao', '+', '', '', '', '', '', '', 'M', '', ' * ', + 0x50 => '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ' // ', ' /// ', null, null, null, null, + 0x60 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0x70 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0x80 => null, 'k', 'kh', null, 'kh', null, null, 'ng', 'ch', null, 's', null, null, 'ny', null, null, + 0x90 => null, null, null, null, 'd', 'h', 'th', 'th', null, 'n', 'b', 'p', 'ph', 'f', 'ph', 'f', + 0xA0 => null, 'm', 'y', 'r', null, 'l', null, 'w', null, null, 's', 'h', null, '`', '', '~', + 0xB0 => 'a', '', 'aa', 'am', 'i', 'ii', 'y', 'yy', 'u', 'uu', null, 'o', 'l', 'ny', null, null, + 0xC0 => 'e', 'ei', 'o', 'ay', 'ai', null, '+', null, '', '', '', '', '', 'M', null, null, + 0xD0 => '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', null, null, 'hn', 'hm', null, null, + 0xE0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0xF0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, +]; diff --git a/resources/transliteration-data/x0f.php b/resources/transliteration-data/x0f.php new file mode 100644 index 000000000..575b21b8e --- /dev/null +++ b/resources/transliteration-data/x0f.php @@ -0,0 +1,20 @@ + 'AUM', '', '', '', '', '', '', '', ' // ', ' * ', '', '-', ' / ', ' / ', ' // ', ' -/ ', + 0x10 => ' +/ ', ' X/ ', ' /XX/ ', ' /X/ ', ',', '', '', '', '', '', '', '', '', '', '', '', + 0x20 => '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.5', '1.5', '2.5', '3.5', '4.5', '5.5', + 0x30 => '6.5', '7.5', '8.5', '-.5', '+', '*', '^', '_', '', '~', null, ']', '[[', ']]', '', '', + 0x40 => 'k', 'kh', 'g', 'gh', 'ng', 'c', 'ch', 'j', null, 'ny', 'tt', 'tth', 'dd', 'ddh', 'nn', 't', + 0x50 => 'th', 'd', 'dh', 'n', 'p', 'ph', 'b', 'bh', 'm', 'ts', 'tsh', 'dz', 'dzh', 'w', 'zh', 'z', + 0x60 => '\'', 'y', 'r', 'l', 'sh', 'ssh', 's', 'h', 'a', 'kss', 'r', null, null, null, null, null, + 0x70 => null, 'aa', 'i', 'ii', 'u', 'uu', 'R', 'RR', 'L', 'LL', 'e', 'ee', 'o', 'oo', 'M', 'H', + 0x80 => 'i', 'ii', '', '', '', '', '', '', '', '', '', '', null, null, null, null, + 0x90 => 'k', 'kh', 'g', 'gh', 'ng', 'c', 'ch', 'j', null, 'ny', 'tt', 'tth', 'dd', 'ddh', 'nn', 't', + 0xA0 => 'th', 'd', 'dh', 'n', 'p', 'ph', 'b', 'bh', 'm', 'ts', 'tsh', 'dz', 'dzh', 'w', 'zh', 'z', + 0xB0 => '\'', 'y', 'r', 'l', 'sh', 'ss', 's', 'h', 'a', 'kss', 'w', 'y', 'r', null, 'X', ' :X: ', + 0xC0 => ' /O/ ', ' /o/ ', ' \\o\\ ', ' (O) ', '', '', '', '', '', '', '', '', '', null, null, '', + 0xD0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0xE0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0xF0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, +]; diff --git a/resources/transliteration-data/x10.php b/resources/transliteration-data/x10.php new file mode 100644 index 000000000..bbf4e9037 --- /dev/null +++ b/resources/transliteration-data/x10.php @@ -0,0 +1,20 @@ + 'k', 'kh', 'g', 'gh', 'ng', 'c', 'ch', 'j', 'jh', 'ny', 'nny', 'tt', 'tth', 'dd', 'ddh', 'nn', + 0x10 => 'tt', 'th', 'd', 'dh', 'n', 'p', 'ph', 'b', 'bh', 'm', 'y', 'r', 'l', 'w', 's', 'h', + 0x20 => 'll', 'a', null, 'i', 'ii', 'u', 'uu', 'e', null, 'o', 'au', null, 'aa', 'i', 'ii', 'u', + 0x30 => 'uu', 'e', 'ai', null, null, null, 'N', '\'', ':', '', null, null, null, null, null, null, + 0x40 => '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ' / ', ' // ', 'n*', 'r*', 'l*', 'e*', + 0x50 => 'sh', 'ss', 'R', 'RR', 'L', 'LL', 'R', 'RR', 'L', 'LL', null, null, null, null, null, null, + 0x60 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0x70 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0x80 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0x90 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0xA0 => 'A', 'B', 'G', 'D', 'E', 'V', 'Z', 'T`', 'I', 'K', 'L', 'M', 'N', 'O', 'P', 'Zh', + 0xB0 => 'R', 'S', 'T', 'U', 'P`', 'K`', 'G\'', 'Q', 'Sh', 'Ch`', 'C`', 'Z\'', 'C', 'Ch', 'X', 'J', + 0xC0 => 'H', 'E', 'Y', 'W', 'Xh', 'OE', null, null, null, null, null, null, null, null, null, null, + 0xD0 => 'a', 'b', 'g', 'd', 'e', 'v', 'z', 't`', 'i', 'k', 'l', 'm', 'n', 'o', 'p', 'zh', + 0xE0 => 'r', 's', 't', 'u', 'p`', 'k`', 'g\'', 'q', 'sh', 'ch`', 'c`', 'z\'', 'c', 'ch', 'x', 'j', + 0xF0 => 'h', 'e', 'y', 'w', 'xh', 'oe', 'f', null, null, null, null, ' // ', null, null, null, null, +]; diff --git a/resources/transliteration-data/x11.php b/resources/transliteration-data/x11.php new file mode 100644 index 000000000..7511b0561 --- /dev/null +++ b/resources/transliteration-data/x11.php @@ -0,0 +1,20 @@ + 'g', 'gg', 'n', 'd', 'dd', 'r', 'm', 'b', 'bb', 's', 'ss', '', 'j', 'jj', 'c', 'k', + 0x10 => 't', 'p', 'h', 'ng', 'nn', 'nd', 'nb', 'dg', 'rn', 'rr', 'rh', 'rN', 'mb', 'mN', 'bg', 'bn', + 0x20 => '', 'bs', 'bsg', 'bst', 'bsb', 'bss', 'bsj', 'bj', 'bc', 'bt', 'bp', 'bN', 'bbN', 'sg', 'sn', 'sd', + 0x30 => 'sr', 'sm', 'sb', 'sbg', 'sss', 's', 'sj', 'sc', 'sk', 'st', 'sp', 'sh', '', '', '', '', + 0x40 => 'Z', 'g', 'd', 'm', 'b', 's', 'Z', '', 'j', 'c', 't', 'p', 'N', 'j', '', '', + 0x50 => '', '', 'ck', 'ch', '', '', 'pb', 'pN', 'hh', 'Q', null, null, null, null, null, '', + 0x60 => '', 'a', 'ae', 'ya', 'yae', 'eo', 'e', 'yeo', 'ye', 'o', 'wa', 'wae', 'oe', 'yo', 'u', 'weo', + 0x70 => 'we', 'wi', 'yu', 'eu', 'yi', 'i', 'a-o', 'a-u', 'ya-o', 'ya-yo', 'eo-o', 'eo-u', 'eo-eu', 'yeo-o', 'yeo-u', 'o-eo', + 0x80 => 'o-e', 'o-ye', 'o-o', 'o-u', 'yo-ya', 'yo-yae', 'yo-yeo', 'yo-o', 'yo-i', 'u-a', 'u-ae', 'u-eo-eu', 'u-ye', 'u-u', 'yu-a', 'yu-eo', + 0x90 => 'yu-e', 'yu-yeo', 'yu-ye', 'yu-u', 'yu-i', 'eu-u', 'eu-eu', 'yi-u', 'i-a', 'i-ya', 'i-o', 'i-u', 'i-eu', 'i-U', 'U', 'U-eo', + 0xA0 => 'U-u', 'U-i', 'UU', null, null, null, null, null, 'g', 'gg', 'gs', 'n', 'nj', 'nh', 'd', 'l', + 0xB0 => 'lg', 'lm', 'lb', 'ls', 'lt', 'lp', 'lh', 'm', 'b', 'bs', 's', 'ss', 'ng', 'j', 'c', 'k', + 0xC0 => 't', 'p', 'h', 'gl', 'gsg', 'ng', 'nd', 'ns', 'nZ', 'nt', 'dg', 'tl', 'lgs', 'ln', 'ld', 'lth', + 0xD0 => 'll', 'lmg', 'lms', 'lbs', 'lbh', 'rNp', 'lss', 'lZ', 'lk', 'lQ', 'mg', 'ml', 'mb', 'ms', 'mss', 'mZ', + 0xE0 => 'mc', 'mh', 'mN', 'bl', 'bp', 'ph', 'pN', 'sg', 'sd', 'sl', 'sb', 'Z', 'g', 'ss', '', 'kh', + 0xF0 => 'N', 'Ns', 'NZ', 'pb', 'pN', 'hn', 'hl', 'hm', 'hb', 'Q', null, null, null, null, null, null, +]; diff --git a/resources/transliteration-data/x12.php b/resources/transliteration-data/x12.php new file mode 100644 index 000000000..e2a322e54 --- /dev/null +++ b/resources/transliteration-data/x12.php @@ -0,0 +1,20 @@ + 'ha', 'hu', 'hi', 'haa', 'hee', 'he', 'ho', null, 'la', 'lu', 'li', 'laa', 'lee', 'le', 'lo', 'lwa', + 0x10 => 'hha', 'hhu', 'hhi', 'hhaa', 'hhee', 'hhe', 'hho', 'hhwa', 'ma', 'mu', 'mi', 'maa', 'mee', 'me', 'mo', 'mwa', + 0x20 => 'sza', 'szu', 'szi', 'szaa', 'szee', 'sze', 'szo', 'szwa', 'ra', 'ru', 'ri', 'raa', 'ree', 're', 'ro', 'rwa', + 0x30 => 'sa', 'su', 'si', 'saa', 'see', 'se', 'so', 'swa', 'sha', 'shu', 'shi', 'shaa', 'shee', 'she', 'sho', 'shwa', + 0x40 => 'qa', 'qu', 'qi', 'qaa', 'qee', 'qe', 'qo', null, 'qwa', null, 'qwi', 'qwaa', 'qwee', 'qwe', null, null, + 0x50 => 'qha', 'qhu', 'qhi', 'qhaa', 'qhee', 'qhe', 'qho', null, 'qhwa', null, 'qhwi', 'qhwaa', 'qhwee', 'qhwe', null, null, + 0x60 => 'ba', 'bu', 'bi', 'baa', 'bee', 'be', 'bo', 'bwa', 'va', 'vu', 'vi', 'vaa', 'vee', 've', 'vo', 'vwa', + 0x70 => 'ta', 'tu', 'ti', 'taa', 'tee', 'te', 'to', 'twa', 'ca', 'cu', 'ci', 'caa', 'cee', 'ce', 'co', 'cwa', + 0x80 => 'xa', 'xu', 'xi', 'xaa', 'xee', 'xe', 'xo', null, 'xwa', null, 'xwi', 'xwaa', 'xwee', 'xwe', null, null, + 0x90 => 'na', 'nu', 'ni', 'naa', 'nee', 'ne', 'no', 'nwa', 'nya', 'nyu', 'nyi', 'nyaa', 'nyee', 'nye', 'nyo', 'nywa', + 0xA0 => '\'a', '\'u', null, '\'aa', '\'ee', '\'e', '\'o', '\'wa', 'ka', 'ku', 'ki', 'kaa', 'kee', 'ke', 'ko', null, + 0xB0 => 'kwa', null, 'kwi', 'kwaa', 'kwee', 'kwe', null, null, 'kxa', 'kxu', 'kxi', 'kxaa', 'kxee', 'kxe', 'kxo', null, + 0xC0 => 'kxwa', null, 'kxwi', 'kxwaa', 'kxwee', 'kxwe', null, null, 'wa', 'wu', 'wi', 'waa', 'wee', 'we', 'wo', null, + 0xD0 => '`a', '`u', '`i', '`aa', '`ee', '`e', '`o', null, 'za', 'zu', 'zi', 'zaa', 'zee', 'ze', 'zo', 'zwa', + 0xE0 => 'zha', 'zhu', 'zhi', 'zhaa', 'zhee', 'zhe', 'zho', 'zhwa', 'ya', 'yu', 'yi', 'yaa', 'yee', 'ye', 'yo', null, + 0xF0 => 'da', 'du', 'di', 'daa', 'dee', 'de', 'do', 'dwa', 'dda', 'ddu', 'ddi', 'ddaa', 'ddee', 'dde', 'ddo', 'ddwa', +]; diff --git a/resources/transliteration-data/x13.php b/resources/transliteration-data/x13.php new file mode 100644 index 000000000..0d3bf75bb --- /dev/null +++ b/resources/transliteration-data/x13.php @@ -0,0 +1,20 @@ + 'ja', 'ju', 'ji', 'jaa', 'jee', 'je', 'jo', 'jwa', 'ga', 'gu', 'gi', 'gaa', 'gee', 'ge', 'go', null, + 0x10 => 'gwa', null, 'gwi', 'gwaa', 'gwee', 'gwe', null, null, 'gga', 'ggu', 'ggi', 'ggaa', 'ggee', 'gge', 'ggo', null, + 0x20 => 'tha', 'thu', 'thi', 'thaa', 'thee', 'the', 'tho', 'thwa', 'cha', 'chu', 'chi', 'chaa', 'chee', 'che', 'cho', 'chwa', + 0x30 => 'pha', 'phu', 'phi', 'phaa', 'phee', 'phe', 'pho', 'phwa', 'tsa', 'tsu', 'tsi', 'tsaa', 'tsee', 'tse', 'tso', 'tswa', + 0x40 => 'tza', 'tzu', 'tzi', 'tzaa', 'tzee', 'tze', 'tzo', null, 'fa', 'fu', 'fi', 'faa', 'fee', 'fe', 'fo', 'fwa', + 0x50 => 'pa', 'pu', 'pi', 'paa', 'pee', 'pe', 'po', 'pwa', 'rya', 'mya', 'fya', null, null, null, null, null, + 0x60 => null, ' ', '.', ',', ';', ':', ':: ', '?', '//', '1', '2', '3', '4', '5', '6', '7', + 0x70 => '8', '9', '10+', '20+', '30+', '40+', '50+', '60+', '70+', '80+', '90+', '100+', '10,000+', null, null, null, + 0x80 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0x90 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0xA0 => 'a', 'e', 'i', 'o', 'u', 'v', 'ga', 'ka', 'ge', 'gi', 'go', 'gu', 'gv', 'ha', 'he', 'hi', + 0xB0 => 'ho', 'hu', 'hv', 'la', 'le', 'li', 'lo', 'lu', 'lv', 'ma', 'me', 'mi', 'mo', 'mu', 'na', 'hna', + 0xC0 => 'nah', 'ne', 'ni', 'no', 'nu', 'nv', 'qua', 'que', 'qui', 'quo', 'quu', 'quv', 'sa', 's', 'se', 'si', + 0xD0 => 'so', 'su', 'sv', 'da', 'ta', 'de', 'te', 'di', 'ti', 'do', 'du', 'dv', 'dla', 'tla', 'tle', 'tli', + 0xE0 => 'tlo', 'tlu', 'tlv', 'tsa', 'tse', 'tsi', 'tso', 'tsu', 'tsv', 'wa', 'we', 'wi', 'wo', 'wu', 'wv', 'ya', + 0xF0 => 'ye', 'yi', 'yo', 'yu', 'yv', null, null, null, null, null, null, null, null, null, null, null, +]; diff --git a/resources/transliteration-data/x14.php b/resources/transliteration-data/x14.php new file mode 100644 index 000000000..dedc29a61 --- /dev/null +++ b/resources/transliteration-data/x14.php @@ -0,0 +1,20 @@ + null, 'ai', 'aai', 'i', 'ii', 'u', 'uu', 'oo', 'ee', 'i', 'a', 'aa', 'we', 'we', 'wi', 'wi', + 0x10 => 'wii', 'wii', 'wo', 'wo', 'woo', 'woo', 'woo', 'wa', 'wa', 'waa', 'waa', 'waa', 'ai', 'w', '\'', 't', + 0x20 => 'k', 'sh', 's', 'n', 'w', 'n', null, 'w', 'c', '?', 'l', 'en', 'in', 'on', 'an', 'pai', + 0x30 => 'paai', 'pi', 'pii', 'pu', 'puu', 'poo', 'hee', 'hi', 'pa', 'paa', 'pwe', 'pwe', 'pwi', 'pwi', 'pwii', 'pwii', + 0x40 => 'pwo', 'pwo', 'pwoo', 'pwoo', 'pwa', 'pwa', 'pwaa', 'pwaa', 'pwaa', 'p', 'p', 'h', 'tai', 'taai', 'ti', 'tii', + 0x50 => 'tu', 'tuu', 'too', 'dee', 'di', 'ta', 'taa', 'twe', 'twe', 'twi', 'twi', 'twii', 'twii', 'two', 'two', 'twoo', + 0x60 => 'twoo', 'twa', 'twa', 'twaa', 'twaa', 'twaa', 't', 'tte', 'tti', 'tto', 'tta', 'kai', 'kaai', 'ki', 'kii', 'ku', + 0x70 => 'kuu', 'koo', 'ka', 'kaa', 'kwe', 'kwe', 'kwi', 'kwi', 'kwii', 'kwii', 'kwo', 'kwo', 'kwoo', 'kwoo', 'kwa', 'kwa', + 0x80 => 'kwaa', 'kwaa', 'kwaa', 'k', 'kw', 'keh', 'kih', 'koh', 'kah', 'gai', 'caai', 'gi', 'gii', 'gu', 'guu', 'coo', + 0x90 => 'ga', 'gaa', 'cwe', 'cwe', 'cwi', 'cwi', 'cwii', 'cwii', 'cwo', 'cwo', 'cwoo', 'cwoo', 'cwa', 'cwa', 'cwaa', 'cwaa', + 0xA0 => 'cwaa', 'g', 'th', 'mai', 'maai', 'mi', 'mii', 'mu', 'muu', 'moo', 'ma', 'maa', 'mwe', 'mwe', 'mwi', 'mwi', + 0xB0 => 'mwii', 'mwii', 'mwo', 'mwo', 'mwoo', 'mwoo', 'mwa', 'mwa', 'mwaa', 'mwaa', 'mwaa', 'm', 'm', 'mh', 'm', 'm', + 0xC0 => 'nai', 'naai', 'ni', 'nii', 'nu', 'nuu', 'noo', 'na', 'naa', 'nwe', 'nwe', 'nwa', 'nwa', 'nwaa', 'nwaa', 'nwaa', + 0xD0 => 'n', 'ng', 'nh', 'lai', 'laai', 'li', 'lii', 'lu', 'luu', 'loo', 'la', 'laa', 'lwe', 'lwe', 'lwi', 'lwi', + 0xE0 => 'lwii', 'lwii', 'lwo', 'lwo', 'lwoo', 'lwoo', 'lwa', 'lwa', 'lwaa', 'lwaa', 'l', 'l', 'l', 'sai', 'saai', 'si', + 0xF0 => 'sii', 'su', 'suu', 'soo', 'sa', 'saa', 'swe', 'swe', 'swi', 'swi', 'swii', 'swii', 'swo', 'swo', 'swoo', 'swoo', +]; diff --git a/resources/transliteration-data/x15.php b/resources/transliteration-data/x15.php new file mode 100644 index 000000000..6c41be136 --- /dev/null +++ b/resources/transliteration-data/x15.php @@ -0,0 +1,20 @@ + 'swa', 'swa', 'swaa', 'swaa', 'swaa', 's', 's', 'sw', 's', 'sk', 'skw', 'sW', 'spwa', 'stwa', 'skwa', 'scwa', + 0x10 => 'she', 'shi', 'shii', 'sho', 'shoo', 'sha', 'shaa', 'shwe', 'shwe', 'shwi', 'shwi', 'shwii', 'shwii', 'shwo', 'shwo', 'shwoo', + 0x20 => 'shwoo', 'shwa', 'shwa', 'shwaa', 'shwaa', 'sh', 'jai', 'yaai', 'ji', 'jii', 'ju', 'juu', 'yoo', 'ja', 'jaa', 'ywe', + 0x30 => 'ywe', 'ywi', 'ywi', 'ywii', 'ywii', 'ywo', 'ywo', 'ywoo', 'ywoo', 'ywa', 'ywa', 'ywaa', 'ywaa', 'ywaa', 'j', 'y', + 0x40 => 'y', 'yi', 're', 'rai', 'le', 'raai', 'ri', 'rii', 'ru', 'ruu', 'lo', 'ra', 'raa', 'la', 'rwaa', 'rwaa', + 0x50 => 'r', 'r', 'r', 'vai', 'faai', 'vi', 'vii', 'vu', 'vuu', 'va', 'vaa', 'fwaa', 'fwaa', 'v', 'the', 'the', + 0x60 => 'thi', 'thi', 'thii', 'thii', 'tho', 'thoo', 'tha', 'thaa', 'thwaa', 'thwaa', 'th', 'tthe', 'tthi', 'ttho', 'ttha', 'tth', + 0x70 => 'tye', 'tyi', 'tyo', 'tya', 'he', 'hi', 'hii', 'ho', 'hoo', 'ha', 'haa', 'h', 'h', 'hk', 'qaai', 'qi', + 0x80 => 'qii', 'qu', 'quu', 'qa', 'qaa', 'q', 'tlhe', 'tlhi', 'tlho', 'tlha', 're', 'ri', 'ro', 'ra', 'ngaai', 'ngi', + 0x90 => 'ngii', 'ngu', 'nguu', 'nga', 'ngaa', 'ng', 'nng', 'she', 'shi', 'sho', 'sha', 'the', 'thi', 'tho', 'tha', 'th', + 0xA0 => 'lhi', 'lhii', 'lho', 'lhoo', 'lha', 'lhaa', 'lh', 'the', 'thi', 'thii', 'tho', 'thoo', 'tha', 'thaa', 'th', 'b', + 0xB0 => 'e', 'i', 'o', 'a', 'we', 'wi', 'wo', 'wa', 'ne', 'ni', 'no', 'na', 'ke', 'ki', 'ko', 'ka', + 0xC0 => 'he', 'hi', 'ho', 'ha', 'ghu', 'gho', 'ghe', 'ghee', 'ghi', 'gha', 'ru', 'ro', 're', 'ree', 'ri', 'ra', + 0xD0 => 'wu', 'wo', 'we', 'wee', 'wi', 'wa', 'hwu', 'hwo', 'hwe', 'hwee', 'hwi', 'hwa', 'thu', 'tho', 'the', 'thee', + 0xE0 => 'thi', 'tha', 'ttu', 'tto', 'tte', 'ttee', 'tti', 'tta', 'pu', 'po', 'pe', 'pee', 'pi', 'pa', 'p', 'gu', + 0xF0 => 'go', 'ge', 'gee', 'gi', 'ga', 'khu', 'kho', 'khe', 'khee', 'khi', 'kha', 'kku', 'kko', 'kke', 'kkee', 'kki', +]; diff --git a/resources/transliteration-data/x16.php b/resources/transliteration-data/x16.php new file mode 100644 index 000000000..a6e12f711 --- /dev/null +++ b/resources/transliteration-data/x16.php @@ -0,0 +1,20 @@ + 'kka', 'kk', 'nu', 'no', 'ne', 'nee', 'ni', 'na', 'mu', 'mo', 'me', 'mee', 'mi', 'ma', 'yu', 'yo', + 0x10 => 'ye', 'yee', 'yi', 'ya', 'ju', 'ju', 'jo', 'je', 'jee', 'ji', 'ji', 'ja', 'jju', 'jjo', 'jje', 'jjee', + 0x20 => 'jji', 'jja', 'lu', 'lo', 'le', 'lee', 'li', 'la', 'dlu', 'dlo', 'dle', 'dlee', 'dli', 'dla', 'lhu', 'lho', + 0x30 => 'lhe', 'lhee', 'lhi', 'lha', 'tlhu', 'tlho', 'tlhe', 'tlhee', 'tlhi', 'tlha', 'tlu', 'tlo', 'tle', 'tlee', 'tli', 'tla', + 0x40 => 'zu', 'zo', 'ze', 'zee', 'zi', 'za', 'z', 'z', 'dzu', 'dzo', 'dze', 'dzee', 'dzi', 'dza', 'su', 'so', + 0x50 => 'se', 'see', 'si', 'sa', 'shu', 'sho', 'she', 'shee', 'shi', 'sha', 'sh', 'tsu', 'tso', 'tse', 'tsee', 'tsi', + 0x60 => 'tsa', 'chu', 'cho', 'che', 'chee', 'chi', 'cha', 'ttsu', 'ttso', 'ttse', 'ttsee', 'ttsi', 'ttsa', 'X', '.', 'qai', + 0x70 => 'ngai', 'nngi', 'nngii', 'nngo', 'nngoo', 'nnga', 'nngaa', null, null, null, null, null, null, null, null, null, + 0x80 => ' ', 'b', 'l', 'f', 's', 'n', 'h', 'd', 't', 'c', 'q', 'm', 'g', 'ng', 'z', 'r', + 0x90 => 'a', 'o', 'u', 'e', 'i', 'ch', 'th', 'ph', 'p', 'x', 'p', '<', '>', null, null, null, + 0xA0 => 'f', 'v', 'u', 'yr', 'y', 'w', 'th', 'th', 'a', 'o', 'ac', 'ae', 'o', 'o', 'o', 'oe', + 0xB0 => 'on', 'r', 'k', 'c', 'k', 'g', 'ng', 'g', 'g', 'w', 'h', 'h', 'h', 'h', 'n', 'n', + 0xC0 => 'n', 'i', 'e', 'j', 'g', 'ae', 'a', 'eo', 'p', 'z', 's', 's', 's', 'c', 'z', 't', + 0xD0 => 't', 'd', 'b', 'b', 'p', 'p', 'e', 'm', 'm', 'm', 'l', 'l', 'ng', 'ng', 'd', 'o', + 0xE0 => 'ear', 'ior', 'qu', 'qu', 'qu', 's', 'yr', 'yr', 'yr', 'q', 'x', '.', ':', '+', '17', '18', + 0xF0 => '19', null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, +]; diff --git a/resources/transliteration-data/x17.php b/resources/transliteration-data/x17.php new file mode 100644 index 000000000..51990bb04 --- /dev/null +++ b/resources/transliteration-data/x17.php @@ -0,0 +1,20 @@ + null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0x10 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0x20 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0x30 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0x40 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0x50 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0x60 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0x70 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0x80 => 'k', 'kh', 'g', 'gh', 'ng', 'c', 'ch', 'j', 'jh', 'ny', 't', 'tth', 'd', 'ddh', 'nn', 't', + 0x90 => 'th', 'd', 'dh', 'n', 'p', 'ph', 'b', 'bh', 'm', 'y', 'r', 'l', 'v', 'sh', 'ss', 's', + 0xA0 => 'h', 'l', 'q', 'a', 'aa', 'i', 'ii', 'u', 'uk', 'uu', 'uuv', 'ry', 'ryy', 'ly', 'lyy', 'e', + 0xB0 => 'ai', 'oo', 'oo', 'au', 'a', 'aa', 'aa', 'i', 'ii', 'y', 'yy', 'u', 'uu', 'ua', 'oe', 'ya', + 0xC0 => 'ie', 'e', 'ae', 'ai', 'oo', 'au', 'M', 'H', 'a`', '', '', '', 'r', '', '!', '', + 0xD0 => '', '', '', '', '.', ' // ', ':', '+', '++', ' * ', ' /// ', 'KR', '\'', null, null, null, + 0xE0 => '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', null, null, null, null, null, null, + 0xF0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, +]; diff --git a/resources/transliteration-data/x18.php b/resources/transliteration-data/x18.php new file mode 100644 index 000000000..5be2dcbb1 --- /dev/null +++ b/resources/transliteration-data/x18.php @@ -0,0 +1,20 @@ + ' @ ', ' ... ', ',', '. ', ': ', ' // ', '', '-', ',', '. ', '', '', '', '', '', null, + 0x10 => '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', null, null, null, null, null, null, + 0x20 => 'a', 'e', 'i', 'o', 'u', 'O', 'U', 'ee', 'n', 'ng', 'b', 'p', 'q', 'g', 'm', 'l', + 0x30 => 's', 'sh', 't', 'd', 'ch', 'j', 'y', 'r', 'w', 'f', 'k', 'kha', 'ts', 'z', 'h', 'zr', + 0x40 => 'lh', 'zh', 'ch', '-', 'e', 'i', 'o', 'u', 'O', 'U', 'ng', 'b', 'p', 'q', 'g', 'm', + 0x50 => 't', 'd', 'ch', 'j', 'ts', 'y', 'w', 'k', 'g', 'h', 'jy', 'ny', 'dz', 'e', 'i', 'iy', + 0x60 => 'U', 'u', 'ng', 'k', 'g', 'h', 'p', 'sh', 't', 'd', 'j', 'f', 'g', 'h', 'ts', 'z', + 0x70 => 'r', 'ch', 'zh', 'i', 'k', 'r', 'f', 'zh', null, null, null, null, null, null, null, null, + 0x80 => null, 'H', 'X', 'W', 'M', ' 3 ', ' 333 ', 'a', 'i', 'k', 'ng', 'c', 'tt', 'tth', 'dd', 'nn', + 0x90 => 't', 'd', 'p', 'ph', 'ss', 'zh', 'z', 'a', 't', 'zh', 'gh', 'ng', 'c', 'jh', 'tta', 'ddh', + 0xA0 => 't', 'dh', 'ss', 'cy', 'zh', 'z', 'u', 'y', 'bh', '\'', null, null, null, null, null, null, + 0xB0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0xC0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0xD0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0xE0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0xF0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, +]; diff --git a/resources/transliteration-data/x1e.php b/resources/transliteration-data/x1e.php new file mode 100644 index 000000000..04eb9986f --- /dev/null +++ b/resources/transliteration-data/x1e.php @@ -0,0 +1,20 @@ + 'A', 'a', 'B', 'b', 'B', 'b', 'B', 'b', 'C', 'c', 'D', 'd', 'D', 'd', 'D', 'd', + 0x10 => 'D', 'd', 'D', 'd', 'E', 'e', 'E', 'e', 'E', 'e', 'E', 'e', 'E', 'e', 'F', 'f', + 0x20 => 'G', 'g', 'H', 'h', 'H', 'h', 'H', 'h', 'H', 'h', 'H', 'h', 'I', 'i', 'I', 'i', + 0x30 => 'K', 'k', 'K', 'k', 'K', 'k', 'L', 'l', 'L', 'l', 'L', 'l', 'L', 'l', 'M', 'm', + 0x40 => 'M', 'm', 'M', 'm', 'N', 'n', 'N', 'n', 'N', 'n', 'N', 'n', 'O', 'o', 'O', 'o', + 0x50 => 'O', 'o', 'O', 'o', 'P', 'p', 'P', 'p', 'R', 'r', 'R', 'r', 'R', 'r', 'R', 'r', + 0x60 => 'S', 's', 'S', 's', 'S', 's', 'S', 's', 'S', 's', 'T', 't', 'T', 't', 'T', 't', + 0x70 => 'T', 't', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'V', 'v', 'V', 'v', + 0x80 => 'W', 'w', 'W', 'w', 'W', 'w', 'W', 'w', 'W', 'w', 'X', 'x', 'X', 'x', 'Y', 'y', + 0x90 => 'Z', 'z', 'Z', 'z', 'Z', 'z', 'h', 't', 'w', 'y', 'a', 'S', null, null, null, null, + 0xA0 => 'A', 'a', 'A', 'a', 'A', 'a', 'A', 'a', 'A', 'a', 'A', 'a', 'A', 'a', 'A', 'a', + 0xB0 => 'A', 'a', 'A', 'a', 'A', 'a', 'A', 'a', 'E', 'e', 'E', 'e', 'E', 'e', 'E', 'e', + 0xC0 => 'E', 'e', 'E', 'e', 'E', 'e', 'E', 'e', 'I', 'i', 'I', 'i', 'O', 'o', 'O', 'o', + 0xD0 => 'O', 'o', 'O', 'o', 'O', 'o', 'O', 'o', 'O', 'o', 'O', 'o', 'O', 'o', 'O', 'o', + 0xE0 => 'O', 'o', 'O', 'o', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', + 0xF0 => 'U', 'u', 'Y', 'y', 'Y', 'y', 'Y', 'y', 'Y', 'y', null, null, null, null, null, null, +]; diff --git a/resources/transliteration-data/x1f.php b/resources/transliteration-data/x1f.php new file mode 100644 index 000000000..94dd3e534 --- /dev/null +++ b/resources/transliteration-data/x1f.php @@ -0,0 +1,20 @@ + 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', + 0x10 => 'e', 'e', 'e', 'e', 'e', 'e', null, null, 'E', 'E', 'E', 'E', 'E', 'E', null, null, + 0x20 => 'e', 'e', 'e', 'e', 'e', 'e', 'e', 'e', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', + 0x30 => 'i', 'i', 'i', 'i', 'i', 'i', 'i', 'i', 'I', 'I', 'I', 'I', 'I', 'I', 'I', 'I', + 0x40 => 'o', 'o', 'o', 'o', 'o', 'o', null, null, 'O', 'O', 'O', 'O', 'O', 'O', null, null, + 0x50 => 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', null, 'U', null, 'U', null, 'U', null, 'U', + 0x60 => 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', + 0x70 => 'a', 'a', 'e', 'e', 'e', 'e', 'i', 'i', 'o', 'o', 'u', 'u', 'o', 'o', null, null, + 0x80 => 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', + 0x90 => 'e', 'e', 'e', 'e', 'e', 'e', 'e', 'e', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', + 0xA0 => 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', + 0xB0 => 'a', 'a', 'a', 'a', 'a', null, 'a', 'a', 'A', 'A', 'A', 'A', 'A', '\'', 'i', '\'', + 0xC0 => '~', '"~', 'e', 'e', 'e', null, 'e', 'e', 'E', 'E', 'E', 'E', 'E', '\'`', '\'\'', '\'~', + 0xD0 => 'i', 'i', 'i', 'i', null, null, 'i', 'i', 'I', 'I', 'I', 'I', null, '`\'', '`\'', '`~', + 0xE0 => 'u', 'u', 'u', 'u', 'R', 'R', 'u', 'u', 'U', 'U', 'U', 'U', 'R', '"`', '"\'', '`', + 0xF0 => null, null, 'o', 'o', 'o', null, 'o', 'o', 'O', 'O', 'O', 'O', 'O', '\'', '`', null, +]; diff --git a/resources/transliteration-data/x20.php b/resources/transliteration-data/x20.php new file mode 100644 index 000000000..6b5071cfe --- /dev/null +++ b/resources/transliteration-data/x20.php @@ -0,0 +1,23 @@ + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '', '', '', '', + 0x10 => '-', '-', '-', '-', '--', '--', '||', '_', '\'', '\'', ',', '\'', '"', '"', ',,', '"', + 0x20 => '+', '++', '*', '*>', '.', '..', '...', '.', ' +', ' + +', '', '', '', '', '', ' ', + 0x30 => '%0', '%00', '\'', '\'\'', '\'\'\'', '`', '``', '```', '^', '<', '>', '*', '!!', '!?', '-', '_', + 0x40 => '-', '^', '***', '--', '/', '-[', ']-', null, '?!', '!?', '7', 'PP', '(]', '[)', null, null, + 0x50 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0x60 => null, null, null, null, null, null, null, null, null, null, '', '', '', '', '', '', + 0x70 => '0', '', '', '', '4', '5', '6', '7', '8', '9', '+', '-', '=', '(', ')', 'n', + 0x80 => '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '-', '=', '(', ')', null, + 0x90 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0xA0 => 'ECU', 'CL', 'Cr', 'FF', 'L', 'mil', 'N', 'Pts', 'Rs', 'W', 'NS', 'D', 'EU', 'K', 'T', 'Dr', + 0xB0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0xC0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0xD0 => '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 0xE0 => '', '', '', '', null, null, null, null, null, null, null, null, null, null, null, null, + 0xF0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, +]; diff --git a/resources/transliteration-data/x21.php b/resources/transliteration-data/x21.php new file mode 100644 index 000000000..07cbe4ae9 --- /dev/null +++ b/resources/transliteration-data/x21.php @@ -0,0 +1,20 @@ + '', '', 'C', '', '', '', '', '', '', '', 'g', 'H', 'H', 'H', 'h', '', + 0x10 => 'I', 'I', 'L', 'l', 'lb', 'N', 'no', '(p)', 'P', 'P', 'Q', 'R', 'R', 'R', '', '', + 0x20 => '(sm)', '(tel)', '(tm)', '', 'Z', '', null, 'mho', 'Z', '', null, null, 'B', 'C', 'e', 'e', + 0x30 => '', 'F', null, 'M', 'o', '', '', '', '', 'i', 'Q', '(fax)', 'pi', '', '', 'Pi', + 0x40 => '', 'G', 'L', 'L', 'Y', 'D', 'd', 'e', 'i', 'j', '', '', 'per', '', null, null, + 0x50 => null, null, null, ' 1/3 ', ' 2/3 ', ' 1/5 ', ' 2/5 ', ' 3/5 ', ' 4/5 ', ' 1/6 ', ' 5/6 ', ' 1/8 ', ' 3/8 ', ' 5/8 ', ' 7/8 ', ' 1/', + 0x60 => 'I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII', 'IX', 'X', 'XI', 'XII', 'L', 'C', 'D', 'M', + 0x70 => 'i', 'ii', 'iii', 'iv', 'v', 'vi', 'vii', 'viii', 'ix', 'x', 'xi', 'xii', 'l', 'c', 'd', 'm', + 0x80 => '(D', 'D)', '((|))', ')', null, null, null, null, null, null, null, null, null, null, null, null, + 0x90 => '-', '|', '-', '|', '-', '|', '\\', '/', '\\', '/', '-', '-', '~', '~', '-', '|', + 0xA0 => '-', '|', '-', '-', '-', '|', '-', '|', '|', '-', '-', '-', '-', '-', '-', '|', + 0xB0 => '|', '|', '|', '|', '|', '|', '^', 'V', '\\', '=', 'V', '^', '-', '-', '|', '|', + 0xC0 => '-', '-', '|', '|', '=', '|', '=', '=', '|', '=', '|', '=', '=', '=', '=', '=', + 0xD0 => '=', '|', '=', '|', '=', '|', '\\', '/', '\\', '/', '=', '=', '~', '~', '|', '|', + 0xE0 => '-', '|', '-', '|', '-', '-', '-', '|', '-', '|', '|', '|', '|', '|', '|', '|', + 0xF0 => '-', '\\', '\\', '|', null, null, null, null, null, null, null, null, null, null, null, null, +]; diff --git a/resources/transliteration-data/x22.php b/resources/transliteration-data/x22.php new file mode 100644 index 000000000..772d981a3 --- /dev/null +++ b/resources/transliteration-data/x22.php @@ -0,0 +1,20 @@ + null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0x10 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0x20 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0x30 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0x40 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0x50 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0x60 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0x70 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0x80 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0x90 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0xA0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0xB0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0xC0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0xD0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0xE0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0xF0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, +]; diff --git a/resources/transliteration-data/x23.php b/resources/transliteration-data/x23.php new file mode 100644 index 000000000..772d981a3 --- /dev/null +++ b/resources/transliteration-data/x23.php @@ -0,0 +1,20 @@ + null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0x10 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0x20 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0x30 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0x40 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0x50 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0x60 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0x70 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0x80 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0x90 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0xA0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0xB0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0xC0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0xD0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0xE0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0xF0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, +]; diff --git a/resources/transliteration-data/x24.php b/resources/transliteration-data/x24.php new file mode 100644 index 000000000..06bfc3c56 --- /dev/null +++ b/resources/transliteration-data/x24.php @@ -0,0 +1,20 @@ + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 0x10 => '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 0x20 => '', '', '', '', '', '', '', null, null, null, null, null, null, null, null, null, + 0x30 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0x40 => '', '', '', '', '', '', '', '', '', '', '', null, null, null, null, null, + 0x50 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0x60 => '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 0x70 => '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 0x80 => '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 0x90 => '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 0xA0 => '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 0xB0 => '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 0xC0 => '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 0xD0 => '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 0xE0 => '', '', '', '', '', '', '', '', '', '', '', null, null, null, null, null, + 0xF0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, +]; diff --git a/resources/transliteration-data/x25.php b/resources/transliteration-data/x25.php new file mode 100644 index 000000000..902bf8259 --- /dev/null +++ b/resources/transliteration-data/x25.php @@ -0,0 +1,20 @@ + '-', '-', '|', '|', '-', '-', '|', '|', '-', '-', '|', '|', '+', '+', '+', '+', + 0x10 => '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', + 0x20 => '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', + 0x30 => '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', + 0x40 => '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '-', '-', '|', '|', + 0x50 => '-', '|', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', + 0x60 => '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', + 0x70 => '+', '/', '\\', 'X', '-', '|', '-', '|', '-', '|', '-', '|', '-', '|', '-', '|', + 0x80 => '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', + 0x90 => '#', '#', '#', '#', '-', '|', null, null, null, null, null, null, null, null, null, null, + 0xA0 => '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', + 0xB0 => '#', '#', '^', '^', '^', '^', '>', '>', '>', '>', '>', '>', 'V', 'V', 'V', 'V', + 0xC0 => '<', '<', '<', '<', '<', '<', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', + 0xD0 => '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', + 0xE0 => '*', '*', '*', '*', '*', '*', '*', '#', '#', '#', '#', '#', '^', '^', '^', 'O', + 0xF0 => '#', '#', '#', '#', '#', '#', '#', '#', null, null, null, null, null, null, null, null, +]; diff --git a/resources/transliteration-data/x26.php b/resources/transliteration-data/x26.php new file mode 100644 index 000000000..0777d7094 --- /dev/null +++ b/resources/transliteration-data/x26.php @@ -0,0 +1,20 @@ + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 0x10 => '', '', '', '', null, null, null, null, null, '', '', '', '', '', '', '', + 0x20 => '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 0x30 => '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 0x40 => '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 0x50 => '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 0x60 => '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 0x70 => '', '', null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0x80 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0x90 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0xA0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0xB0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0xC0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0xD0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0xE0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0xF0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, +]; diff --git a/resources/transliteration-data/x27.php b/resources/transliteration-data/x27.php new file mode 100644 index 000000000..237f3e20d --- /dev/null +++ b/resources/transliteration-data/x27.php @@ -0,0 +1,20 @@ + null, '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 0x10 => '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 0x20 => '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 0x30 => '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 0x40 => '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 0x50 => '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', null, + 0x60 => null, '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 0x70 => '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 0x80 => '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 0x90 => '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 0xA0 => '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 0xB0 => null, '', '', '', '', '', '', '', '', '', '', '', '', '', '', null, + 0xC0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0xD0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0xE0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0xF0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, +]; diff --git a/resources/transliteration-data/x28.php b/resources/transliteration-data/x28.php new file mode 100644 index 000000000..84e7d5a8c --- /dev/null +++ b/resources/transliteration-data/x28.php @@ -0,0 +1,20 @@ + ' ', 'a', '1', 'b', '\'', 'k', '2', 'l', '@', 'c', 'i', 'f', '/', 'm', 's', 'p', + 0x10 => '"', 'e', '3', 'h', '9', 'o', '6', 'r', '^', 'd', 'j', 'g', '>', 'n', 't', 'q', + 0x20 => ',', '*', '5', '<', '-', 'u', '8', 'v', '.', '%', '[', '$', '+', 'x', '!', '&', + 0x30 => ';', ':', '4', '\\', '0', 'z', '7', '(', '_', '?', 'w', ']', '#', 'y', ')', '=', + 0x40 => '[d7]', '[d17]', '[d27]', '[d127]', '[d37]', '[d137]', '[d237]', '[d1237]', '[d47]', '[d147]', '[d247]', '[d1247]', '[d347]', '[d1347]', '[d2347]', '[d12347]', + 0x50 => '[d57]', '[d157]', '[d257]', '[d1257]', '[d357]', '[d1357]', '[d2357]', '[d12357]', '[d457]', '[d1457]', '[d2457]', '[d12457]', '[d3457]', '[d13457]', '[d23457]', '[d123457]', + 0x60 => '[d67]', '[d167]', '[d267]', '[d1267]', '[d367]', '[d1367]', '[d2367]', '[d12367]', '[d467]', '[d1467]', '[d2467]', '[d12467]', '[d3467]', '[d13467]', '[d23467]', '[d123467]', + 0x70 => '[d567]', '[d1567]', '[d2567]', '[d12567]', '[d3567]', '[d13567]', '[d23567]', '[d123567]', '[d4567]', '[d14567]', '[d24567]', '[d124567]', '[d34567]', '[d134567]', '[d234567]', '[d1234567]', + 0x80 => '[d8]', '[d18]', '[d28]', '[d128]', '[d38]', '[d138]', '[d238]', '[d1238]', '[d48]', '[d148]', '[d248]', '[d1248]', '[d348]', '[d1348]', '[d2348]', '[d12348]', + 0x90 => '[d58]', '[d158]', '[d258]', '[d1258]', '[d358]', '[d1358]', '[d2358]', '[d12358]', '[d458]', '[d1458]', '[d2458]', '[d12458]', '[d3458]', '[d13458]', '[d23458]', '[d123458]', + 0xA0 => '[d68]', '[d168]', '[d268]', '[d1268]', '[d368]', '[d1368]', '[d2368]', '[d12368]', '[d468]', '[d1468]', '[d2468]', '[d12468]', '[d3468]', '[d13468]', '[d23468]', '[d123468]', + 0xB0 => '[d568]', '[d1568]', '[d2568]', '[d12568]', '[d3568]', '[d13568]', '[d23568]', '[d123568]', '[d4568]', '[d14568]', '[d24568]', '[d124568]', '[d34568]', '[d134568]', '[d234568]', '[d1234568]', + 0xC0 => '[d78]', '[d178]', '[d278]', '[d1278]', '[d378]', '[d1378]', '[d2378]', '[d12378]', '[d478]', '[d1478]', '[d2478]', '[d12478]', '[d3478]', '[d13478]', '[d23478]', '[d123478]', + 0xD0 => '[d578]', '[d1578]', '[d2578]', '[d12578]', '[d3578]', '[d13578]', '[d23578]', '[d123578]', '[d4578]', '[d14578]', '[d24578]', '[d124578]', '[d34578]', '[d134578]', '[d234578]', '[d1234578]', + 0xE0 => '[d678]', '[d1678]', '[d2678]', '[d12678]', '[d3678]', '[d13678]', '[d23678]', '[d123678]', '[d4678]', '[d14678]', '[d24678]', '[d124678]', '[d34678]', '[d134678]', '[d234678]', '[d1234678]', + 0xF0 => '[d5678]', '[d15678]', '[d25678]', '[d125678]', '[d35678]', '[d135678]', '[d235678]', '[d1235678]', '[d45678]', '[d145678]', '[d245678]', '[d1245678]', '[d345678]', '[d1345678]', '[d2345678]', '[d12345678]', +]; diff --git a/resources/transliteration-data/x2e.php b/resources/transliteration-data/x2e.php new file mode 100644 index 000000000..772d981a3 --- /dev/null +++ b/resources/transliteration-data/x2e.php @@ -0,0 +1,20 @@ + null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0x10 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0x20 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0x30 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0x40 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0x50 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0x60 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0x70 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0x80 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0x90 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0xA0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0xB0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0xC0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0xD0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0xE0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0xF0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, +]; diff --git a/resources/transliteration-data/x2f.php b/resources/transliteration-data/x2f.php new file mode 100644 index 000000000..772d981a3 --- /dev/null +++ b/resources/transliteration-data/x2f.php @@ -0,0 +1,20 @@ + null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0x10 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0x20 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0x30 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0x40 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0x50 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0x60 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0x70 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0x80 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0x90 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0xA0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0xB0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0xC0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0xD0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0xE0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0xF0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, +]; diff --git a/resources/transliteration-data/x30.php b/resources/transliteration-data/x30.php new file mode 100644 index 000000000..e5765c203 --- /dev/null +++ b/resources/transliteration-data/x30.php @@ -0,0 +1,20 @@ + ' ', ',', '. ', '"', '[JIS]', '"', '/', '0', '<', '> ', '<<', '>> ', '[', '] ', '{', '} ', + 0x10 => '[(', ')] ', '@', 'X ', '[', '] ', '[[', ']] ', '((', ')) ', '[[', ']] ', '~ ', '``', '\'\'', ',,', + 0x20 => '@', '1', '2', '3', '4', '5', '6', '7', '8', '9', '', '', '', '', '', '', + 0x30 => '~', '+', '+', '+', '+', '', '@', ' // ', '+10+', '+20+', '+30+', null, null, null, '', '', + 0x40 => null, 'a', 'a', 'i', 'i', 'u', 'u', 'e', 'e', 'o', 'o', 'ka', 'ga', 'ki', 'gi', 'ku', + 0x50 => 'gu', 'ke', 'ge', 'ko', 'go', 'sa', 'za', 'si', 'zi', 'su', 'zu', 'se', 'ze', 'so', 'zo', 'ta', + 0x60 => 'da', 'ti', 'di', 'tu', 'tu', 'du', 'te', 'de', 'to', 'do', 'na', 'ni', 'nu', 'ne', 'no', 'ha', + 0x70 => 'ba', 'pa', 'hi', 'bi', 'pi', 'hu', 'bu', 'pu', 'he', 'be', 'pe', 'ho', 'bo', 'po', 'ma', 'mi', + 0x80 => 'mu', 'me', 'mo', 'ya', 'ya', 'yu', 'yu', 'yo', 'yo', 'ra', 'ri', 'ru', 're', 'ro', 'wa', 'wa', + 0x90 => 'wi', 'we', 'wo', 'n', 'vu', null, null, null, null, '', '', '', '', '"', '"', null, + 0xA0 => null, 'a', 'a', 'i', 'i', 'u', 'u', 'e', 'e', 'o', 'o', 'ka', 'ga', 'ki', 'gi', 'ku', + 0xB0 => 'gu', 'ke', 'ge', 'ko', 'go', 'sa', 'za', 'si', 'zi', 'su', 'zu', 'se', 'ze', 'so', 'zo', 'ta', + 0xC0 => 'da', 'ti', 'di', 'tu', 'tu', 'du', 'te', 'de', 'to', 'do', 'na', 'ni', 'nu', 'ne', 'no', 'ha', + 0xD0 => 'ba', 'pa', 'hi', 'bi', 'pi', 'hu', 'bu', 'pu', 'he', 'be', 'pe', 'ho', 'bo', 'po', 'ma', 'mi', + 0xE0 => 'mu', 'me', 'mo', 'ya', 'ya', 'yu', 'yu', 'yo', 'yo', 'ra', 'ri', 'ru', 're', 'ro', 'wa', 'wa', + 0xF0 => 'wi', 'we', 'wo', 'n', 'vu', 'ka', 'ke', 'va', 'vi', 've', 'vo', '', '', '"', '"', null, +]; diff --git a/resources/transliteration-data/x31.php b/resources/transliteration-data/x31.php new file mode 100644 index 000000000..d69347da9 --- /dev/null +++ b/resources/transliteration-data/x31.php @@ -0,0 +1,20 @@ + null, null, null, null, null, 'B', 'P', 'M', 'F', 'D', 'T', 'N', 'L', 'G', 'K', 'H', + 0x10 => 'J', 'Q', 'X', 'ZH', 'CH', 'SH', 'R', 'Z', 'C', 'S', 'A', 'O', 'E', 'EH', 'AI', 'EI', + 0x20 => 'AU', 'OU', 'AN', 'EN', 'ANG', 'ENG', 'ER', 'I', 'U', 'IU', 'V', 'NG', 'GN', null, null, null, + 0x30 => null, 'g', 'gg', 'gs', 'n', 'nj', 'nh', 'd', 'dd', 'r', 'lg', 'lm', 'lb', 'ls', 'lt', 'lp', + 0x40 => 'rh', 'm', 'b', 'bb', 'bs', 's', 'ss', '', 'j', 'jj', 'c', 'k', 't', 'p', 'h', 'a', + 0x50 => 'ae', 'ya', 'yae', 'eo', 'e', 'yeo', 'ye', 'o', 'wa', 'wae', 'oe', 'yo', 'u', 'weo', 'we', 'wi', + 0x60 => 'yu', 'eu', 'yi', 'i', '', 'nn', 'nd', 'ns', 'nZ', 'lgs', 'ld', 'lbs', 'lZ', 'lQ', 'mb', 'ms', + 0x70 => 'mZ', 'mN', 'bg', '', 'bsg', 'bst', 'bj', 'bt', 'bN', 'bbN', 'sg', 'sn', 'sd', 'sb', 'sj', 'Z', + 0x80 => '', 'N', 'Ns', 'NZ', 'pN', 'hh', 'Q', 'yo-ya', 'yo-yae', 'yo-i', 'yu-yeo', 'yu-ye', 'yu-i', 'U', 'U-i', null, + 0x90 => '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 0xA0 => 'BU', 'ZI', 'JI', 'GU', 'EE', 'ENN', 'OO', 'ONN', 'IR', 'ANN', 'INN', 'UNN', 'IM', 'NGG', 'AINN', 'AUNN', + 0xB0 => 'AM', 'OM', 'ONG', 'INNN', 'P', 'T', 'K', 'H', null, null, null, null, null, null, null, null, + 0xC0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0xD0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0xE0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0xF0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, +]; diff --git a/resources/transliteration-data/x32.php b/resources/transliteration-data/x32.php new file mode 100644 index 000000000..23df28106 --- /dev/null +++ b/resources/transliteration-data/x32.php @@ -0,0 +1,20 @@ + '(g)', '(n)', '(d)', '(r)', '(m)', '(b)', '(s)', '()', '(j)', '(c)', '(k)', '(t)', '(p)', '(h)', '(ga)', '(na)', + 0x10 => '(da)', '(ra)', '(ma)', '(ba)', '(sa)', '(a)', '(ja)', '(ca)', '(ka)', '(ta)', '(pa)', '(ha)', '(ju)', null, null, null, + 0x20 => '(1) ', '(2) ', '(3) ', '(4) ', '(5) ', '(6) ', '(7) ', '(8) ', '(9) ', '(10) ', '(Yue) ', '(Huo) ', '(Shui) ', '(Mu) ', '(Jin) ', '(Tu) ', + 0x30 => '(Ri) ', '(Zhu) ', '(You) ', '(She) ', '(Ming) ', '(Te) ', '(Cai) ', '(Zhu) ', '(Lao) ', '(Dai) ', '(Hu) ', '(Xue) ', '(Jian) ', '(Qi) ', '(Zi) ', '(Xie) ', + 0x40 => '(Ji) ', '(Xiu) ', '<<', '>>', null, null, null, null, null, null, null, null, null, null, null, null, + 0x50 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0x60 => '(g)', '(n)', '(d)', '(r)', '(m)', '(b)', '(s)', '()', '(j)', '(c)', '(k)', '(t)', '(p)', '(h)', '(ga)', '(na)', + 0x70 => '(da)', '(ra)', '(ma)', '(ba)', '(sa)', '(a)', '(ja)', '(ca)', '(ka)', '(ta)', '(pa)', '(ha)', null, null, null, 'KIS ', + 0x80 => '(1) ', '(2) ', '(3) ', '(4) ', '(5) ', '(6) ', '(7) ', '(8) ', '(9) ', '(10) ', '(Yue) ', '(Huo) ', '(Shui) ', '(Mu) ', '(Jin) ', '(Tu) ', + 0x90 => '(Ri) ', '(Zhu) ', '(You) ', '(She) ', '(Ming) ', '(Te) ', '(Cai) ', '(Zhu) ', '(Lao) ', '(Mi) ', '(Nan) ', '(Nu) ', '(Shi) ', '(You) ', '(Yin) ', '(Zhu) ', + 0xA0 => '(Xiang) ', '(Xiu) ', '(Xie) ', '(Zheng) ', '(Shang) ', '(Zhong) ', '(Xia) ', '(Zuo) ', '(You) ', '(Yi) ', '(Zong) ', '(Xue) ', '(Jian) ', '(Qi) ', '(Zi) ', '(Xie) ', + 0xB0 => '(Ye) ', null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0xC0 => '1M', '2M', '3M', '4M', '5M', '6M', '7M', '8M', '9M', '10M', '11M', '12M', null, null, null, null, + 0xD0 => 'a', 'i', 'u', 'u', 'o', 'ka', 'ki', 'ku', 'ke', 'ko', 'sa', 'si', 'su', 'se', 'so', 'ta', + 0xE0 => 'ti', 'tu', 'te', 'to', 'na', 'ni', 'nu', 'ne', 'no', 'ha', 'hi', 'hu', 'he', 'ho', 'ma', 'mi', + 0xF0 => 'mu', 'me', 'mo', 'ya', 'yu', 'yo', 'ra', 'ri', 'ru', 're', 'ro', 'wa', 'wi', 'we', 'wo', null, +]; diff --git a/resources/transliteration-data/x33.php b/resources/transliteration-data/x33.php new file mode 100644 index 000000000..473d1523d --- /dev/null +++ b/resources/transliteration-data/x33.php @@ -0,0 +1,20 @@ + 'apartment', 'alpha', 'ampere', 'are', 'inning', 'inch', 'won', 'escudo', 'acre', 'ounce', 'ohm', 'kai-ri', 'carat', 'calorie', 'gallon', 'gamma', + 0x10 => 'giga', 'guinea', 'curie', 'guilder', 'kilo', 'kilogram', 'kilometer', 'kilowatt', 'gram', 'gram ton', 'cruzeiro', 'krone', 'case', 'koruna', 'co-op', 'cycle', + 0x20 => 'centime', 'shilling', 'centi', 'cent', 'dozen', 'desi', 'dollar', 'ton', 'nano', 'knot', 'heights', 'percent', 'parts', 'barrel', 'piaster', 'picul', + 0x30 => 'pico', 'building', 'farad', 'feet', 'bushel', 'franc', 'hectare', 'peso', 'pfennig', 'hertz', 'pence', 'page', 'beta', 'point', 'volt', 'hon', + 0x40 => 'pound', 'hall', 'horn', 'micro', 'mile', 'mach', 'mark', 'mansion', 'micron', 'milli', 'millibar', 'mega', 'megaton', 'meter', 'yard', 'yard', + 0x50 => 'yuan', 'liter', 'lira', 'rupee', 'ruble', 'rem', 'roentgen', 'watt', '0h', '1h', '2h', '3h', '4h', '5h', '6h', '7h', + 0x60 => '8h', '9h', '10h', '11h', '12h', '13h', '14h', '15h', '16h', '17h', '18h', '19h', '20h', '21h', '22h', '23h', + 0x70 => '24h', 'HPA', 'da', 'AU', 'bar', 'oV', 'pc', null, null, null, null, 'Heisei', 'Syouwa', 'Taisyou', 'Meiji', 'Inc.', + 0x80 => 'pA', 'nA', 'microamp', 'mA', 'kA', 'kB', 'MB', 'GB', 'cal', 'kcal', 'pF', 'nF', 'microFarad', 'microgram', 'mg', 'kg', + 0x90 => 'Hz', 'kHz', 'MHz', 'GHz', 'THz', 'microliter', 'ml', 'dl', 'kl', 'fm', 'nm', 'micrometer', 'mm', 'cm', 'km', 'mm^2', + 0xA0 => 'cm^2', 'm^2', 'km^2', 'mm^4', 'cm^3', 'm^3', 'km^3', 'm/s', 'm/s^2', 'Pa', 'kPa', 'MPa', 'GPa', 'rad', 'rad/s', 'rad/s^2', + 0xB0 => 'ps', 'ns', 'microsecond', 'ms', 'pV', 'nV', 'microvolt', 'mV', 'kV', 'MV', 'pW', 'nW', 'microwatt', 'mW', 'kW', 'MW', + 0xC0 => 'kOhm', 'MOhm', 'a.m.', 'Bq', 'cc', 'cd', 'C/kg', 'Co.', 'dB', 'Gy', 'ha', 'HP', 'in', 'K.K.', 'KM', 'kt', + 0xD0 => 'lm', 'ln', 'log', 'lx', 'mb', 'mil', 'mol', 'pH', 'p.m.', 'PPM', 'PR', 'sr', 'Sv', 'Wb', null, null, + 0xE0 => '1d', '2d', '3d', '4d', '5d', '6d', '7d', '8d', '9d', '10d', '11d', '12d', '13d', '14d', '15d', '16d', + 0xF0 => '17d', '18d', '19d', '20d', '21d', '22d', '23d', '24d', '25d', '26d', '27d', '28d', '29d', '30d', '31d', null, +]; diff --git a/resources/transliteration-data/x4d.php b/resources/transliteration-data/x4d.php new file mode 100644 index 000000000..772d981a3 --- /dev/null +++ b/resources/transliteration-data/x4d.php @@ -0,0 +1,20 @@ + null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0x10 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0x20 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0x30 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0x40 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0x50 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0x60 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0x70 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0x80 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0x90 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0xA0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0xB0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0xC0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0xD0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0xE0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0xF0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, +]; diff --git a/resources/transliteration-data/x4e.php b/resources/transliteration-data/x4e.php new file mode 100644 index 000000000..b7049842d --- /dev/null +++ b/resources/transliteration-data/x4e.php @@ -0,0 +1,20 @@ + 'Yi ', 'Ding ', 'Kao ', 'Qi ', 'Shang ', 'Xia ', null, 'Mo ', 'Zhang ', 'San ', 'Shang ', 'Xia ', 'Ji ', 'Bu ', 'Yu ', 'Mian ', + 0x10 => 'Gai ', 'Chou ', 'Chou ', 'Zhuan ', 'Qie ', 'Pi ', 'Shi ', 'Shi ', 'Qiu ', 'Bing ', 'Ye ', 'Cong ', 'Dong ', 'Si ', 'Cheng ', 'Diu ', + 0x20 => 'Qiu ', 'Liang ', 'Diu ', 'You ', 'Liang ', 'Yan ', 'Bing ', 'Sang ', 'Gun ', 'Jiu ', 'Ge ', 'Ya ', 'Qiang ', 'Zhong ', 'Ji ', 'Jie ', + 0x30 => 'Feng ', 'Guan ', 'Chuan ', 'Chan ', 'Lin ', 'Zhuo ', 'Zhu ', 'Ha ', 'Wan ', 'Dan ', 'Wei ', 'Zhu ', 'Jing ', 'Li ', 'Ju ', 'Pie ', + 0x40 => 'Fu ', 'Yi ', 'Yi ', 'Nai ', 'Shime ', 'Jiu ', 'Jiu ', 'Zhe ', 'Yao ', 'Yi ', null, 'Zhi ', 'Wu ', 'Zha ', 'Hu ', 'Fa ', + 0x50 => 'Le ', 'Zhong ', 'Ping ', 'Pang ', 'Qiao ', 'Hu ', 'Guai ', 'Cheng ', 'Cheng ', 'Yi ', 'Yin ', null, 'Mie ', 'Jiu ', 'Qi ', 'Ye ', + 0x60 => 'Xi ', 'Xiang ', 'Gai ', 'Diu ', 'Hal ', null, 'Shu ', 'Twul ', 'Shi ', 'Ji ', 'Nang ', 'Jia ', 'Kel ', 'Shi ', null, 'Ol ', + 0x70 => 'Mai ', 'Luan ', 'Cal ', 'Ru ', 'Xue ', 'Yan ', 'Fu ', 'Sha ', 'Na ', 'Gan ', 'Sol ', 'El ', 'Cwul ', null, 'Gan ', 'Chi ', + 0x80 => 'Gui ', 'Gan ', 'Luan ', 'Lin ', 'Yi ', 'Jue ', 'Liao ', 'Ma ', 'Yu ', 'Zheng ', 'Shi ', 'Shi ', 'Er ', 'Chu ', 'Yu ', 'Yu ', + 0x90 => 'Yu ', 'Yun ', 'Hu ', 'Qi ', 'Wu ', 'Jing ', 'Si ', 'Sui ', 'Gen ', 'Gen ', 'Ya ', 'Xie ', 'Ya ', 'Qi ', 'Ya ', 'Ji ', + 0xA0 => 'Tou ', 'Wang ', 'Kang ', 'Ta ', 'Jiao ', 'Hai ', 'Yi ', 'Chan ', 'Heng ', 'Mu ', null, 'Xiang ', 'Jing ', 'Ting ', 'Liang ', 'Xiang ', + 0xB0 => 'Jing ', 'Ye ', 'Qin ', 'Bo ', 'You ', 'Xie ', 'Dan ', 'Lian ', 'Duo ', 'Wei ', 'Ren ', 'Ren ', 'Ji ', 'La ', 'Wang ', 'Yi ', + 0xC0 => 'Shi ', 'Ren ', 'Le ', 'Ding ', 'Ze ', 'Jin ', 'Pu ', 'Chou ', 'Ba ', 'Zhang ', 'Jin ', 'Jie ', 'Bing ', 'Reng ', 'Cong ', 'Fo ', + 0xD0 => 'San ', 'Lun ', 'Sya ', 'Cang ', 'Zi ', 'Shi ', 'Ta ', 'Zhang ', 'Fu ', 'Xian ', 'Xian ', 'Tuo ', 'Hong ', 'Tong ', 'Ren ', 'Qian ', + 0xE0 => 'Gan ', 'Yi ', 'Di ', 'Dai ', 'Ling ', 'Yi ', 'Chao ', 'Chang ', 'Sa ', null, 'Yi ', 'Mu ', 'Men ', 'Ren ', 'Jia ', 'Chao ', + 0xF0 => 'Yang ', 'Qian ', 'Zhong ', 'Pi ', 'Wan ', 'Wu ', 'Jian ', 'Jie ', 'Yao ', 'Feng ', 'Cang ', 'Ren ', 'Wang ', 'Fen ', 'Di ', 'Fang ', +]; diff --git a/resources/transliteration-data/x4f.php b/resources/transliteration-data/x4f.php new file mode 100644 index 000000000..0ea3d53ff --- /dev/null +++ b/resources/transliteration-data/x4f.php @@ -0,0 +1,20 @@ + 'Zhong ', 'Qi ', 'Pei ', 'Yu ', 'Diao ', 'Dun ', 'Wen ', 'Yi ', 'Xin ', 'Kang ', 'Yi ', 'Ji ', 'Ai ', 'Wu ', 'Ji ', 'Fu ', + 0x10 => 'Fa ', 'Xiu ', 'Jin ', 'Bei ', 'Dan ', 'Fu ', 'Tang ', 'Zhong ', 'You ', 'Huo ', 'Hui ', 'Yu ', 'Cui ', 'Chuan ', 'San ', 'Wei ', + 0x20 => 'Chuan ', 'Che ', 'Ya ', 'Xian ', 'Shang ', 'Chang ', 'Lun ', 'Cang ', 'Xun ', 'Xin ', 'Wei ', 'Zhu ', null, 'Xuan ', 'Nu ', 'Bo ', + 0x30 => 'Gu ', 'Ni ', 'Ni ', 'Xie ', 'Ban ', 'Xu ', 'Ling ', 'Zhou ', 'Shen ', 'Qu ', 'Si ', 'Beng ', 'Si ', 'Jia ', 'Pi ', 'Yi ', + 0x40 => 'Si ', 'Ai ', 'Zheng ', 'Dian ', 'Han ', 'Mai ', 'Dan ', 'Zhu ', 'Bu ', 'Qu ', 'Bi ', 'Shao ', 'Ci ', 'Wei ', 'Di ', 'Zhu ', + 0x50 => 'Zuo ', 'You ', 'Yang ', 'Ti ', 'Zhan ', 'He ', 'Bi ', 'Tuo ', 'She ', 'Yu ', 'Yi ', 'Fo ', 'Zuo ', 'Kou ', 'Ning ', 'Tong ', + 0x60 => 'Ni ', 'Xuan ', 'Qu ', 'Yong ', 'Wa ', 'Qian ', null, 'Ka ', null, 'Pei ', 'Huai ', 'He ', 'Lao ', 'Xiang ', 'Ge ', 'Yang ', + 0x70 => 'Bai ', 'Fa ', 'Ming ', 'Jia ', 'Er ', 'Bing ', 'Ji ', 'Hen ', 'Huo ', 'Gui ', 'Quan ', 'Tiao ', 'Jiao ', 'Ci ', 'Yi ', 'Shi ', + 0x80 => 'Xing ', 'Shen ', 'Tuo ', 'Kan ', 'Zhi ', 'Gai ', 'Lai ', 'Yi ', 'Chi ', 'Kua ', 'Guang ', 'Li ', 'Yin ', 'Shi ', 'Mi ', 'Zhu ', + 0x90 => 'Xu ', 'You ', 'An ', 'Lu ', 'Mou ', 'Er ', 'Lun ', 'Tong ', 'Cha ', 'Chi ', 'Xun ', 'Gong ', 'Zhou ', 'Yi ', 'Ru ', 'Jian ', + 0xA0 => 'Xia ', 'Jia ', 'Zai ', 'Lu ', 'Ko ', 'Jiao ', 'Zhen ', 'Ce ', 'Qiao ', 'Kuai ', 'Chai ', 'Ning ', 'Nong ', 'Jin ', 'Wu ', 'Hou ', + 0xB0 => 'Jiong ', 'Cheng ', 'Zhen ', 'Zuo ', 'Chou ', 'Qin ', 'Lu ', 'Ju ', 'Shu ', 'Ting ', 'Shen ', 'Tuo ', 'Bo ', 'Nan ', 'Hao ', 'Bian ', + 0xC0 => 'Tui ', 'Yu ', 'Xi ', 'Cu ', 'E ', 'Qiu ', 'Xu ', 'Kuang ', 'Ku ', 'Wu ', 'Jun ', 'Yi ', 'Fu ', 'Lang ', 'Zu ', 'Qiao ', + 0xD0 => 'Li ', 'Yong ', 'Hun ', 'Jing ', 'Xian ', 'San ', 'Pai ', 'Su ', 'Fu ', 'Xi ', 'Li ', 'Fu ', 'Ping ', 'Bao ', 'Yu ', 'Si ', + 0xE0 => 'Xia ', 'Xin ', 'Xiu ', 'Yu ', 'Ti ', 'Che ', 'Chou ', null, 'Yan ', 'Lia ', 'Li ', 'Lai ', null, 'Jian ', 'Xiu ', 'Fu ', + 0xF0 => 'He ', 'Ju ', 'Xiao ', 'Pai ', 'Jian ', 'Biao ', 'Chu ', 'Fei ', 'Feng ', 'Ya ', 'An ', 'Bei ', 'Yu ', 'Xin ', 'Bi ', 'Jian ', +]; diff --git a/resources/transliteration-data/x50.php b/resources/transliteration-data/x50.php new file mode 100644 index 000000000..bd708d4ec --- /dev/null +++ b/resources/transliteration-data/x50.php @@ -0,0 +1,20 @@ + 'Chang ', 'Chi ', 'Bing ', 'Zan ', 'Yao ', 'Cui ', 'Lia ', 'Wan ', 'Lai ', 'Cang ', 'Zong ', 'Ge ', 'Guan ', 'Bei ', 'Tian ', 'Shu ', + 0x10 => 'Shu ', 'Men ', 'Dao ', 'Tan ', 'Jue ', 'Chui ', 'Xing ', 'Peng ', 'Tang ', 'Hou ', 'Yi ', 'Qi ', 'Ti ', 'Gan ', 'Jing ', 'Jie ', + 0x20 => 'Sui ', 'Chang ', 'Jie ', 'Fang ', 'Zhi ', 'Kong ', 'Juan ', 'Zong ', 'Ju ', 'Qian ', 'Ni ', 'Lun ', 'Zhuo ', 'Wei ', 'Luo ', 'Song ', + 0x30 => 'Leng ', 'Hun ', 'Dong ', 'Zi ', 'Ben ', 'Wu ', 'Ju ', 'Nai ', 'Cai ', 'Jian ', 'Zhai ', 'Ye ', 'Zhi ', 'Sha ', 'Qing ', null, + 0x40 => 'Ying ', 'Cheng ', 'Jian ', 'Yan ', 'Nuan ', 'Zhong ', 'Chun ', 'Jia ', 'Jie ', 'Wei ', 'Yu ', 'Bing ', 'Ruo ', 'Ti ', 'Wei ', 'Pian ', + 0x50 => 'Yan ', 'Feng ', 'Tang ', 'Wo ', 'E ', 'Xie ', 'Che ', 'Sheng ', 'Kan ', 'Di ', 'Zuo ', 'Cha ', 'Ting ', 'Bei ', 'Ye ', 'Huang ', + 0x60 => 'Yao ', 'Zhan ', 'Chou ', 'Yan ', 'You ', 'Jian ', 'Xu ', 'Zha ', 'Ci ', 'Fu ', 'Bi ', 'Zhi ', 'Zong ', 'Mian ', 'Ji ', 'Yi ', + 0x70 => 'Xie ', 'Xun ', 'Si ', 'Duan ', 'Ce ', 'Zhen ', 'Ou ', 'Tou ', 'Tou ', 'Bei ', 'Za ', 'Lu ', 'Jie ', 'Wei ', 'Fen ', 'Chang ', + 0x80 => 'Gui ', 'Sou ', 'Zhi ', 'Su ', 'Xia ', 'Fu ', 'Yuan ', 'Rong ', 'Li ', 'Ru ', 'Yun ', 'Gou ', 'Ma ', 'Bang ', 'Dian ', 'Tang ', + 0x90 => 'Hao ', 'Jie ', 'Xi ', 'Shan ', 'Qian ', 'Jue ', 'Cang ', 'Chu ', 'San ', 'Bei ', 'Xiao ', 'Yong ', 'Yao ', 'Tan ', 'Suo ', 'Yang ', + 0xA0 => 'Fa ', 'Bing ', 'Jia ', 'Dai ', 'Zai ', 'Tang ', null, 'Bin ', 'Chu ', 'Nuo ', 'Can ', 'Lei ', 'Cui ', 'Yong ', 'Zao ', 'Zong ', + 0xB0 => 'Peng ', 'Song ', 'Ao ', 'Chuan ', 'Yu ', 'Zhai ', 'Cou ', 'Shang ', 'Qiang ', 'Jing ', 'Chi ', 'Sha ', 'Han ', 'Zhang ', 'Qing ', 'Yan ', + 0xC0 => 'Di ', 'Xi ', 'Lu ', 'Bei ', 'Piao ', 'Jin ', 'Lian ', 'Lu ', 'Man ', 'Qian ', 'Xian ', 'Tan ', 'Ying ', 'Dong ', 'Zhuan ', 'Xiang ', + 0xD0 => 'Shan ', 'Qiao ', 'Jiong ', 'Tui ', 'Zun ', 'Pu ', 'Xi ', 'Lao ', 'Chang ', 'Guang ', 'Liao ', 'Qi ', 'Deng ', 'Chan ', 'Wei ', 'Ji ', + 0xE0 => 'Fan ', 'Hui ', 'Chuan ', 'Jian ', 'Dan ', 'Jiao ', 'Jiu ', 'Seng ', 'Fen ', 'Xian ', 'Jue ', 'E ', 'Jiao ', 'Jian ', 'Tong ', 'Lin ', + 0xF0 => 'Bo ', 'Gu ', null, 'Su ', 'Xian ', 'Jiang ', 'Min ', 'Ye ', 'Jin ', 'Jia ', 'Qiao ', 'Pi ', 'Feng ', 'Zhou ', 'Ai ', 'Sai ', +]; diff --git a/resources/transliteration-data/x51.php b/resources/transliteration-data/x51.php new file mode 100644 index 000000000..49bbad21e --- /dev/null +++ b/resources/transliteration-data/x51.php @@ -0,0 +1,20 @@ + 'Yi ', 'Jun ', 'Nong ', 'Chan ', 'Yi ', 'Dang ', 'Jing ', 'Xuan ', 'Kuai ', 'Jian ', 'Chu ', 'Dan ', 'Jiao ', 'Sha ', 'Zai ', null, + 0x10 => 'Bin ', 'An ', 'Ru ', 'Tai ', 'Chou ', 'Chai ', 'Lan ', 'Ni ', 'Jin ', 'Qian ', 'Meng ', 'Wu ', 'Ning ', 'Qiong ', 'Ni ', 'Chang ', + 0x20 => 'Lie ', 'Lei ', 'Lu ', 'Kuang ', 'Bao ', 'Du ', 'Biao ', 'Zan ', 'Zhi ', 'Si ', 'You ', 'Hao ', 'Chen ', 'Chen ', 'Li ', 'Teng ', + 0x30 => 'Wei ', 'Long ', 'Chu ', 'Chan ', 'Rang ', 'Shu ', 'Hui ', 'Li ', 'Luo ', 'Zan ', 'Nuo ', 'Tang ', 'Yan ', 'Lei ', 'Nang ', 'Er ', + 0x40 => 'Wu ', 'Yun ', 'Zan ', 'Yuan ', 'Xiong ', 'Chong ', 'Zhao ', 'Xiong ', 'Xian ', 'Guang ', 'Dui ', 'Ke ', 'Dui ', 'Mian ', 'Tu ', 'Chang ', + 0x50 => 'Er ', 'Dui ', 'Er ', 'Xin ', 'Tu ', 'Si ', 'Yan ', 'Yan ', 'Shi ', 'Shi ', 'Dang ', 'Qian ', 'Dou ', 'Fen ', 'Mao ', 'Shen ', + 0x60 => 'Dou ', 'Bai ', 'Jing ', 'Li ', 'Huang ', 'Ru ', 'Wang ', 'Nei ', 'Quan ', 'Liang ', 'Yu ', 'Ba ', 'Gong ', 'Liu ', 'Xi ', null, + 0x70 => 'Lan ', 'Gong ', 'Tian ', 'Guan ', 'Xing ', 'Bing ', 'Qi ', 'Ju ', 'Dian ', 'Zi ', 'Ppwun ', 'Yang ', 'Jian ', 'Shou ', 'Ji ', 'Yi ', + 0x80 => 'Ji ', 'Chan ', 'Jiong ', 'Mao ', 'Ran ', 'Nei ', 'Yuan ', 'Mao ', 'Gang ', 'Ran ', 'Ce ', 'Jiong ', 'Ce ', 'Zai ', 'Gua ', 'Jiong ', + 0x90 => 'Mao ', 'Zhou ', 'Mou ', 'Gou ', 'Xu ', 'Mian ', 'Mi ', 'Rong ', 'Yin ', 'Xie ', 'Kan ', 'Jun ', 'Nong ', 'Yi ', 'Mi ', 'Shi ', + 0xA0 => 'Guan ', 'Meng ', 'Zhong ', 'Ju ', 'Yuan ', 'Ming ', 'Kou ', 'Lam ', 'Fu ', 'Xie ', 'Mi ', 'Bing ', 'Dong ', 'Tai ', 'Gang ', 'Feng ', + 0xB0 => 'Bing ', 'Hu ', 'Chong ', 'Jue ', 'Hu ', 'Kuang ', 'Ye ', 'Leng ', 'Pan ', 'Fu ', 'Min ', 'Dong ', 'Xian ', 'Lie ', 'Xia ', 'Jian ', + 0xC0 => 'Jing ', 'Shu ', 'Mei ', 'Tu ', 'Qi ', 'Gu ', 'Zhun ', 'Song ', 'Jing ', 'Liang ', 'Qing ', 'Diao ', 'Ling ', 'Dong ', 'Gan ', 'Jian ', + 0xD0 => 'Yin ', 'Cou ', 'Yi ', 'Li ', 'Cang ', 'Ming ', 'Zhuen ', 'Cui ', 'Si ', 'Duo ', 'Jin ', 'Lin ', 'Lin ', 'Ning ', 'Xi ', 'Du ', + 0xE0 => 'Ji ', 'Fan ', 'Fan ', 'Fan ', 'Feng ', 'Ju ', 'Chu ', 'Tako ', 'Feng ', 'Mok ', 'Ci ', 'Fu ', 'Feng ', 'Ping ', 'Feng ', 'Kai ', + 0xF0 => 'Huang ', 'Kai ', 'Gan ', 'Deng ', 'Ping ', 'Qu ', 'Xiong ', 'Kuai ', 'Tu ', 'Ao ', 'Chu ', 'Ji ', 'Dang ', 'Han ', 'Han ', 'Zao ', +]; diff --git a/resources/transliteration-data/x52.php b/resources/transliteration-data/x52.php new file mode 100644 index 000000000..7c5e38acd --- /dev/null +++ b/resources/transliteration-data/x52.php @@ -0,0 +1,20 @@ + 'Dao ', 'Diao ', 'Dao ', 'Ren ', 'Ren ', 'Chuang ', 'Fen ', 'Qie ', 'Yi ', 'Ji ', 'Kan ', 'Qian ', 'Cun ', 'Chu ', 'Wen ', 'Ji ', + 0x10 => 'Dan ', 'Xing ', 'Hua ', 'Wan ', 'Jue ', 'Li ', 'Yue ', 'Lie ', 'Liu ', 'Ze ', 'Gang ', 'Chuang ', 'Fu ', 'Chu ', 'Qu ', 'Ju ', + 0x20 => 'Shan ', 'Min ', 'Ling ', 'Zhong ', 'Pan ', 'Bie ', 'Jie ', 'Jie ', 'Bao ', 'Li ', 'Shan ', 'Bie ', 'Chan ', 'Jing ', 'Gua ', 'Gen ', + 0x30 => 'Dao ', 'Chuang ', 'Kui ', 'Ku ', 'Duo ', 'Er ', 'Zhi ', 'Shua ', 'Quan ', 'Cha ', 'Ci ', 'Ke ', 'Jie ', 'Gui ', 'Ci ', 'Gui ', + 0x40 => 'Kai ', 'Duo ', 'Ji ', 'Ti ', 'Jing ', 'Lou ', 'Gen ', 'Ze ', 'Yuan ', 'Cuo ', 'Xue ', 'Ke ', 'La ', 'Qian ', 'Cha ', 'Chuang ', + 0x50 => 'Gua ', 'Jian ', 'Cuo ', 'Li ', 'Ti ', 'Fei ', 'Pou ', 'Chan ', 'Qi ', 'Chuang ', 'Zi ', 'Gang ', 'Wan ', 'Bo ', 'Ji ', 'Duo ', + 0x60 => 'Qing ', 'Yan ', 'Zhuo ', 'Jian ', 'Ji ', 'Bo ', 'Yan ', 'Ju ', 'Huo ', 'Sheng ', 'Jian ', 'Duo ', 'Duan ', 'Wu ', 'Gua ', 'Fu ', + 0x70 => 'Sheng ', 'Jian ', 'Ge ', 'Zha ', 'Kai ', 'Chuang ', 'Juan ', 'Chan ', 'Tuan ', 'Lu ', 'Li ', 'Fou ', 'Shan ', 'Piao ', 'Kou ', 'Jiao ', + 0x80 => 'Gua ', 'Qiao ', 'Jue ', 'Hua ', 'Zha ', 'Zhuo ', 'Lian ', 'Ju ', 'Pi ', 'Liu ', 'Gui ', 'Jiao ', 'Gui ', 'Jian ', 'Jian ', 'Tang ', + 0x90 => 'Huo ', 'Ji ', 'Jian ', 'Yi ', 'Jian ', 'Zhi ', 'Chan ', 'Cuan ', 'Mo ', 'Li ', 'Zhu ', 'Li ', 'Ya ', 'Quan ', 'Ban ', 'Gong ', + 0xA0 => 'Jia ', 'Wu ', 'Mai ', 'Lie ', 'Jin ', 'Keng ', 'Xie ', 'Zhi ', 'Dong ', 'Zhu ', 'Nu ', 'Jie ', 'Qu ', 'Shao ', 'Yi ', 'Zhu ', + 0xB0 => 'Miao ', 'Li ', 'Jing ', 'Lao ', 'Lao ', 'Juan ', 'Kou ', 'Yang ', 'Wa ', 'Xiao ', 'Mou ', 'Kuang ', 'Jie ', 'Lie ', 'He ', 'Shi ', + 0xC0 => 'Ke ', 'Jing ', 'Hao ', 'Bo ', 'Min ', 'Chi ', 'Lang ', 'Yong ', 'Yong ', 'Mian ', 'Ke ', 'Xun ', 'Juan ', 'Qing ', 'Lu ', 'Pou ', + 0xD0 => 'Meng ', 'Lai ', 'Le ', 'Kai ', 'Mian ', 'Dong ', 'Xu ', 'Xu ', 'Kan ', 'Wu ', 'Yi ', 'Xun ', 'Weng ', 'Sheng ', 'Lao ', 'Mu ', + 0xE0 => 'Lu ', 'Piao ', 'Shi ', 'Ji ', 'Qin ', 'Qiang ', 'Jiao ', 'Quan ', 'Yang ', 'Yi ', 'Jue ', 'Fan ', 'Juan ', 'Tong ', 'Ju ', 'Dan ', + 0xF0 => 'Xie ', 'Mai ', 'Xun ', 'Xun ', 'Lu ', 'Li ', 'Che ', 'Rang ', 'Quan ', 'Bao ', 'Shao ', 'Yun ', 'Jiu ', 'Bao ', 'Gou ', 'Wu ', +]; diff --git a/resources/transliteration-data/x53.php b/resources/transliteration-data/x53.php new file mode 100644 index 000000000..f003469d3 --- /dev/null +++ b/resources/transliteration-data/x53.php @@ -0,0 +1,20 @@ + 'Yun ', 'Mwun ', 'Nay ', 'Gai ', 'Gai ', 'Bao ', 'Cong ', null, 'Xiong ', 'Peng ', 'Ju ', 'Tao ', 'Ge ', 'Pu ', 'An ', 'Pao ', + 0x10 => 'Fu ', 'Gong ', 'Da ', 'Jiu ', 'Qiong ', 'Bi ', 'Hua ', 'Bei ', 'Nao ', 'Chi ', 'Fang ', 'Jiu ', 'Yi ', 'Za ', 'Jiang ', 'Kang ', + 0x20 => 'Jiang ', 'Kuang ', 'Hu ', 'Xia ', 'Qu ', 'Bian ', 'Gui ', 'Qie ', 'Zang ', 'Kuang ', 'Fei ', 'Hu ', 'Tou ', 'Gui ', 'Gui ', 'Hui ', + 0x30 => 'Dan ', 'Gui ', 'Lian ', 'Lian ', 'Suan ', 'Du ', 'Jiu ', 'Qu ', 'Xi ', 'Pi ', 'Qu ', 'Yi ', 'Qia ', 'Yan ', 'Bian ', 'Ni ', + 0x40 => 'Qu ', 'Shi ', 'Xin ', 'Qian ', 'Nian ', 'Sa ', 'Zu ', 'Sheng ', 'Wu ', 'Hui ', 'Ban ', 'Shi ', 'Xi ', 'Wan ', 'Hua ', 'Xie ', + 0x50 => 'Wan ', 'Bei ', 'Zu ', 'Zhuo ', 'Xie ', 'Dan ', 'Mai ', 'Nan ', 'Dan ', 'Ji ', 'Bo ', 'Shuai ', 'Bu ', 'Kuang ', 'Bian ', 'Bu ', + 0x60 => 'Zhan ', 'Qia ', 'Lu ', 'You ', 'Lu ', 'Xi ', 'Gua ', 'Wo ', 'Xie ', 'Jie ', 'Jie ', 'Wei ', 'Ang ', 'Qiong ', 'Zhi ', 'Mao ', + 0x70 => 'Yin ', 'Wei ', 'Shao ', 'Ji ', 'Que ', 'Luan ', 'Shi ', 'Juan ', 'Xie ', 'Xu ', 'Jin ', 'Que ', 'Wu ', 'Ji ', 'E ', 'Qing ', + 0x80 => 'Xi ', null, 'Han ', 'Zhan ', 'E ', 'Ting ', 'Li ', 'Zhe ', 'Han ', 'Li ', 'Ya ', 'Ya ', 'Yan ', 'She ', 'Zhi ', 'Zha ', + 0x90 => 'Pang ', null, 'He ', 'Ya ', 'Zhi ', 'Ce ', 'Pang ', 'Ti ', 'Li ', 'She ', 'Hou ', 'Ting ', 'Zui ', 'Cuo ', 'Fei ', 'Yuan ', + 0xA0 => 'Ce ', 'Yuan ', 'Xiang ', 'Yan ', 'Li ', 'Jue ', 'Sha ', 'Dian ', 'Chu ', 'Jiu ', 'Qin ', 'Ao ', 'Gui ', 'Yan ', 'Si ', 'Li ', + 0xB0 => 'Chang ', 'Lan ', 'Li ', 'Yan ', 'Yan ', 'Yuan ', 'Si ', 'Gong ', 'Lin ', 'Qiu ', 'Qu ', 'Qu ', 'Uk ', 'Lei ', 'Du ', 'Xian ', + 0xC0 => 'Zhuan ', 'San ', 'Can ', 'Can ', 'Can ', 'Can ', 'Ai ', 'Dai ', 'You ', 'Cha ', 'Ji ', 'You ', 'Shuang ', 'Fan ', 'Shou ', 'Guai ', + 0xD0 => 'Ba ', 'Fa ', 'Ruo ', 'Shi ', 'Shu ', 'Zhuo ', 'Qu ', 'Shou ', 'Bian ', 'Xu ', 'Jia ', 'Pan ', 'Sou ', 'Gao ', 'Wei ', 'Sou ', + 0xE0 => 'Die ', 'Rui ', 'Cong ', 'Kou ', 'Gu ', 'Ju ', 'Ling ', 'Gua ', 'Tao ', 'Kou ', 'Zhi ', 'Jiao ', 'Zhao ', 'Ba ', 'Ding ', 'Ke ', + 0xF0 => 'Tai ', 'Chi ', 'Shi ', 'You ', 'Qiu ', 'Po ', 'Xie ', 'Hao ', 'Si ', 'Tan ', 'Chi ', 'Le ', 'Diao ', 'Ji ', null, 'Hong ', +]; diff --git a/resources/transliteration-data/x54.php b/resources/transliteration-data/x54.php new file mode 100644 index 000000000..f59641bce --- /dev/null +++ b/resources/transliteration-data/x54.php @@ -0,0 +1,20 @@ + 'Mie ', 'Xu ', 'Mang ', 'Chi ', 'Ge ', 'Xuan ', 'Yao ', 'Zi ', 'He ', 'Ji ', 'Diao ', 'Cun ', 'Tong ', 'Ming ', 'Hou ', 'Li ', + 0x10 => 'Tu ', 'Xiang ', 'Zha ', 'Xia ', 'Ye ', 'Lu ', 'A ', 'Ma ', 'Ou ', 'Xue ', 'Yi ', 'Jun ', 'Chou ', 'Lin ', 'Tun ', 'Yin ', + 0x20 => 'Fei ', 'Bi ', 'Qin ', 'Qin ', 'Jie ', 'Bu ', 'Fou ', 'Ba ', 'Dun ', 'Fen ', 'E ', 'Han ', 'Ting ', 'Hang ', 'Shun ', 'Qi ', + 0x30 => 'Hong ', 'Zhi ', 'Shen ', 'Wu ', 'Wu ', 'Chao ', 'Ne ', 'Xue ', 'Xi ', 'Chui ', 'Dou ', 'Wen ', 'Hou ', 'Ou ', 'Wu ', 'Gao ', + 0x40 => 'Ya ', 'Jun ', 'Lu ', 'E ', 'Ge ', 'Mei ', 'Ai ', 'Qi ', 'Cheng ', 'Wu ', 'Gao ', 'Fu ', 'Jiao ', 'Hong ', 'Chi ', 'Sheng ', + 0x50 => 'Ne ', 'Tun ', 'Fu ', 'Yi ', 'Dai ', 'Ou ', 'Li ', 'Bai ', 'Yuan ', 'Kuai ', null, 'Qiang ', 'Wu ', 'E ', 'Shi ', 'Quan ', + 0x60 => 'Pen ', 'Wen ', 'Ni ', 'M ', 'Ling ', 'Ran ', 'You ', 'Di ', 'Zhou ', 'Shi ', 'Zhou ', 'Tie ', 'Xi ', 'Yi ', 'Qi ', 'Ping ', + 0x70 => 'Zi ', 'Gu ', 'Zi ', 'Wei ', 'Xu ', 'He ', 'Nao ', 'Xia ', 'Pei ', 'Yi ', 'Xiao ', 'Shen ', 'Hu ', 'Ming ', 'Da ', 'Qu ', + 0x80 => 'Ju ', 'Gem ', 'Za ', 'Tuo ', 'Duo ', 'Pou ', 'Pao ', 'Bi ', 'Fu ', 'Yang ', 'He ', 'Zha ', 'He ', 'Hai ', 'Jiu ', 'Yong ', + 0x90 => 'Fu ', 'Que ', 'Zhou ', 'Wa ', 'Ka ', 'Gu ', 'Ka ', 'Zuo ', 'Bu ', 'Long ', 'Dong ', 'Ning ', 'Tha ', 'Si ', 'Xian ', 'Huo ', + 0xA0 => 'Qi ', 'Er ', 'E ', 'Guang ', 'Zha ', 'Xi ', 'Yi ', 'Lie ', 'Zi ', 'Mie ', 'Mi ', 'Zhi ', 'Yao ', 'Ji ', 'Zhou ', 'Ge ', + 0xB0 => 'Shuai ', 'Zan ', 'Xiao ', 'Ke ', 'Hui ', 'Kua ', 'Huai ', 'Tao ', 'Xian ', 'E ', 'Xuan ', 'Xiu ', 'Wai ', 'Yan ', 'Lao ', 'Yi ', + 0xC0 => 'Ai ', 'Pin ', 'Shen ', 'Tong ', 'Hong ', 'Xiong ', 'Chi ', 'Wa ', 'Ha ', 'Zai ', 'Yu ', 'Di ', 'Pai ', 'Xiang ', 'Ai ', 'Hen ', + 0xD0 => 'Kuang ', 'Ya ', 'Da ', 'Xiao ', 'Bi ', 'Yue ', null, 'Hua ', 'Sasou ', 'Kuai ', 'Duo ', null, 'Ji ', 'Nong ', 'Mou ', 'Yo ', + 0xE0 => 'Hao ', 'Yuan ', 'Long ', 'Pou ', 'Mang ', 'Ge ', 'E ', 'Chi ', 'Shao ', 'Li ', 'Na ', 'Zu ', 'He ', 'Ku ', 'Xiao ', 'Xian ', + 0xF0 => 'Lao ', 'Bo ', 'Zhe ', 'Zha ', 'Liang ', 'Ba ', 'Mie ', 'Le ', 'Sui ', 'Fou ', 'Bu ', 'Han ', 'Heng ', 'Geng ', 'Shuo ', 'Ge ', +]; diff --git a/resources/transliteration-data/x55.php b/resources/transliteration-data/x55.php new file mode 100644 index 000000000..efa9f439b --- /dev/null +++ b/resources/transliteration-data/x55.php @@ -0,0 +1,20 @@ + 'You ', 'Yan ', 'Gu ', 'Gu ', 'Bai ', 'Han ', 'Suo ', 'Chun ', 'Yi ', 'Ai ', 'Jia ', 'Tu ', 'Xian ', 'Huan ', 'Li ', 'Xi ', + 0x10 => 'Tang ', 'Zuo ', 'Qiu ', 'Che ', 'Wu ', 'Zao ', 'Ya ', 'Dou ', 'Qi ', 'Di ', 'Qin ', 'Ma ', 'Mal ', 'Hong ', 'Dou ', 'Kes ', + 0x20 => 'Lao ', 'Liang ', 'Suo ', 'Zao ', 'Huan ', 'Lang ', 'Sha ', 'Ji ', 'Zuo ', 'Wo ', 'Feng ', 'Yin ', 'Hu ', 'Qi ', 'Shou ', 'Wei ', + 0x30 => 'Shua ', 'Chang ', 'Er ', 'Li ', 'Qiang ', 'An ', 'Jie ', 'Yo ', 'Nian ', 'Yu ', 'Tian ', 'Lai ', 'Sha ', 'Xi ', 'Tuo ', 'Hu ', + 0x40 => 'Ai ', 'Zhou ', 'Nou ', 'Ken ', 'Zhuo ', 'Zhuo ', 'Shang ', 'Di ', 'Heng ', 'Lan ', 'A ', 'Xiao ', 'Xiang ', 'Tun ', 'Wu ', 'Wen ', + 0x50 => 'Cui ', 'Sha ', 'Hu ', 'Qi ', 'Qi ', 'Tao ', 'Dan ', 'Dan ', 'Ye ', 'Zi ', 'Bi ', 'Cui ', 'Chuo ', 'He ', 'Ya ', 'Qi ', + 0x60 => 'Zhe ', 'Pei ', 'Liang ', 'Xian ', 'Pi ', 'Sha ', 'La ', 'Ze ', 'Qing ', 'Gua ', 'Pa ', 'Zhe ', 'Se ', 'Zhuan ', 'Nie ', 'Guo ', + 0x70 => 'Luo ', 'Yan ', 'Di ', 'Quan ', 'Tan ', 'Bo ', 'Ding ', 'Lang ', 'Xiao ', null, 'Tang ', 'Chi ', 'Ti ', 'An ', 'Jiu ', 'Dan ', + 0x80 => 'Ke ', 'Yong ', 'Wei ', 'Nan ', 'Shan ', 'Yu ', 'Zhe ', 'La ', 'Jie ', 'Hou ', 'Han ', 'Die ', 'Zhou ', 'Chai ', 'Wai ', 'Re ', + 0x90 => 'Yu ', 'Yin ', 'Zan ', 'Yao ', 'Wo ', 'Mian ', 'Hu ', 'Yun ', 'Chuan ', 'Hui ', 'Huan ', 'Huan ', 'Xi ', 'He ', 'Ji ', 'Kui ', + 0xA0 => 'Zhong ', 'Wei ', 'Sha ', 'Xu ', 'Huang ', 'Du ', 'Nie ', 'Xuan ', 'Liang ', 'Yu ', 'Sang ', 'Chi ', 'Qiao ', 'Yan ', 'Dan ', 'Pen ', + 0xB0 => 'Can ', 'Li ', 'Yo ', 'Zha ', 'Wei ', 'Miao ', 'Ying ', 'Pen ', 'Phos ', 'Kui ', 'Xi ', 'Yu ', 'Jie ', 'Lou ', 'Ku ', 'Sao ', + 0xC0 => 'Huo ', 'Ti ', 'Yao ', 'He ', 'A ', 'Xiu ', 'Qiang ', 'Se ', 'Yong ', 'Su ', 'Hong ', 'Xie ', 'Yi ', 'Suo ', 'Ma ', 'Cha ', + 0xD0 => 'Hai ', 'Ke ', 'Ta ', 'Sang ', 'Tian ', 'Ru ', 'Sou ', 'Wa ', 'Ji ', 'Pang ', 'Wu ', 'Xian ', 'Shi ', 'Ge ', 'Zi ', 'Jie ', + 0xE0 => 'Luo ', 'Weng ', 'Wa ', 'Si ', 'Chi ', 'Hao ', 'Suo ', 'Jia ', 'Hai ', 'Suo ', 'Qin ', 'Nie ', 'He ', 'Cis ', 'Sai ', 'Ng ', + 0xF0 => 'Ge ', 'Na ', 'Dia ', 'Ai ', null, 'Tong ', 'Bi ', 'Ao ', 'Ao ', 'Lian ', 'Cui ', 'Zhe ', 'Mo ', 'Sou ', 'Sou ', 'Tan ', +]; diff --git a/resources/transliteration-data/x56.php b/resources/transliteration-data/x56.php new file mode 100644 index 000000000..3906a3b13 --- /dev/null +++ b/resources/transliteration-data/x56.php @@ -0,0 +1,20 @@ + 'Di ', 'Qi ', 'Jiao ', 'Chong ', 'Jiao ', 'Kai ', 'Tan ', 'San ', 'Cao ', 'Jia ', 'Ai ', 'Xiao ', 'Piao ', 'Lou ', 'Ga ', 'Gu ', + 0x10 => 'Xiao ', 'Hu ', 'Hui ', 'Guo ', 'Ou ', 'Xian ', 'Ze ', 'Chang ', 'Xu ', 'Po ', 'De ', 'Ma ', 'Ma ', 'Hu ', 'Lei ', 'Du ', + 0x20 => 'Ga ', 'Tang ', 'Ye ', 'Beng ', 'Ying ', 'Saai ', 'Jiao ', 'Mi ', 'Xiao ', 'Hua ', 'Mai ', 'Ran ', 'Zuo ', 'Peng ', 'Lao ', 'Xiao ', + 0x30 => 'Ji ', 'Zhu ', 'Chao ', 'Kui ', 'Zui ', 'Xiao ', 'Si ', 'Hao ', 'Fu ', 'Liao ', 'Qiao ', 'Xi ', 'Xiu ', 'Tan ', 'Tan ', 'Mo ', + 0x40 => 'Xun ', 'E ', 'Zun ', 'Fan ', 'Chi ', 'Hui ', 'Zan ', 'Chuang ', 'Cu ', 'Dan ', 'Yu ', 'Tun ', 'Cheng ', 'Jiao ', 'Ye ', 'Xi ', + 0x50 => 'Qi ', 'Hao ', 'Lian ', 'Xu ', 'Deng ', 'Hui ', 'Yin ', 'Pu ', 'Jue ', 'Qin ', 'Xun ', 'Nie ', 'Lu ', 'Si ', 'Yan ', 'Ying ', + 0x60 => 'Da ', 'Dan ', 'Yu ', 'Zhou ', 'Jin ', 'Nong ', 'Yue ', 'Hui ', 'Qi ', 'E ', 'Zao ', 'Yi ', 'Shi ', 'Jiao ', 'Yuan ', 'Ai ', + 0x70 => 'Yong ', 'Jue ', 'Kuai ', 'Yu ', 'Pen ', 'Dao ', 'Ge ', 'Xin ', 'Dun ', 'Dang ', 'Sin ', 'Sai ', 'Pi ', 'Pi ', 'Yin ', 'Zui ', + 0x80 => 'Ning ', 'Di ', 'Lan ', 'Ta ', 'Huo ', 'Ru ', 'Hao ', 'Xia ', 'Ya ', 'Duo ', 'Xi ', 'Chou ', 'Ji ', 'Jin ', 'Hao ', 'Ti ', + 0x90 => 'Chang ', null, null, 'Ca ', 'Ti ', 'Lu ', 'Hui ', 'Bo ', 'You ', 'Nie ', 'Yin ', 'Hu ', 'Mo ', 'Huang ', 'Zhe ', 'Li ', + 0xA0 => 'Liu ', 'Haai ', 'Nang ', 'Xiao ', 'Mo ', 'Yan ', 'Li ', 'Lu ', 'Long ', 'Fu ', 'Dan ', 'Chen ', 'Pin ', 'Pi ', 'Xiang ', 'Huo ', + 0xB0 => 'Mo ', 'Xi ', 'Duo ', 'Ku ', 'Yan ', 'Chan ', 'Ying ', 'Rang ', 'Dian ', 'La ', 'Ta ', 'Xiao ', 'Jiao ', 'Chuo ', 'Huan ', 'Huo ', + 0xC0 => 'Zhuan ', 'Nie ', 'Xiao ', 'Ca ', 'Li ', 'Chan ', 'Chai ', 'Li ', 'Yi ', 'Luo ', 'Nang ', 'Zan ', 'Su ', 'Xi ', 'So ', 'Jian ', + 0xD0 => 'Za ', 'Zhu ', 'Lan ', 'Nie ', 'Nang ', null, null, 'Wei ', 'Hui ', 'Yin ', 'Qiu ', 'Si ', 'Nin ', 'Jian ', 'Hui ', 'Xin ', + 0xE0 => 'Yin ', 'Nan ', 'Tuan ', 'Tuan ', 'Dun ', 'Kang ', 'Yuan ', 'Jiong ', 'Pian ', 'Yun ', 'Cong ', 'Hu ', 'Hui ', 'Yuan ', 'You ', 'Guo ', + 0xF0 => 'Kun ', 'Cong ', 'Wei ', 'Tu ', 'Wei ', 'Lun ', 'Guo ', 'Qun ', 'Ri ', 'Ling ', 'Gu ', 'Guo ', 'Tai ', 'Guo ', 'Tu ', 'You ', +]; diff --git a/resources/transliteration-data/x57.php b/resources/transliteration-data/x57.php new file mode 100644 index 000000000..b9e74ec25 --- /dev/null +++ b/resources/transliteration-data/x57.php @@ -0,0 +1,20 @@ + 'Guo ', 'Yin ', 'Hun ', 'Pu ', 'Yu ', 'Han ', 'Yuan ', 'Lun ', 'Quan ', 'Yu ', 'Qing ', 'Guo ', 'Chuan ', 'Wei ', 'Yuan ', 'Quan ', + 0x10 => 'Ku ', 'Fu ', 'Yuan ', 'Yuan ', 'E ', 'Tu ', 'Tu ', 'Tu ', 'Tuan ', 'Lue ', 'Hui ', 'Yi ', 'Yuan ', 'Luan ', 'Luan ', 'Tu ', + 0x20 => 'Ya ', 'Tu ', 'Ting ', 'Sheng ', 'Pu ', 'Lu ', 'Iri ', 'Ya ', 'Zai ', 'Wei ', 'Ge ', 'Yu ', 'Wu ', 'Gui ', 'Pi ', 'Yi ', + 0x30 => 'Di ', 'Qian ', 'Qian ', 'Zhen ', 'Zhuo ', 'Dang ', 'Qia ', 'Akutsu ', 'Yama ', 'Kuang ', 'Chang ', 'Qi ', 'Nie ', 'Mo ', 'Ji ', 'Jia ', + 0x40 => 'Zhi ', 'Zhi ', 'Ban ', 'Xun ', 'Tou ', 'Qin ', 'Fen ', 'Jun ', 'Keng ', 'Tun ', 'Fang ', 'Fen ', 'Ben ', 'Tan ', 'Kan ', 'Pi ', + 0x50 => 'Zuo ', 'Keng ', 'Bi ', 'Xing ', 'Di ', 'Jing ', 'Ji ', 'Kuai ', 'Di ', 'Jing ', 'Jian ', 'Tan ', 'Li ', 'Ba ', 'Wu ', 'Fen ', + 0x60 => 'Zhui ', 'Po ', 'Pan ', 'Tang ', 'Kun ', 'Qu ', 'Tan ', 'Zhi ', 'Tuo ', 'Gan ', 'Ping ', 'Dian ', 'Gua ', 'Ni ', 'Tai ', 'Pi ', + 0x70 => 'Jiong ', 'Yang ', 'Fo ', 'Ao ', 'Liu ', 'Qiu ', 'Mu ', 'Ke ', 'Gou ', 'Xue ', 'Ba ', 'Chi ', 'Che ', 'Ling ', 'Zhu ', 'Fu ', + 0x80 => 'Hu ', 'Zhi ', 'Chui ', 'La ', 'Long ', 'Long ', 'Lu ', 'Ao ', 'Tay ', 'Pao ', null, 'Xing ', 'Dong ', 'Ji ', 'Ke ', 'Lu ', + 0x90 => 'Ci ', 'Chi ', 'Lei ', 'Gai ', 'Yin ', 'Hou ', 'Dui ', 'Zhao ', 'Fu ', 'Guang ', 'Yao ', 'Duo ', 'Duo ', 'Gui ', 'Cha ', 'Yang ', + 0xA0 => 'Yin ', 'Fa ', 'Gou ', 'Yuan ', 'Die ', 'Xie ', 'Ken ', 'Jiong ', 'Shou ', 'E ', 'Ha ', 'Dian ', 'Hong ', 'Wu ', 'Kua ', null, + 0xB0 => 'Tao ', 'Dang ', 'Kai ', 'Gake ', 'Nao ', 'An ', 'Xing ', 'Xian ', 'Huan ', 'Bang ', 'Pei ', 'Ba ', 'Yi ', 'Yin ', 'Han ', 'Xu ', + 0xC0 => 'Chui ', 'Cen ', 'Geng ', 'Ai ', 'Peng ', 'Fang ', 'Que ', 'Yong ', 'Xun ', 'Jia ', 'Di ', 'Mai ', 'Lang ', 'Xuan ', 'Cheng ', 'Yan ', + 0xD0 => 'Jin ', 'Zhe ', 'Lei ', 'Lie ', 'Bu ', 'Cheng ', 'Gomi ', 'Bu ', 'Shi ', 'Xun ', 'Guo ', 'Jiong ', 'Ye ', 'Nian ', 'Di ', 'Yu ', + 0xE0 => 'Bu ', 'Ya ', 'Juan ', 'Sui ', 'Pi ', 'Cheng ', 'Wan ', 'Ju ', 'Lun ', 'Zheng ', 'Kong ', 'Chong ', 'Dong ', 'Dai ', 'Tan ', 'An ', + 0xF0 => 'Cai ', 'Shu ', 'Beng ', 'Kan ', 'Zhi ', 'Duo ', 'Yi ', 'Zhi ', 'Yi ', 'Pei ', 'Ji ', 'Zhun ', 'Qi ', 'Sao ', 'Ju ', 'Ni ', +]; diff --git a/resources/transliteration-data/x58.php b/resources/transliteration-data/x58.php new file mode 100644 index 000000000..4f6de5241 --- /dev/null +++ b/resources/transliteration-data/x58.php @@ -0,0 +1,20 @@ + 'Ku ', 'Ke ', 'Tang ', 'Kun ', 'Ni ', 'Jian ', 'Dui ', 'Jin ', 'Gang ', 'Yu ', 'E ', 'Peng ', 'Gu ', 'Tu ', 'Leng ', null, + 0x10 => 'Ya ', 'Qian ', null, 'An ', null, 'Duo ', 'Nao ', 'Tu ', 'Cheng ', 'Yin ', 'Hun ', 'Bi ', 'Lian ', 'Guo ', 'Die ', 'Zhuan ', + 0x20 => 'Hou ', 'Bao ', 'Bao ', 'Yu ', 'Di ', 'Mao ', 'Jie ', 'Ruan ', 'E ', 'Geng ', 'Kan ', 'Zong ', 'Yu ', 'Huang ', 'E ', 'Yao ', + 0x30 => 'Yan ', 'Bao ', 'Ji ', 'Mei ', 'Chang ', 'Du ', 'Tuo ', 'Yin ', 'Feng ', 'Zhong ', 'Jie ', 'Zhen ', 'Feng ', 'Gang ', 'Chuan ', 'Jian ', + 0x40 => 'Pyeng ', 'Toride ', 'Xiang ', 'Huang ', 'Leng ', 'Duan ', null, 'Xuan ', 'Ji ', 'Ji ', 'Kuai ', 'Ying ', 'Ta ', 'Cheng ', 'Yong ', 'Kai ', + 0x50 => 'Su ', 'Su ', 'Shi ', 'Mi ', 'Ta ', 'Weng ', 'Cheng ', 'Tu ', 'Tang ', 'Que ', 'Zhong ', 'Li ', 'Peng ', 'Bang ', 'Sai ', 'Zang ', + 0x60 => 'Dui ', 'Tian ', 'Wu ', 'Cheng ', 'Xun ', 'Ge ', 'Zhen ', 'Ai ', 'Gong ', 'Yan ', 'Kan ', 'Tian ', 'Yuan ', 'Wen ', 'Xie ', 'Liu ', + 0x70 => 'Ama ', 'Lang ', 'Chang ', 'Peng ', 'Beng ', 'Chen ', 'Cu ', 'Lu ', 'Ou ', 'Qian ', 'Mei ', 'Mo ', 'Zhuan ', 'Shuang ', 'Shu ', 'Lou ', + 0x80 => 'Chi ', 'Man ', 'Biao ', 'Jing ', 'Qi ', 'Shu ', 'Di ', 'Zhang ', 'Kan ', 'Yong ', 'Dian ', 'Chen ', 'Zhi ', 'Xi ', 'Guo ', 'Qiang ', + 0x90 => 'Jin ', 'Di ', 'Shang ', 'Mu ', 'Cui ', 'Yan ', 'Ta ', 'Zeng ', 'Qi ', 'Qiang ', 'Liang ', null, 'Zhui ', 'Qiao ', 'Zeng ', 'Xu ', + 0xA0 => 'Shan ', 'Shan ', 'Ba ', 'Pu ', 'Kuai ', 'Dong ', 'Fan ', 'Que ', 'Mo ', 'Dun ', 'Dun ', 'Dun ', 'Di ', 'Sheng ', 'Duo ', 'Duo ', + 0xB0 => 'Tan ', 'Deng ', 'Wu ', 'Fen ', 'Huang ', 'Tan ', 'Da ', 'Ye ', 'Sho ', 'Mama ', 'Yu ', 'Qiang ', 'Ji ', 'Qiao ', 'Ken ', 'Yi ', + 0xC0 => 'Pi ', 'Bi ', 'Dian ', 'Jiang ', 'Ye ', 'Yong ', 'Bo ', 'Tan ', 'Lan ', 'Ju ', 'Huai ', 'Dang ', 'Rang ', 'Qian ', 'Xun ', 'Lan ', + 0xD0 => 'Xi ', 'He ', 'Ai ', 'Ya ', 'Dao ', 'Hao ', 'Ruan ', 'Mama ', 'Lei ', 'Kuang ', 'Lu ', 'Yan ', 'Tan ', 'Wei ', 'Huai ', 'Long ', + 0xE0 => 'Long ', 'Rui ', 'Li ', 'Lin ', 'Rang ', 'Ten ', 'Xun ', 'Yan ', 'Lei ', 'Ba ', null, 'Shi ', 'Ren ', null, 'Zhuang ', 'Zhuang ', + 0xF0 => 'Sheng ', 'Yi ', 'Mai ', 'Ke ', 'Zhu ', 'Zhuang ', 'Hu ', 'Hu ', 'Kun ', 'Yi ', 'Hu ', 'Xu ', 'Kun ', 'Shou ', 'Mang ', 'Zun ', +]; diff --git a/resources/transliteration-data/x59.php b/resources/transliteration-data/x59.php new file mode 100644 index 000000000..8b8051621 --- /dev/null +++ b/resources/transliteration-data/x59.php @@ -0,0 +1,20 @@ + 'Shou ', 'Yi ', 'Zhi ', 'Gu ', 'Chu ', 'Jiang ', 'Feng ', 'Bei ', 'Cay ', 'Bian ', 'Sui ', 'Qun ', 'Ling ', 'Fu ', 'Zuo ', 'Xia ', + 0x10 => 'Xiong ', null, 'Nao ', 'Xia ', 'Kui ', 'Xi ', 'Wai ', 'Yuan ', 'Mao ', 'Su ', 'Duo ', 'Duo ', 'Ye ', 'Qing ', 'Uys ', 'Gou ', + 0x20 => 'Gou ', 'Qi ', 'Meng ', 'Meng ', 'Yin ', 'Huo ', 'Chen ', 'Da ', 'Ze ', 'Tian ', 'Tai ', 'Fu ', 'Guai ', 'Yao ', 'Yang ', 'Hang ', + 0x30 => 'Gao ', 'Shi ', 'Ben ', 'Tai ', 'Tou ', 'Yan ', 'Bi ', 'Yi ', 'Kua ', 'Jia ', 'Duo ', 'Kwu ', 'Kuang ', 'Yun ', 'Jia ', 'Pa ', + 0x40 => 'En ', 'Lian ', 'Huan ', 'Di ', 'Yan ', 'Pao ', 'Quan ', 'Qi ', 'Nai ', 'Feng ', 'Xie ', 'Fen ', 'Dian ', null, 'Kui ', 'Zou ', + 0x50 => 'Huan ', 'Qi ', 'Kai ', 'Zha ', 'Ben ', 'Yi ', 'Jiang ', 'Tao ', 'Zang ', 'Ben ', 'Xi ', 'Xiang ', 'Fei ', 'Diao ', 'Xun ', 'Keng ', + 0x60 => 'Dian ', 'Ao ', 'She ', 'Weng ', 'Pan ', 'Ao ', 'Wu ', 'Ao ', 'Jiang ', 'Lian ', 'Duo ', 'Yun ', 'Jiang ', 'Shi ', 'Fen ', 'Huo ', + 0x70 => 'Bi ', 'Lian ', 'Duo ', 'Nu ', 'Nu ', 'Ding ', 'Nai ', 'Qian ', 'Jian ', 'Ta ', 'Jiu ', 'Nan ', 'Cha ', 'Hao ', 'Xian ', 'Fan ', + 0x80 => 'Ji ', 'Shuo ', 'Ru ', 'Fei ', 'Wang ', 'Hong ', 'Zhuang ', 'Fu ', 'Ma ', 'Dan ', 'Ren ', 'Fu ', 'Jing ', 'Yan ', 'Xie ', 'Wen ', + 0x90 => 'Zhong ', 'Pa ', 'Du ', 'Ji ', 'Keng ', 'Zhong ', 'Yao ', 'Jin ', 'Yun ', 'Miao ', 'Pei ', 'Shi ', 'Yue ', 'Zhuang ', 'Niu ', 'Yan ', + 0xA0 => 'Na ', 'Xin ', 'Fen ', 'Bi ', 'Yu ', 'Tuo ', 'Feng ', 'Yuan ', 'Fang ', 'Wu ', 'Yu ', 'Gui ', 'Du ', 'Ba ', 'Ni ', 'Zhou ', + 0xB0 => 'Zhuo ', 'Zhao ', 'Da ', 'Nai ', 'Yuan ', 'Tou ', 'Xuan ', 'Zhi ', 'E ', 'Mei ', 'Mo ', 'Qi ', 'Bi ', 'Shen ', 'Qie ', 'E ', + 0xC0 => 'He ', 'Xu ', 'Fa ', 'Zheng ', 'Min ', 'Ban ', 'Mu ', 'Fu ', 'Ling ', 'Zi ', 'Zi ', 'Shi ', 'Ran ', 'Shan ', 'Yang ', 'Man ', + 0xD0 => 'Jie ', 'Gu ', 'Si ', 'Xing ', 'Wei ', 'Zi ', 'Ju ', 'Shan ', 'Pin ', 'Ren ', 'Yao ', 'Tong ', 'Jiang ', 'Shu ', 'Ji ', 'Gai ', + 0xE0 => 'Shang ', 'Kuo ', 'Juan ', 'Jiao ', 'Gou ', 'Mu ', 'Jian ', 'Jian ', 'Yi ', 'Nian ', 'Zhi ', 'Ji ', 'Ji ', 'Xian ', 'Heng ', 'Guang ', + 0xF0 => 'Jun ', 'Kua ', 'Yan ', 'Ming ', 'Lie ', 'Pei ', 'Yan ', 'You ', 'Yan ', 'Cha ', 'Shen ', 'Yin ', 'Chi ', 'Gui ', 'Quan ', 'Zi ', +]; diff --git a/resources/transliteration-data/x5a.php b/resources/transliteration-data/x5a.php new file mode 100644 index 000000000..8e9950212 --- /dev/null +++ b/resources/transliteration-data/x5a.php @@ -0,0 +1,20 @@ + 'Song ', 'Wei ', 'Hong ', 'Wa ', 'Lou ', 'Ya ', 'Rao ', 'Jiao ', 'Luan ', 'Ping ', 'Xian ', 'Shao ', 'Li ', 'Cheng ', 'Xiao ', 'Mang ', + 0x10 => 'Fu ', 'Suo ', 'Wu ', 'Wei ', 'Ke ', 'Lai ', 'Chuo ', 'Ding ', 'Niang ', 'Xing ', 'Nan ', 'Yu ', 'Nuo ', 'Pei ', 'Nei ', 'Juan ', + 0x20 => 'Shen ', 'Zhi ', 'Han ', 'Di ', 'Zhuang ', 'E ', 'Pin ', 'Tui ', 'Han ', 'Mian ', 'Wu ', 'Yan ', 'Wu ', 'Xi ', 'Yan ', 'Yu ', + 0x30 => 'Si ', 'Yu ', 'Wa ', null, 'Xian ', 'Ju ', 'Qu ', 'Shui ', 'Qi ', 'Xian ', 'Zhui ', 'Dong ', 'Chang ', 'Lu ', 'Ai ', 'E ', + 0x40 => 'E ', 'Lou ', 'Mian ', 'Cong ', 'Pou ', 'Ju ', 'Po ', 'Cai ', 'Ding ', 'Wan ', 'Biao ', 'Xiao ', 'Shu ', 'Qi ', 'Hui ', 'Fu ', + 0x50 => 'E ', 'Wo ', 'Tan ', 'Fei ', 'Wei ', 'Jie ', 'Tian ', 'Ni ', 'Quan ', 'Jing ', 'Hun ', 'Jing ', 'Qian ', 'Dian ', 'Xing ', 'Hu ', + 0x60 => 'Wa ', 'Lai ', 'Bi ', 'Yin ', 'Chou ', 'Chuo ', 'Fu ', 'Jing ', 'Lun ', 'Yan ', 'Lan ', 'Kun ', 'Yin ', 'Ya ', 'Ju ', 'Li ', + 0x70 => 'Dian ', 'Xian ', 'Hwa ', 'Hua ', 'Ying ', 'Chan ', 'Shen ', 'Ting ', 'Dang ', 'Yao ', 'Wu ', 'Nan ', 'Ruo ', 'Jia ', 'Tou ', 'Xu ', + 0x80 => 'Yu ', 'Wei ', 'Ti ', 'Rou ', 'Mei ', 'Dan ', 'Ruan ', 'Qin ', 'Hui ', 'Wu ', 'Qian ', 'Chun ', 'Mao ', 'Fu ', 'Jie ', 'Duan ', + 0x90 => 'Xi ', 'Zhong ', 'Mei ', 'Huang ', 'Mian ', 'An ', 'Ying ', 'Xuan ', 'Jie ', 'Wei ', 'Mei ', 'Yuan ', 'Zhen ', 'Qiu ', 'Ti ', 'Xie ', + 0xA0 => 'Tuo ', 'Lian ', 'Mao ', 'Ran ', 'Si ', 'Pian ', 'Wei ', 'Wa ', 'Jiu ', 'Hu ', 'Ao ', null, 'Bou ', 'Xu ', 'Tou ', 'Gui ', + 0xB0 => 'Zou ', 'Yao ', 'Pi ', 'Xi ', 'Yuan ', 'Ying ', 'Rong ', 'Ru ', 'Chi ', 'Liu ', 'Mei ', 'Pan ', 'Ao ', 'Ma ', 'Gou ', 'Kui ', + 0xC0 => 'Qin ', 'Jia ', 'Sao ', 'Zhen ', 'Yuan ', 'Cha ', 'Yong ', 'Ming ', 'Ying ', 'Ji ', 'Su ', 'Niao ', 'Xian ', 'Tao ', 'Pang ', 'Lang ', + 0xD0 => 'Nao ', 'Bao ', 'Ai ', 'Pi ', 'Pin ', 'Yi ', 'Piao ', 'Yu ', 'Lei ', 'Xuan ', 'Man ', 'Yi ', 'Zhang ', 'Kang ', 'Yong ', 'Ni ', + 0xE0 => 'Li ', 'Di ', 'Gui ', 'Yan ', 'Jin ', 'Zhuan ', 'Chang ', 'Ce ', 'Han ', 'Nen ', 'Lao ', 'Mo ', 'Zhe ', 'Hu ', 'Hu ', 'Ao ', + 0xF0 => 'Nen ', 'Qiang ', 'Ma ', 'Pie ', 'Gu ', 'Wu ', 'Jiao ', 'Tuo ', 'Zhan ', 'Mao ', 'Xian ', 'Xian ', 'Mo ', 'Liao ', 'Lian ', 'Hua ', +]; diff --git a/resources/transliteration-data/x5b.php b/resources/transliteration-data/x5b.php new file mode 100644 index 000000000..c4620b1df --- /dev/null +++ b/resources/transliteration-data/x5b.php @@ -0,0 +1,20 @@ + 'Gui ', 'Deng ', 'Zhi ', 'Xu ', 'Yi ', 'Hua ', 'Xi ', 'Hui ', 'Rao ', 'Xi ', 'Yan ', 'Chan ', 'Jiao ', 'Mei ', 'Fan ', 'Fan ', + 0x10 => 'Xian ', 'Yi ', 'Wei ', 'Jiao ', 'Fu ', 'Shi ', 'Bi ', 'Shan ', 'Sui ', 'Qiang ', 'Lian ', 'Huan ', 'Xin ', 'Niao ', 'Dong ', 'Yi ', + 0x20 => 'Can ', 'Ai ', 'Niang ', 'Neng ', 'Ma ', 'Tiao ', 'Chou ', 'Jin ', 'Ci ', 'Yu ', 'Pin ', 'Yong ', 'Xu ', 'Nai ', 'Yan ', 'Tai ', + 0x30 => 'Ying ', 'Can ', 'Niao ', 'Wo ', 'Ying ', 'Mian ', 'Kaka ', 'Ma ', 'Shen ', 'Xing ', 'Ni ', 'Du ', 'Liu ', 'Yuan ', 'Lan ', 'Yan ', + 0x40 => 'Shuang ', 'Ling ', 'Jiao ', 'Niang ', 'Lan ', 'Xian ', 'Ying ', 'Shuang ', 'Shuai ', 'Quan ', 'Mi ', 'Li ', 'Luan ', 'Yan ', 'Zhu ', 'Lan ', + 0x50 => 'Zi ', 'Jie ', 'Jue ', 'Jue ', 'Kong ', 'Yun ', 'Zi ', 'Zi ', 'Cun ', 'Sun ', 'Fu ', 'Bei ', 'Zi ', 'Xiao ', 'Xin ', 'Meng ', + 0x60 => 'Si ', 'Tai ', 'Bao ', 'Ji ', 'Gu ', 'Nu ', 'Xue ', null, 'Zhuan ', 'Hai ', 'Luan ', 'Sun ', 'Huai ', 'Mie ', 'Cong ', 'Qian ', + 0x70 => 'Shu ', 'Chan ', 'Ya ', 'Zi ', 'Ni ', 'Fu ', 'Zi ', 'Li ', 'Xue ', 'Bo ', 'Ru ', 'Lai ', 'Nie ', 'Nie ', 'Ying ', 'Luan ', + 0x80 => 'Mian ', 'Ning ', 'Rong ', 'Ta ', 'Gui ', 'Zhai ', 'Qiong ', 'Yu ', 'Shou ', 'An ', 'Tu ', 'Song ', 'Wan ', 'Rou ', 'Yao ', 'Hong ', + 0x90 => 'Yi ', 'Jing ', 'Zhun ', 'Mi ', 'Zhu ', 'Dang ', 'Hong ', 'Zong ', 'Guan ', 'Zhou ', 'Ding ', 'Wan ', 'Yi ', 'Bao ', 'Shi ', 'Shi ', + 0xA0 => 'Chong ', 'Shen ', 'Ke ', 'Xuan ', 'Shi ', 'You ', 'Huan ', 'Yi ', 'Tiao ', 'Shi ', 'Xian ', 'Gong ', 'Cheng ', 'Qun ', 'Gong ', 'Xiao ', + 0xB0 => 'Zai ', 'Zha ', 'Bao ', 'Hai ', 'Yan ', 'Xiao ', 'Jia ', 'Shen ', 'Chen ', 'Rong ', 'Huang ', 'Mi ', 'Kou ', 'Kuan ', 'Bin ', 'Su ', + 0xC0 => 'Cai ', 'Zan ', 'Ji ', 'Yuan ', 'Ji ', 'Yin ', 'Mi ', 'Kou ', 'Qing ', 'Que ', 'Zhen ', 'Jian ', 'Fu ', 'Ning ', 'Bing ', 'Huan ', + 0xD0 => 'Mei ', 'Qin ', 'Han ', 'Yu ', 'Shi ', 'Ning ', 'Qin ', 'Ning ', 'Zhi ', 'Yu ', 'Bao ', 'Kuan ', 'Ning ', 'Qin ', 'Mo ', 'Cha ', + 0xE0 => 'Ju ', 'Gua ', 'Qin ', 'Hu ', 'Wu ', 'Liao ', 'Shi ', 'Zhu ', 'Zhai ', 'Shen ', 'Wei ', 'Xie ', 'Kuan ', 'Hui ', 'Liao ', 'Jun ', + 0xF0 => 'Huan ', 'Yi ', 'Yi ', 'Bao ', 'Qin ', 'Chong ', 'Bao ', 'Feng ', 'Cun ', 'Dui ', 'Si ', 'Xun ', 'Dao ', 'Lu ', 'Dui ', 'Shou ', +]; diff --git a/resources/transliteration-data/x5c.php b/resources/transliteration-data/x5c.php new file mode 100644 index 000000000..389a4dfa3 --- /dev/null +++ b/resources/transliteration-data/x5c.php @@ -0,0 +1,20 @@ + 'Po ', 'Feng ', 'Zhuan ', 'Fu ', 'She ', 'Ke ', 'Jiang ', 'Jiang ', 'Zhuan ', 'Wei ', 'Zun ', 'Xun ', 'Shu ', 'Dui ', 'Dao ', 'Xiao ', + 0x10 => 'Ji ', 'Shao ', 'Er ', 'Er ', 'Er ', 'Ga ', 'Jian ', 'Shu ', 'Chen ', 'Shang ', 'Shang ', 'Mo ', 'Ga ', 'Chang ', 'Liao ', 'Xian ', + 0x20 => 'Xian ', null, 'Wang ', 'Wang ', 'You ', 'Liao ', 'Liao ', 'Yao ', 'Mang ', 'Wang ', 'Wang ', 'Wang ', 'Ga ', 'Yao ', 'Duo ', 'Kui ', + 0x30 => 'Zhong ', 'Jiu ', 'Gan ', 'Gu ', 'Gan ', 'Tui ', 'Gan ', 'Gan ', 'Shi ', 'Yin ', 'Chi ', 'Kao ', 'Ni ', 'Jin ', 'Wei ', 'Niao ', + 0x40 => 'Ju ', 'Pi ', 'Ceng ', 'Xi ', 'Bi ', 'Ju ', 'Jie ', 'Tian ', 'Qu ', 'Ti ', 'Jie ', 'Wu ', 'Diao ', 'Shi ', 'Shi ', 'Ping ', + 0x50 => 'Ji ', 'Xie ', 'Chen ', 'Xi ', 'Ni ', 'Zhan ', 'Xi ', null, 'Man ', 'E ', 'Lou ', 'Ping ', 'Ti ', 'Fei ', 'Shu ', 'Xie ', + 0x60 => 'Tu ', 'Lu ', 'Lu ', 'Xi ', 'Ceng ', 'Lu ', 'Ju ', 'Xie ', 'Ju ', 'Jue ', 'Liao ', 'Jue ', 'Shu ', 'Xi ', 'Che ', 'Tun ', + 0x70 => 'Ni ', 'Shan ', null, 'Xian ', 'Li ', 'Xue ', 'Nata ', null, 'Long ', 'Yi ', 'Qi ', 'Ren ', 'Wu ', 'Han ', 'Shen ', 'Yu ', + 0x80 => 'Chu ', 'Sui ', 'Qi ', null, 'Yue ', 'Ban ', 'Yao ', 'Ang ', 'Ya ', 'Wu ', 'Jie ', 'E ', 'Ji ', 'Qian ', 'Fen ', 'Yuan ', + 0x90 => 'Qi ', 'Cen ', 'Qian ', 'Qi ', 'Cha ', 'Jie ', 'Qu ', 'Gang ', 'Xian ', 'Ao ', 'Lan ', 'Dao ', 'Ba ', 'Zuo ', 'Zuo ', 'Yang ', + 0xA0 => 'Ju ', 'Gang ', 'Ke ', 'Gou ', 'Xue ', 'Bei ', 'Li ', 'Tiao ', 'Ju ', 'Yan ', 'Fu ', 'Xiu ', 'Jia ', 'Ling ', 'Tuo ', 'Pei ', + 0xB0 => 'You ', 'Dai ', 'Kuang ', 'Yue ', 'Qu ', 'Hu ', 'Po ', 'Min ', 'An ', 'Tiao ', 'Ling ', 'Chi ', 'Yuri ', 'Dong ', 'Cem ', 'Kui ', + 0xC0 => 'Xiu ', 'Mao ', 'Tong ', 'Xue ', 'Yi ', 'Kura ', 'He ', 'Ke ', 'Luo ', 'E ', 'Fu ', 'Xun ', 'Die ', 'Lu ', 'An ', 'Er ', + 0xD0 => 'Gai ', 'Quan ', 'Tong ', 'Yi ', 'Mu ', 'Shi ', 'An ', 'Wei ', 'Hu ', 'Zhi ', 'Mi ', 'Li ', 'Ji ', 'Tong ', 'Wei ', 'You ', + 0xE0 => 'Sang ', 'Xia ', 'Li ', 'Yao ', 'Jiao ', 'Zheng ', 'Luan ', 'Jiao ', 'E ', 'E ', 'Yu ', 'Ye ', 'Bu ', 'Qiao ', 'Qun ', 'Feng ', + 0xF0 => 'Feng ', 'Nao ', 'Li ', 'You ', 'Xian ', 'Hong ', 'Dao ', 'Shen ', 'Cheng ', 'Tu ', 'Geng ', 'Jun ', 'Hao ', 'Xia ', 'Yin ', 'Yu ', +]; diff --git a/resources/transliteration-data/x5d.php b/resources/transliteration-data/x5d.php new file mode 100644 index 000000000..d66ec26bd --- /dev/null +++ b/resources/transliteration-data/x5d.php @@ -0,0 +1,20 @@ + 'Lang ', 'Kan ', 'Lao ', 'Lai ', 'Xian ', 'Que ', 'Kong ', 'Chong ', 'Chong ', 'Ta ', 'Lin ', 'Hua ', 'Ju ', 'Lai ', 'Qi ', 'Min ', + 0x10 => 'Kun ', 'Kun ', 'Zu ', 'Gu ', 'Cui ', 'Ya ', 'Ya ', 'Gang ', 'Lun ', 'Lun ', 'Leng ', 'Jue ', 'Duo ', 'Zheng ', 'Guo ', 'Yin ', + 0x20 => 'Dong ', 'Han ', 'Zheng ', 'Wei ', 'Yao ', 'Pi ', 'Yan ', 'Song ', 'Jie ', 'Beng ', 'Zu ', 'Jue ', 'Dong ', 'Zhan ', 'Gu ', 'Yin ', + 0x30 => null, 'Ze ', 'Huang ', 'Yu ', 'Wei ', 'Yang ', 'Feng ', 'Qiu ', 'Dun ', 'Ti ', 'Yi ', 'Zhi ', 'Shi ', 'Zai ', 'Yao ', 'E ', + 0x40 => 'Zhu ', 'Kan ', 'Lu ', 'Yan ', 'Mei ', 'Gan ', 'Ji ', 'Ji ', 'Huan ', 'Ting ', 'Sheng ', 'Mei ', 'Qian ', 'Wu ', 'Yu ', 'Zong ', + 0x50 => 'Lan ', 'Jue ', 'Yan ', 'Yan ', 'Wei ', 'Zong ', 'Cha ', 'Sui ', 'Rong ', 'Yamashina ', 'Qin ', 'Yu ', 'Kewashii ', 'Lou ', 'Tu ', 'Dui ', + 0x60 => 'Xi ', 'Weng ', 'Cang ', 'Dang ', 'Hong ', 'Jie ', 'Ai ', 'Liu ', 'Wu ', 'Song ', 'Qiao ', 'Zi ', 'Wei ', 'Beng ', 'Dian ', 'Cuo ', + 0x70 => 'Qian ', 'Yong ', 'Nie ', 'Cuo ', 'Ji ', null, 'Tao ', 'Song ', 'Zong ', 'Jiang ', 'Liao ', 'Kang ', 'Chan ', 'Die ', 'Cen ', 'Ding ', + 0x80 => 'Tu ', 'Lou ', 'Zhang ', 'Zhan ', 'Zhan ', 'Ao ', 'Cao ', 'Qu ', 'Qiang ', 'Zui ', 'Zui ', 'Dao ', 'Dao ', 'Xi ', 'Yu ', 'Bo ', + 0x90 => 'Long ', 'Xiang ', 'Ceng ', 'Bo ', 'Qin ', 'Jiao ', 'Yan ', 'Lao ', 'Zhan ', 'Lin ', 'Liao ', 'Liao ', 'Jin ', 'Deng ', 'Duo ', 'Zun ', + 0xA0 => 'Jiao ', 'Gui ', 'Yao ', 'Qiao ', 'Yao ', 'Jue ', 'Zhan ', 'Yi ', 'Xue ', 'Nao ', 'Ye ', 'Ye ', 'Yi ', 'E ', 'Xian ', 'Ji ', + 0xB0 => 'Xie ', 'Ke ', 'Xi ', 'Di ', 'Ao ', 'Zui ', null, 'Ni ', 'Rong ', 'Dao ', 'Ling ', 'Za ', 'Yu ', 'Yue ', 'Yin ', null, + 0xC0 => 'Jie ', 'Li ', 'Sui ', 'Long ', 'Long ', 'Dian ', 'Ying ', 'Xi ', 'Ju ', 'Chan ', 'Ying ', 'Kui ', 'Yan ', 'Wei ', 'Nao ', 'Quan ', + 0xD0 => 'Chao ', 'Cuan ', 'Luan ', 'Dian ', 'Dian ', null, 'Yan ', 'Yan ', 'Yan ', 'Nao ', 'Yan ', 'Chuan ', 'Gui ', 'Chuan ', 'Zhou ', 'Huang ', + 0xE0 => 'Jing ', 'Xun ', 'Chao ', 'Chao ', 'Lie ', 'Gong ', 'Zuo ', 'Qiao ', 'Ju ', 'Gong ', 'Kek ', 'Wu ', 'Pwu ', 'Pwu ', 'Chai ', 'Qiu ', + 0xF0 => 'Qiu ', 'Ji ', 'Yi ', 'Si ', 'Ba ', 'Zhi ', 'Zhao ', 'Xiang ', 'Yi ', 'Jin ', 'Xun ', 'Juan ', 'Phas ', 'Xun ', 'Jin ', 'Fu ', +]; diff --git a/resources/transliteration-data/x5e.php b/resources/transliteration-data/x5e.php new file mode 100644 index 000000000..2c2c92821 --- /dev/null +++ b/resources/transliteration-data/x5e.php @@ -0,0 +1,20 @@ + 'Za ', 'Bi ', 'Shi ', 'Bu ', 'Ding ', 'Shuai ', 'Fan ', 'Nie ', 'Shi ', 'Fen ', 'Pa ', 'Zhi ', 'Xi ', 'Hu ', 'Dan ', 'Wei ', + 0x10 => 'Zhang ', 'Tang ', 'Dai ', 'Ma ', 'Pei ', 'Pa ', 'Tie ', 'Fu ', 'Lian ', 'Zhi ', 'Zhou ', 'Bo ', 'Zhi ', 'Di ', 'Mo ', 'Yi ', + 0x20 => 'Yi ', 'Ping ', 'Qia ', 'Juan ', 'Ru ', 'Shuai ', 'Dai ', 'Zheng ', 'Shui ', 'Qiao ', 'Zhen ', 'Shi ', 'Qun ', 'Xi ', 'Bang ', 'Dai ', + 0x30 => 'Gui ', 'Chou ', 'Ping ', 'Zhang ', 'Sha ', 'Wan ', 'Dai ', 'Wei ', 'Chang ', 'Sha ', 'Qi ', 'Ze ', 'Guo ', 'Mao ', 'Du ', 'Hou ', + 0x40 => 'Zheng ', 'Xu ', 'Mi ', 'Wei ', 'Wo ', 'Fu ', 'Yi ', 'Bang ', 'Ping ', 'Tazuna ', 'Gong ', 'Pan ', 'Huang ', 'Dao ', 'Mi ', 'Jia ', + 0x50 => 'Teng ', 'Hui ', 'Zhong ', 'Shan ', 'Man ', 'Mu ', 'Biao ', 'Guo ', 'Ze ', 'Mu ', 'Bang ', 'Zhang ', 'Jiong ', 'Chan ', 'Fu ', 'Zhi ', + 0x60 => 'Hu ', 'Fan ', 'Chuang ', 'Bi ', 'Hei ', null, 'Mi ', 'Qiao ', 'Chan ', 'Fen ', 'Meng ', 'Bang ', 'Chou ', 'Mie ', 'Chu ', 'Jie ', + 0x70 => 'Xian ', 'Lan ', 'Gan ', 'Ping ', 'Nian ', 'Qian ', 'Bing ', 'Bing ', 'Xing ', 'Gan ', 'Yao ', 'Huan ', 'You ', 'You ', 'Ji ', 'Guang ', + 0x80 => 'Pi ', 'Ting ', 'Ze ', 'Guang ', 'Zhuang ', 'Mo ', 'Qing ', 'Bi ', 'Qin ', 'Dun ', 'Chuang ', 'Gui ', 'Ya ', 'Bai ', 'Jie ', 'Xu ', + 0x90 => 'Lu ', 'Wu ', null, 'Ku ', 'Ying ', 'Di ', 'Pao ', 'Dian ', 'Ya ', 'Miao ', 'Geng ', 'Ci ', 'Fu ', 'Tong ', 'Pang ', 'Fei ', + 0xA0 => 'Xiang ', 'Yi ', 'Zhi ', 'Tiao ', 'Zhi ', 'Xiu ', 'Du ', 'Zuo ', 'Xiao ', 'Tu ', 'Gui ', 'Ku ', 'Pang ', 'Ting ', 'You ', 'Bu ', + 0xB0 => 'Ding ', 'Cheng ', 'Lai ', 'Bei ', 'Ji ', 'An ', 'Shu ', 'Kang ', 'Yong ', 'Tuo ', 'Song ', 'Shu ', 'Qing ', 'Yu ', 'Yu ', 'Miao ', + 0xC0 => 'Sou ', 'Ce ', 'Xiang ', 'Fei ', 'Jiu ', 'He ', 'Hui ', 'Liu ', 'Sha ', 'Lian ', 'Lang ', 'Sou ', 'Jian ', 'Pou ', 'Qing ', 'Jiu ', + 0xD0 => 'Jiu ', 'Qin ', 'Ao ', 'Kuo ', 'Lou ', 'Yin ', 'Liao ', 'Dai ', 'Lu ', 'Yi ', 'Chu ', 'Chan ', 'Tu ', 'Si ', 'Xin ', 'Miao ', + 0xE0 => 'Chang ', 'Wu ', 'Fei ', 'Guang ', 'Koc ', 'Kuai ', 'Bi ', 'Qiang ', 'Xie ', 'Lin ', 'Lin ', 'Liao ', 'Lu ', null, 'Ying ', 'Xian ', + 0xF0 => 'Ting ', 'Yong ', 'Li ', 'Ting ', 'Yin ', 'Xun ', 'Yan ', 'Ting ', 'Di ', 'Po ', 'Jian ', 'Hui ', 'Nai ', 'Hui ', 'Gong ', 'Nian ', +]; diff --git a/resources/transliteration-data/x5f.php b/resources/transliteration-data/x5f.php new file mode 100644 index 000000000..05e351067 --- /dev/null +++ b/resources/transliteration-data/x5f.php @@ -0,0 +1,20 @@ + 'Kai ', 'Bian ', 'Yi ', 'Qi ', 'Nong ', 'Fen ', 'Ju ', 'Yan ', 'Yi ', 'Zang ', 'Bi ', 'Yi ', 'Yi ', 'Er ', 'San ', 'Shi ', + 0x10 => 'Er ', 'Shi ', 'Shi ', 'Gong ', 'Diao ', 'Yin ', 'Hu ', 'Fu ', 'Hong ', 'Wu ', 'Tui ', 'Chi ', 'Jiang ', 'Ba ', 'Shen ', 'Di ', + 0x20 => 'Zhang ', 'Jue ', 'Tao ', 'Fu ', 'Di ', 'Mi ', 'Xian ', 'Hu ', 'Chao ', 'Nu ', 'Jing ', 'Zhen ', 'Yi ', 'Mi ', 'Quan ', 'Wan ', + 0x30 => 'Shao ', 'Ruo ', 'Xuan ', 'Jing ', 'Dun ', 'Zhang ', 'Jiang ', 'Qiang ', 'Peng ', 'Dan ', 'Qiang ', 'Bi ', 'Bi ', 'She ', 'Dan ', 'Jian ', + 0x40 => 'Gou ', 'Sei ', 'Fa ', 'Bi ', 'Kou ', 'Nagi ', 'Bie ', 'Xiao ', 'Dan ', 'Kuo ', 'Qiang ', 'Hong ', 'Mi ', 'Kuo ', 'Wan ', 'Jue ', + 0x50 => 'Ji ', 'Ji ', 'Gui ', 'Dang ', 'Lu ', 'Lu ', 'Tuan ', 'Hui ', 'Zhi ', 'Hui ', 'Hui ', 'Yi ', 'Yi ', 'Yi ', 'Yi ', 'Huo ', + 0x60 => 'Huo ', 'Shan ', 'Xing ', 'Wen ', 'Tong ', 'Yan ', 'Yan ', 'Yu ', 'Chi ', 'Cai ', 'Biao ', 'Diao ', 'Bin ', 'Peng ', 'Yong ', 'Piao ', + 0x70 => 'Zhang ', 'Ying ', 'Chi ', 'Chi ', 'Zhuo ', 'Tuo ', 'Ji ', 'Pang ', 'Zhong ', 'Yi ', 'Wang ', 'Che ', 'Bi ', 'Chi ', 'Ling ', 'Fu ', + 0x80 => 'Wang ', 'Zheng ', 'Cu ', 'Wang ', 'Jing ', 'Dai ', 'Xi ', 'Xun ', 'Hen ', 'Yang ', 'Huai ', 'Lu ', 'Hou ', 'Wa ', 'Cheng ', 'Zhi ', + 0x90 => 'Xu ', 'Jing ', 'Tu ', 'Cong ', null, 'Lai ', 'Cong ', 'De ', 'Pai ', 'Xi ', null, 'Qi ', 'Chang ', 'Zhi ', 'Cong ', 'Zhou ', + 0xA0 => 'Lai ', 'Yu ', 'Xie ', 'Jie ', 'Jian ', 'Chi ', 'Jia ', 'Bian ', 'Huang ', 'Fu ', 'Xun ', 'Wei ', 'Pang ', 'Yao ', 'Wei ', 'Xi ', + 0xB0 => 'Zheng ', 'Piao ', 'Chi ', 'De ', 'Zheng ', 'Zheng ', 'Bie ', 'De ', 'Chong ', 'Che ', 'Jiao ', 'Wei ', 'Jiao ', 'Hui ', 'Mei ', 'Long ', + 0xC0 => 'Xiang ', 'Bao ', 'Qu ', 'Xin ', 'Shu ', 'Bi ', 'Yi ', 'Le ', 'Ren ', 'Dao ', 'Ding ', 'Gai ', 'Ji ', 'Ren ', 'Ren ', 'Chan ', + 0xD0 => 'Tan ', 'Te ', 'Te ', 'Gan ', 'Qi ', 'Shi ', 'Cun ', 'Zhi ', 'Wang ', 'Mang ', 'Xi ', 'Fan ', 'Ying ', 'Tian ', 'Min ', 'Min ', + 0xE0 => 'Zhong ', 'Chong ', 'Wu ', 'Ji ', 'Wu ', 'Xi ', 'Ye ', 'You ', 'Wan ', 'Cong ', 'Zhong ', 'Kuai ', 'Yu ', 'Bian ', 'Zhi ', 'Qi ', + 0xF0 => 'Cui ', 'Chen ', 'Tai ', 'Tun ', 'Qian ', 'Nian ', 'Hun ', 'Xiong ', 'Niu ', 'Wang ', 'Xian ', 'Xin ', 'Kang ', 'Hu ', 'Kai ', 'Fen ', +]; diff --git a/resources/transliteration-data/x60.php b/resources/transliteration-data/x60.php new file mode 100644 index 000000000..eda7ec199 --- /dev/null +++ b/resources/transliteration-data/x60.php @@ -0,0 +1,20 @@ + 'Huai ', 'Tai ', 'Song ', 'Wu ', 'Ou ', 'Chang ', 'Chuang ', 'Ju ', 'Yi ', 'Bao ', 'Chao ', 'Min ', 'Pei ', 'Zuo ', 'Zen ', 'Yang ', + 0x10 => 'Kou ', 'Ban ', 'Nu ', 'Nao ', 'Zheng ', 'Pa ', 'Bu ', 'Tie ', 'Gu ', 'Hu ', 'Ju ', 'Da ', 'Lian ', 'Si ', 'Chou ', 'Di ', + 0x20 => 'Dai ', 'Yi ', 'Tu ', 'You ', 'Fu ', 'Ji ', 'Peng ', 'Xing ', 'Yuan ', 'Ni ', 'Guai ', 'Fu ', 'Xi ', 'Bi ', 'You ', 'Qie ', + 0x30 => 'Xuan ', 'Cong ', 'Bing ', 'Huang ', 'Xu ', 'Chu ', 'Pi ', 'Xi ', 'Xi ', 'Tan ', 'Koraeru ', 'Zong ', 'Dui ', null, 'Ki ', 'Yi ', + 0x40 => 'Chi ', 'Ren ', 'Xun ', 'Shi ', 'Xi ', 'Lao ', 'Heng ', 'Kuang ', 'Mu ', 'Zhi ', 'Xie ', 'Lian ', 'Tiao ', 'Huang ', 'Die ', 'Hao ', + 0x50 => 'Kong ', 'Gui ', 'Heng ', 'Xi ', 'Xiao ', 'Shu ', 'S ', 'Kua ', 'Qiu ', 'Yang ', 'Hui ', 'Hui ', 'Chi ', 'Jia ', 'Yi ', 'Xiong ', + 0x60 => 'Guai ', 'Lin ', 'Hui ', 'Zi ', 'Xu ', 'Chi ', 'Xiang ', 'Nu ', 'Hen ', 'En ', 'Ke ', 'Tong ', 'Tian ', 'Gong ', 'Quan ', 'Xi ', + 0x70 => 'Qia ', 'Yue ', 'Peng ', 'Ken ', 'De ', 'Hui ', 'E ', 'Kyuu ', 'Tong ', 'Yan ', 'Kai ', 'Ce ', 'Nao ', 'Yun ', 'Mang ', 'Yong ', + 0x80 => 'Yong ', 'Yuan ', 'Pi ', 'Kun ', 'Qiao ', 'Yue ', 'Yu ', 'Yu ', 'Jie ', 'Xi ', 'Zhe ', 'Lin ', 'Ti ', 'Han ', 'Hao ', 'Qie ', + 0x90 => 'Ti ', 'Bu ', 'Yi ', 'Qian ', 'Hui ', 'Xi ', 'Bei ', 'Man ', 'Yi ', 'Heng ', 'Song ', 'Quan ', 'Cheng ', 'Hui ', 'Wu ', 'Wu ', + 0xA0 => 'You ', 'Li ', 'Liang ', 'Huan ', 'Cong ', 'Yi ', 'Yue ', 'Li ', 'Nin ', 'Nao ', 'E ', 'Que ', 'Xuan ', 'Qian ', 'Wu ', 'Min ', + 0xB0 => 'Cong ', 'Fei ', 'Bei ', 'Duo ', 'Cui ', 'Chang ', 'Men ', 'Li ', 'Ji ', 'Guan ', 'Guan ', 'Xing ', 'Dao ', 'Qi ', 'Kong ', 'Tian ', + 0xC0 => 'Lun ', 'Xi ', 'Kan ', 'Kun ', 'Ni ', 'Qing ', 'Chou ', 'Dun ', 'Guo ', 'Chan ', 'Liang ', 'Wan ', 'Yuan ', 'Jin ', 'Ji ', 'Lin ', + 0xD0 => 'Yu ', 'Huo ', 'He ', 'Quan ', 'Tan ', 'Ti ', 'Ti ', 'Nie ', 'Wang ', 'Chuo ', 'Bu ', 'Hun ', 'Xi ', 'Tang ', 'Xin ', 'Wei ', + 0xE0 => 'Hui ', 'E ', 'Rui ', 'Zong ', 'Jian ', 'Yong ', 'Dian ', 'Ju ', 'Can ', 'Cheng ', 'De ', 'Bei ', 'Qie ', 'Can ', 'Dan ', 'Guan ', + 0xF0 => 'Duo ', 'Nao ', 'Yun ', 'Xiang ', 'Zhui ', 'Die ', 'Huang ', 'Chun ', 'Qiong ', 'Re ', 'Xing ', 'Ce ', 'Bian ', 'Hun ', 'Zong ', 'Ti ', +]; diff --git a/resources/transliteration-data/x61.php b/resources/transliteration-data/x61.php new file mode 100644 index 000000000..57089c4ae --- /dev/null +++ b/resources/transliteration-data/x61.php @@ -0,0 +1,20 @@ + 'Qiao ', 'Chou ', 'Bei ', 'Xuan ', 'Wei ', 'Ge ', 'Qian ', 'Wei ', 'Yu ', 'Yu ', 'Bi ', 'Xuan ', 'Huan ', 'Min ', 'Bi ', 'Yi ', + 0x10 => 'Mian ', 'Yong ', 'Kai ', 'Dang ', 'Yin ', 'E ', 'Chen ', 'Mou ', 'Ke ', 'Ke ', 'Yu ', 'Ai ', 'Qie ', 'Yan ', 'Nuo ', 'Gan ', + 0x20 => 'Yun ', 'Zong ', 'Sai ', 'Leng ', 'Fen ', null, 'Kui ', 'Kui ', 'Que ', 'Gong ', 'Yun ', 'Su ', 'Su ', 'Qi ', 'Yao ', 'Song ', + 0x30 => 'Huang ', 'Ji ', 'Gu ', 'Ju ', 'Chuang ', 'Ni ', 'Xie ', 'Kai ', 'Zheng ', 'Yong ', 'Cao ', 'Sun ', 'Shen ', 'Bo ', 'Kai ', 'Yuan ', + 0x40 => 'Xie ', 'Hun ', 'Yong ', 'Yang ', 'Li ', 'Sao ', 'Tao ', 'Yin ', 'Ci ', 'Xu ', 'Qian ', 'Tai ', 'Huang ', 'Yun ', 'Shen ', 'Ming ', + 0x50 => null, 'She ', 'Cong ', 'Piao ', 'Mo ', 'Mu ', 'Guo ', 'Chi ', 'Can ', 'Can ', 'Can ', 'Cui ', 'Min ', 'Te ', 'Zhang ', 'Tong ', + 0x60 => 'Ao ', 'Shuang ', 'Man ', 'Guan ', 'Que ', 'Zao ', 'Jiu ', 'Hui ', 'Kai ', 'Lian ', 'Ou ', 'Song ', 'Jin ', 'Yin ', 'Lu ', 'Shang ', + 0x70 => 'Wei ', 'Tuan ', 'Man ', 'Qian ', 'She ', 'Yong ', 'Qing ', 'Kang ', 'Di ', 'Zhi ', 'Lou ', 'Juan ', 'Qi ', 'Qi ', 'Yu ', 'Ping ', + 0x80 => 'Liao ', 'Cong ', 'You ', 'Chong ', 'Zhi ', 'Tong ', 'Cheng ', 'Qi ', 'Qu ', 'Peng ', 'Bei ', 'Bie ', 'Chun ', 'Jiao ', 'Zeng ', 'Chi ', + 0x90 => 'Lian ', 'Ping ', 'Kui ', 'Hui ', 'Qiao ', 'Cheng ', 'Yin ', 'Yin ', 'Xi ', 'Xi ', 'Dan ', 'Tan ', 'Duo ', 'Dui ', 'Dui ', 'Su ', + 0xA0 => 'Jue ', 'Ce ', 'Xiao ', 'Fan ', 'Fen ', 'Lao ', 'Lao ', 'Chong ', 'Han ', 'Qi ', 'Xian ', 'Min ', 'Jing ', 'Liao ', 'Wu ', 'Can ', + 0xB0 => 'Jue ', 'Cu ', 'Xian ', 'Tan ', 'Sheng ', 'Pi ', 'Yi ', 'Chu ', 'Xian ', 'Nao ', 'Dan ', 'Tan ', 'Jing ', 'Song ', 'Han ', 'Jiao ', + 0xC0 => 'Wai ', 'Huan ', 'Dong ', 'Qin ', 'Qin ', 'Qu ', 'Cao ', 'Ken ', 'Xie ', 'Ying ', 'Ao ', 'Mao ', 'Yi ', 'Lin ', 'Se ', 'Jun ', + 0xD0 => 'Huai ', 'Men ', 'Lan ', 'Ai ', 'Lin ', 'Yan ', 'Gua ', 'Xia ', 'Chi ', 'Yu ', 'Yin ', 'Dai ', 'Meng ', 'Ai ', 'Meng ', 'Dui ', + 0xE0 => 'Qi ', 'Mo ', 'Lan ', 'Men ', 'Chou ', 'Zhi ', 'Nuo ', 'Nuo ', 'Yan ', 'Yang ', 'Bo ', 'Zhi ', 'Kuang ', 'Kuang ', 'You ', 'Fu ', + 0xF0 => 'Liu ', 'Mie ', 'Cheng ', null, 'Chan ', 'Meng ', 'Lan ', 'Huai ', 'Xuan ', 'Rang ', 'Chan ', 'Ji ', 'Ju ', 'Huan ', 'She ', 'Yi ', +]; diff --git a/resources/transliteration-data/x62.php b/resources/transliteration-data/x62.php new file mode 100644 index 000000000..b074918c8 --- /dev/null +++ b/resources/transliteration-data/x62.php @@ -0,0 +1,20 @@ + 'Lian ', 'Nan ', 'Mi ', 'Tang ', 'Jue ', 'Gang ', 'Gang ', 'Gang ', 'Ge ', 'Yue ', 'Wu ', 'Jian ', 'Xu ', 'Shu ', 'Rong ', 'Xi ', + 0x10 => 'Cheng ', 'Wo ', 'Jie ', 'Ge ', 'Jian ', 'Qiang ', 'Huo ', 'Qiang ', 'Zhan ', 'Dong ', 'Qi ', 'Jia ', 'Die ', 'Zei ', 'Jia ', 'Ji ', + 0x20 => 'Shi ', 'Kan ', 'Ji ', 'Kui ', 'Gai ', 'Deng ', 'Zhan ', 'Chuang ', 'Ge ', 'Jian ', 'Jie ', 'Yu ', 'Jian ', 'Yan ', 'Lu ', 'Xi ', + 0x30 => 'Zhan ', 'Xi ', 'Xi ', 'Chuo ', 'Dai ', 'Qu ', 'Hu ', 'Hu ', 'Hu ', 'E ', 'Shi ', 'Li ', 'Mao ', 'Hu ', 'Li ', 'Fang ', + 0x40 => 'Suo ', 'Bian ', 'Dian ', 'Jiong ', 'Shang ', 'Yi ', 'Yi ', 'Shan ', 'Hu ', 'Fei ', 'Yan ', 'Shou ', 'T ', 'Cai ', 'Zha ', 'Qiu ', + 0x50 => 'Le ', 'Bu ', 'Ba ', 'Da ', 'Reng ', 'Fu ', 'Hameru ', 'Zai ', 'Tuo ', 'Zhang ', 'Diao ', 'Kang ', 'Yu ', 'Ku ', 'Han ', 'Shen ', + 0x60 => 'Cha ', 'Yi ', 'Gu ', 'Kou ', 'Wu ', 'Tuo ', 'Qian ', 'Zhi ', 'Ren ', 'Kuo ', 'Men ', 'Sao ', 'Yang ', 'Niu ', 'Ban ', 'Che ', + 0x70 => 'Rao ', 'Xi ', 'Qian ', 'Ban ', 'Jia ', 'Yu ', 'Fu ', 'Ao ', 'Xi ', 'Pi ', 'Zhi ', 'Zi ', 'E ', 'Dun ', 'Zhao ', 'Cheng ', + 0x80 => 'Ji ', 'Yan ', 'Kuang ', 'Bian ', 'Chao ', 'Ju ', 'Wen ', 'Hu ', 'Yue ', 'Jue ', 'Ba ', 'Qin ', 'Zhen ', 'Zheng ', 'Yun ', 'Wan ', + 0x90 => 'Nu ', 'Yi ', 'Shu ', 'Zhua ', 'Pou ', 'Tou ', 'Dou ', 'Kang ', 'Zhe ', 'Pou ', 'Fu ', 'Pao ', 'Ba ', 'Ao ', 'Ze ', 'Tuan ', + 0xA0 => 'Kou ', 'Lun ', 'Qiang ', null, 'Hu ', 'Bao ', 'Bing ', 'Zhi ', 'Peng ', 'Tan ', 'Pu ', 'Pi ', 'Tai ', 'Yao ', 'Zhen ', 'Zha ', + 0xB0 => 'Yang ', 'Bao ', 'He ', 'Ni ', 'Yi ', 'Di ', 'Chi ', 'Pi ', 'Za ', 'Mo ', 'Mo ', 'Shen ', 'Ya ', 'Chou ', 'Qu ', 'Min ', + 0xC0 => 'Chu ', 'Jia ', 'Fu ', 'Zhan ', 'Zhu ', 'Dan ', 'Chai ', 'Mu ', 'Nian ', 'La ', 'Fu ', 'Pao ', 'Ban ', 'Pai ', 'Ling ', 'Na ', + 0xD0 => 'Guai ', 'Qian ', 'Ju ', 'Tuo ', 'Ba ', 'Tuo ', 'Tuo ', 'Ao ', 'Ju ', 'Zhuo ', 'Pan ', 'Zhao ', 'Bai ', 'Bai ', 'Di ', 'Ni ', + 0xE0 => 'Ju ', 'Kuo ', 'Long ', 'Jian ', null, 'Yong ', 'Lan ', 'Ning ', 'Bo ', 'Ze ', 'Qian ', 'Hen ', 'Gua ', 'Shi ', 'Jie ', 'Zheng ', + 0xF0 => 'Nin ', 'Gong ', 'Gong ', 'Quan ', 'Shuan ', 'Cun ', 'Zan ', 'Kao ', 'Chi ', 'Xie ', 'Ce ', 'Hui ', 'Pin ', 'Zhuai ', 'Shi ', 'Na ', +]; diff --git a/resources/transliteration-data/x63.php b/resources/transliteration-data/x63.php new file mode 100644 index 000000000..e5b73808d --- /dev/null +++ b/resources/transliteration-data/x63.php @@ -0,0 +1,20 @@ + 'Bo ', 'Chi ', 'Gua ', 'Zhi ', 'Kuo ', 'Duo ', 'Duo ', 'Zhi ', 'Qie ', 'An ', 'Nong ', 'Zhen ', 'Ge ', 'Jiao ', 'Ku ', 'Dong ', + 0x10 => 'Ru ', 'Tiao ', 'Lie ', 'Zha ', 'Lu ', 'Die ', 'Wa ', 'Jue ', 'Mushiru ', 'Ju ', 'Zhi ', 'Luan ', 'Ya ', 'Zhua ', 'Ta ', 'Xie ', + 0x20 => 'Nao ', 'Dang ', 'Jiao ', 'Zheng ', 'Ji ', 'Hui ', 'Xun ', 'Ku ', 'Ai ', 'Tuo ', 'Nuo ', 'Cuo ', 'Bo ', 'Geng ', 'Ti ', 'Zhen ', + 0x30 => 'Cheng ', 'Suo ', 'Suo ', 'Keng ', 'Mei ', 'Long ', 'Ju ', 'Peng ', 'Jian ', 'Yi ', 'Ting ', 'Shan ', 'Nuo ', 'Wan ', 'Xie ', 'Cha ', + 0x40 => 'Feng ', 'Jiao ', 'Wu ', 'Jun ', 'Jiu ', 'Tong ', 'Kun ', 'Huo ', 'Tu ', 'Zhuo ', 'Pou ', 'Le ', 'Ba ', 'Han ', 'Shao ', 'Nie ', + 0x50 => 'Juan ', 'Ze ', 'Song ', 'Ye ', 'Jue ', 'Bu ', 'Huan ', 'Bu ', 'Zun ', 'Yi ', 'Zhai ', 'Lu ', 'Sou ', 'Tuo ', 'Lao ', 'Sun ', + 0x60 => 'Bang ', 'Jian ', 'Huan ', 'Dao ', null, 'Wan ', 'Qin ', 'Peng ', 'She ', 'Lie ', 'Min ', 'Men ', 'Fu ', 'Bai ', 'Ju ', 'Dao ', + 0x70 => 'Wo ', 'Ai ', 'Juan ', 'Yue ', 'Zong ', 'Chen ', 'Chui ', 'Jie ', 'Tu ', 'Ben ', 'Na ', 'Nian ', 'Nuo ', 'Zu ', 'Wo ', 'Xi ', + 0x80 => 'Xian ', 'Cheng ', 'Dian ', 'Sao ', 'Lun ', 'Qing ', 'Gang ', 'Duo ', 'Shou ', 'Diao ', 'Pou ', 'Di ', 'Zhang ', 'Gun ', 'Ji ', 'Tao ', + 0x90 => 'Qia ', 'Qi ', 'Pai ', 'Shu ', 'Qian ', 'Ling ', 'Yi ', 'Ya ', 'Jue ', 'Zheng ', 'Liang ', 'Gua ', 'Yi ', 'Huo ', 'Shan ', 'Zheng ', + 0xA0 => 'Lue ', 'Cai ', 'Tan ', 'Che ', 'Bing ', 'Jie ', 'Ti ', 'Kong ', 'Tui ', 'Yan ', 'Cuo ', 'Zou ', 'Ju ', 'Tian ', 'Qian ', 'Ken ', + 0xB0 => 'Bai ', 'Shou ', 'Jie ', 'Lu ', 'Guo ', 'Haba ', null, 'Zhi ', 'Dan ', 'Mang ', 'Xian ', 'Sao ', 'Guan ', 'Peng ', 'Yuan ', 'Nuo ', + 0xC0 => 'Jian ', 'Zhen ', 'Jiu ', 'Jian ', 'Yu ', 'Yan ', 'Kui ', 'Nan ', 'Hong ', 'Rou ', 'Pi ', 'Wei ', 'Sai ', 'Zou ', 'Xuan ', 'Miao ', + 0xD0 => 'Ti ', 'Nie ', 'Cha ', 'Shi ', 'Zong ', 'Zhen ', 'Yi ', 'Shun ', 'Heng ', 'Bian ', 'Yang ', 'Huan ', 'Yan ', 'Zuan ', 'An ', 'Xu ', + 0xE0 => 'Ya ', 'Wo ', 'Ke ', 'Chuai ', 'Ji ', 'Ti ', 'La ', 'La ', 'Cheng ', 'Kai ', 'Jiu ', 'Jiu ', 'Tu ', 'Jie ', 'Hui ', 'Geng ', + 0xF0 => 'Chong ', 'Shuo ', 'She ', 'Xie ', 'Yuan ', 'Qian ', 'Ye ', 'Cha ', 'Zha ', 'Bei ', 'Yao ', null, null, 'Lan ', 'Wen ', 'Qin ', +]; diff --git a/resources/transliteration-data/x64.php b/resources/transliteration-data/x64.php new file mode 100644 index 000000000..ade5a8e4c --- /dev/null +++ b/resources/transliteration-data/x64.php @@ -0,0 +1,20 @@ + 'Chan ', 'Ge ', 'Lou ', 'Zong ', 'Geng ', 'Jiao ', 'Gou ', 'Qin ', 'Yong ', 'Que ', 'Chou ', 'Chi ', 'Zhan ', 'Sun ', 'Sun ', 'Bo ', + 0x10 => 'Chu ', 'Rong ', 'Beng ', 'Cuo ', 'Sao ', 'Ke ', 'Yao ', 'Dao ', 'Zhi ', 'Nu ', 'Xie ', 'Jian ', 'Sou ', 'Qiu ', 'Gao ', 'Xian ', + 0x20 => 'Shuo ', 'Sang ', 'Jin ', 'Mie ', 'E ', 'Chui ', 'Nuo ', 'Shan ', 'Ta ', 'Jie ', 'Tang ', 'Pan ', 'Ban ', 'Da ', 'Li ', 'Tao ', + 0x30 => 'Hu ', 'Zhi ', 'Wa ', 'Xia ', 'Qian ', 'Wen ', 'Qiang ', 'Tian ', 'Zhen ', 'E ', 'Xi ', 'Nuo ', 'Quan ', 'Cha ', 'Zha ', 'Ge ', + 0x40 => 'Wu ', 'En ', 'She ', 'Kang ', 'She ', 'Shu ', 'Bai ', 'Yao ', 'Bin ', 'Sou ', 'Tan ', 'Sa ', 'Chan ', 'Suo ', 'Liao ', 'Chong ', + 0x50 => 'Chuang ', 'Guo ', 'Bing ', 'Feng ', 'Shuai ', 'Di ', 'Qi ', 'Sou ', 'Zhai ', 'Lian ', 'Tang ', 'Chi ', 'Guan ', 'Lu ', 'Luo ', 'Lou ', + 0x60 => 'Zong ', 'Gai ', 'Hu ', 'Zha ', 'Chuang ', 'Tang ', 'Hua ', 'Cui ', 'Nai ', 'Mo ', 'Jiang ', 'Gui ', 'Ying ', 'Zhi ', 'Ao ', 'Zhi ', + 0x70 => 'Nie ', 'Man ', 'Shan ', 'Kou ', 'Shu ', 'Suo ', 'Tuan ', 'Jiao ', 'Mo ', 'Mo ', 'Zhe ', 'Xian ', 'Keng ', 'Piao ', 'Jiang ', 'Yin ', + 0x80 => 'Gou ', 'Qian ', 'Lue ', 'Ji ', 'Ying ', 'Jue ', 'Pie ', 'Pie ', 'Lao ', 'Dun ', 'Xian ', 'Ruan ', 'Kui ', 'Zan ', 'Yi ', 'Xun ', + 0x90 => 'Cheng ', 'Cheng ', 'Sa ', 'Nao ', 'Heng ', 'Si ', 'Qian ', 'Huang ', 'Da ', 'Zun ', 'Nian ', 'Lin ', 'Zheng ', 'Hui ', 'Zhuang ', 'Jiao ', + 0xA0 => 'Ji ', 'Cao ', 'Dan ', 'Dan ', 'Che ', 'Bo ', 'Che ', 'Jue ', 'Xiao ', 'Liao ', 'Ben ', 'Fu ', 'Qiao ', 'Bo ', 'Cuo ', 'Zhuo ', + 0xB0 => 'Zhuan ', 'Tuo ', 'Pu ', 'Qin ', 'Dun ', 'Nian ', null, 'Xie ', 'Lu ', 'Jiao ', 'Cuan ', 'Ta ', 'Han ', 'Qiao ', 'Zhua ', 'Jian ', + 0xC0 => 'Gan ', 'Yong ', 'Lei ', 'Kuo ', 'Lu ', 'Shan ', 'Zhuo ', 'Ze ', 'Pu ', 'Chuo ', 'Ji ', 'Dang ', 'Suo ', 'Cao ', 'Qing ', 'Jing ', + 0xD0 => 'Huan ', 'Jie ', 'Qin ', 'Kuai ', 'Dan ', 'Xi ', 'Ge ', 'Pi ', 'Bo ', 'Ao ', 'Ju ', 'Ye ', null, 'Mang ', 'Sou ', 'Mi ', + 0xE0 => 'Ji ', 'Tai ', 'Zhuo ', 'Dao ', 'Xing ', 'Lan ', 'Ca ', 'Ju ', 'Ye ', 'Ru ', 'Ye ', 'Ye ', 'Ni ', 'Hu ', 'Ji ', 'Bin ', + 0xF0 => 'Ning ', 'Ge ', 'Zhi ', 'Jie ', 'Kuo ', 'Mo ', 'Jian ', 'Xie ', 'Lie ', 'Tan ', 'Bai ', 'Sou ', 'Lu ', 'Lue ', 'Rao ', 'Zhi ', +]; diff --git a/resources/transliteration-data/x65.php b/resources/transliteration-data/x65.php new file mode 100644 index 000000000..23fb32a24 --- /dev/null +++ b/resources/transliteration-data/x65.php @@ -0,0 +1,20 @@ + 'Pan ', 'Yang ', 'Lei ', 'Sa ', 'Shu ', 'Zan ', 'Nian ', 'Xian ', 'Jun ', 'Huo ', 'Li ', 'La ', 'Han ', 'Ying ', 'Lu ', 'Long ', + 0x10 => 'Qian ', 'Qian ', 'Zan ', 'Qian ', 'Lan ', 'San ', 'Ying ', 'Mei ', 'Rang ', 'Chan ', null, 'Cuan ', 'Xi ', 'She ', 'Luo ', 'Jun ', + 0x20 => 'Mi ', 'Li ', 'Zan ', 'Luan ', 'Tan ', 'Zuan ', 'Li ', 'Dian ', 'Wa ', 'Dang ', 'Jiao ', 'Jue ', 'Lan ', 'Li ', 'Nang ', 'Zhi ', + 0x30 => 'Gui ', 'Gui ', 'Qi ', 'Xin ', 'Pu ', 'Sui ', 'Shou ', 'Kao ', 'You ', 'Gai ', 'Yi ', 'Gong ', 'Gan ', 'Ban ', 'Fang ', 'Zheng ', + 0x40 => 'Bo ', 'Dian ', 'Kou ', 'Min ', 'Wu ', 'Gu ', 'He ', 'Ce ', 'Xiao ', 'Mi ', 'Chu ', 'Ge ', 'Di ', 'Xu ', 'Jiao ', 'Min ', + 0x50 => 'Chen ', 'Jiu ', 'Zhen ', 'Duo ', 'Yu ', 'Chi ', 'Ao ', 'Bai ', 'Xu ', 'Jiao ', 'Duo ', 'Lian ', 'Nie ', 'Bi ', 'Chang ', 'Dian ', + 0x60 => 'Duo ', 'Yi ', 'Gan ', 'San ', 'Ke ', 'Yan ', 'Dun ', 'Qi ', 'Dou ', 'Xiao ', 'Duo ', 'Jiao ', 'Jing ', 'Yang ', 'Xia ', 'Min ', + 0x70 => 'Shu ', 'Ai ', 'Qiao ', 'Ai ', 'Zheng ', 'Di ', 'Zhen ', 'Fu ', 'Shu ', 'Liao ', 'Qu ', 'Xiong ', 'Xi ', 'Jiao ', 'Sen ', 'Jiao ', + 0x80 => 'Zhuo ', 'Yi ', 'Lian ', 'Bi ', 'Li ', 'Xiao ', 'Xiao ', 'Wen ', 'Xue ', 'Qi ', 'Qi ', 'Zhai ', 'Bin ', 'Jue ', 'Zhai ', null, + 0x90 => 'Fei ', 'Ban ', 'Ban ', 'Lan ', 'Yu ', 'Lan ', 'Wei ', 'Dou ', 'Sheng ', 'Liao ', 'Jia ', 'Hu ', 'Xie ', 'Jia ', 'Yu ', 'Zhen ', + 0xA0 => 'Jiao ', 'Wo ', 'Tou ', 'Chu ', 'Jin ', 'Chi ', 'Yin ', 'Fu ', 'Qiang ', 'Zhan ', 'Qu ', 'Zhuo ', 'Zhan ', 'Duan ', 'Zhuo ', 'Si ', + 0xB0 => 'Xin ', 'Zhuo ', 'Zhuo ', 'Qin ', 'Lin ', 'Zhuo ', 'Chu ', 'Duan ', 'Zhu ', 'Fang ', 'Xie ', 'Hang ', 'Yu ', 'Shi ', 'Pei ', 'You ', + 0xC0 => 'Mye ', 'Pang ', 'Qi ', 'Zhan ', 'Mao ', 'Lu ', 'Pei ', 'Pi ', 'Liu ', 'Fu ', 'Fang ', 'Xuan ', 'Jing ', 'Jing ', 'Ni ', 'Zu ', + 0xD0 => 'Zhao ', 'Yi ', 'Liu ', 'Shao ', 'Jian ', 'Es ', 'Yi ', 'Qi ', 'Zhi ', 'Fan ', 'Piao ', 'Fan ', 'Zhan ', 'Guai ', 'Sui ', 'Yu ', + 0xE0 => 'Wu ', 'Ji ', 'Ji ', 'Ji ', 'Huo ', 'Ri ', 'Dan ', 'Jiu ', 'Zhi ', 'Zao ', 'Xie ', 'Tiao ', 'Xun ', 'Xu ', 'Xu ', 'Xu ', + 0xF0 => 'Gan ', 'Han ', 'Tai ', 'Di ', 'Xu ', 'Chan ', 'Shi ', 'Kuang ', 'Yang ', 'Shi ', 'Wang ', 'Min ', 'Min ', 'Tun ', 'Chun ', 'Wu ', +]; diff --git a/resources/transliteration-data/x66.php b/resources/transliteration-data/x66.php new file mode 100644 index 000000000..a13e1bdc2 --- /dev/null +++ b/resources/transliteration-data/x66.php @@ -0,0 +1,20 @@ + 'Yun ', 'Bei ', 'Ang ', 'Ze ', 'Ban ', 'Jie ', 'Kun ', 'Sheng ', 'Hu ', 'Fang ', 'Hao ', 'Gui ', 'Chang ', 'Xuan ', 'Ming ', 'Hun ', + 0x10 => 'Fen ', 'Qin ', 'Hu ', 'Yi ', 'Xi ', 'Xin ', 'Yan ', 'Ze ', 'Fang ', 'Tan ', 'Shen ', 'Ju ', 'Yang ', 'Zan ', 'Bing ', 'Xing ', + 0x20 => 'Ying ', 'Xuan ', 'Pei ', 'Zhen ', 'Ling ', 'Chun ', 'Hao ', 'Mei ', 'Zuo ', 'Mo ', 'Bian ', 'Xu ', 'Hun ', 'Zhao ', 'Zong ', 'Shi ', + 0x30 => 'Shi ', 'Yu ', 'Fei ', 'Die ', 'Mao ', 'Ni ', 'Chang ', 'Wen ', 'Dong ', 'Ai ', 'Bing ', 'Ang ', 'Zhou ', 'Long ', 'Xian ', 'Kuang ', + 0x40 => 'Tiao ', 'Chao ', 'Shi ', 'Huang ', 'Huang ', 'Xuan ', 'Kui ', 'Xu ', 'Jiao ', 'Jin ', 'Zhi ', 'Jin ', 'Shang ', 'Tong ', 'Hong ', 'Yan ', + 0x50 => 'Gai ', 'Xiang ', 'Shai ', 'Xiao ', 'Ye ', 'Yun ', 'Hui ', 'Han ', 'Han ', 'Jun ', 'Wan ', 'Xian ', 'Kun ', 'Zhou ', 'Xi ', 'Cheng ', + 0x60 => 'Sheng ', 'Bu ', 'Zhe ', 'Zhe ', 'Wu ', 'Han ', 'Hui ', 'Hao ', 'Chen ', 'Wan ', 'Tian ', 'Zhuo ', 'Zui ', 'Zhou ', 'Pu ', 'Jing ', + 0x70 => 'Xi ', 'Shan ', 'Yi ', 'Xi ', 'Qing ', 'Qi ', 'Jing ', 'Gui ', 'Zhen ', 'Yi ', 'Zhi ', 'An ', 'Wan ', 'Lin ', 'Liang ', 'Chang ', + 0x80 => 'Wang ', 'Xiao ', 'Zan ', 'Hi ', 'Xuan ', 'Xuan ', 'Yi ', 'Xia ', 'Yun ', 'Hui ', 'Fu ', 'Min ', 'Kui ', 'He ', 'Ying ', 'Du ', + 0x90 => 'Wei ', 'Shu ', 'Qing ', 'Mao ', 'Nan ', 'Jian ', 'Nuan ', 'An ', 'Yang ', 'Chun ', 'Yao ', 'Suo ', 'Jin ', 'Ming ', 'Jiao ', 'Kai ', + 0xA0 => 'Gao ', 'Weng ', 'Chang ', 'Qi ', 'Hao ', 'Yan ', 'Li ', 'Ai ', 'Ji ', 'Gui ', 'Men ', 'Zan ', 'Xie ', 'Hao ', 'Mu ', 'Mo ', + 0xB0 => 'Cong ', 'Ni ', 'Zhang ', 'Hui ', 'Bao ', 'Han ', 'Xuan ', 'Chuan ', 'Liao ', 'Xian ', 'Dan ', 'Jing ', 'Pie ', 'Lin ', 'Tun ', 'Xi ', + 0xC0 => 'Yi ', 'Ji ', 'Huang ', 'Tai ', 'Ye ', 'Ye ', 'Li ', 'Tan ', 'Tong ', 'Xiao ', 'Fei ', 'Qin ', 'Zhao ', 'Hao ', 'Yi ', 'Xiang ', + 0xD0 => 'Xing ', 'Sen ', 'Jiao ', 'Bao ', 'Jing ', 'Yian ', 'Ai ', 'Ye ', 'Ru ', 'Shu ', 'Meng ', 'Xun ', 'Yao ', 'Pu ', 'Li ', 'Chen ', + 0xE0 => 'Kuang ', 'Die ', null, 'Yan ', 'Huo ', 'Lu ', 'Xi ', 'Rong ', 'Long ', 'Nang ', 'Luo ', 'Luan ', 'Shai ', 'Tang ', 'Yan ', 'Chu ', + 0xF0 => 'Yue ', 'Yue ', 'Qu ', 'Yi ', 'Geng ', 'Ye ', 'Hu ', 'He ', 'Shu ', 'Cao ', 'Cao ', 'Noboru ', 'Man ', 'Ceng ', 'Ceng ', 'Ti ', +]; diff --git a/resources/transliteration-data/x67.php b/resources/transliteration-data/x67.php new file mode 100644 index 000000000..5c0a7128a --- /dev/null +++ b/resources/transliteration-data/x67.php @@ -0,0 +1,20 @@ + 'Zui ', 'Can ', 'Xu ', 'Hui ', 'Yin ', 'Qie ', 'Fen ', 'Pi ', 'Yue ', 'You ', 'Ruan ', 'Peng ', 'Ban ', 'Fu ', 'Ling ', 'Fei ', + 0x10 => 'Qu ', null, 'Nu ', 'Tiao ', 'Shuo ', 'Zhen ', 'Lang ', 'Lang ', 'Juan ', 'Ming ', 'Huang ', 'Wang ', 'Tun ', 'Zhao ', 'Ji ', 'Qi ', + 0x20 => 'Ying ', 'Zong ', 'Wang ', 'Tong ', 'Lang ', null, 'Meng ', 'Long ', 'Mu ', 'Deng ', 'Wei ', 'Mo ', 'Ben ', 'Zha ', 'Zhu ', 'Zhu ', + 0x30 => null, 'Zhu ', 'Ren ', 'Ba ', 'Po ', 'Duo ', 'Duo ', 'Dao ', 'Li ', 'Qiu ', 'Ji ', 'Jiu ', 'Bi ', 'Xiu ', 'Ting ', 'Ci ', + 0x40 => 'Sha ', 'Eburi ', 'Za ', 'Quan ', 'Qian ', 'Yu ', 'Gan ', 'Wu ', 'Cha ', 'Shan ', 'Xun ', 'Fan ', 'Wu ', 'Zi ', 'Li ', 'Xing ', + 0x50 => 'Cai ', 'Cun ', 'Ren ', 'Shao ', 'Tuo ', 'Di ', 'Zhang ', 'Mang ', 'Chi ', 'Yi ', 'Gu ', 'Gong ', 'Du ', 'Yi ', 'Qi ', 'Shu ', + 0x60 => 'Gang ', 'Tiao ', 'Moku ', 'Soma ', 'Tochi ', 'Lai ', 'Sugi ', 'Mang ', 'Yang ', 'Ma ', 'Miao ', 'Si ', 'Yuan ', 'Hang ', 'Fei ', 'Bei ', + 0x70 => 'Jie ', 'Dong ', 'Gao ', 'Yao ', 'Xian ', 'Chu ', 'Qun ', 'Pa ', 'Shu ', 'Hua ', 'Xin ', 'Chou ', 'Zhu ', 'Chou ', 'Song ', 'Ban ', + 0x80 => 'Song ', 'Ji ', 'Yue ', 'Jin ', 'Gou ', 'Ji ', 'Mao ', 'Pi ', 'Bi ', 'Wang ', 'Ang ', 'Fang ', 'Fen ', 'Yi ', 'Fu ', 'Nan ', + 0x90 => 'Xi ', 'Hu ', 'Ya ', 'Dou ', 'Xun ', 'Zhen ', 'Yao ', 'Lin ', 'Rui ', 'E ', 'Mei ', 'Zhao ', 'Guo ', 'Zhi ', 'Cong ', 'Yun ', + 0xA0 => 'Waku ', 'Dou ', 'Shu ', 'Zao ', null, 'Li ', 'Haze ', 'Jian ', 'Cheng ', 'Matsu ', 'Qiang ', 'Feng ', 'Nan ', 'Xiao ', 'Xian ', 'Ku ', + 0xB0 => 'Ping ', 'Yi ', 'Xi ', 'Zhi ', 'Guai ', 'Xiao ', 'Jia ', 'Jia ', 'Gou ', 'Fu ', 'Mo ', 'Yi ', 'Ye ', 'Ye ', 'Shi ', 'Nie ', + 0xC0 => 'Bi ', 'Duo ', 'Yi ', 'Ling ', 'Bing ', 'Ni ', 'La ', 'He ', 'Pan ', 'Fan ', 'Zhong ', 'Dai ', 'Ci ', 'Yang ', 'Fu ', 'Bo ', + 0xD0 => 'Mou ', 'Gan ', 'Qi ', 'Ran ', 'Rou ', 'Mao ', 'Zhao ', 'Song ', 'Zhe ', 'Xia ', 'You ', 'Shen ', 'Ju ', 'Tuo ', 'Zuo ', 'Nan ', + 0xE0 => 'Ning ', 'Yong ', 'Di ', 'Zhi ', 'Zha ', 'Cha ', 'Dan ', 'Gu ', 'Pu ', 'Jiu ', 'Ao ', 'Fu ', 'Jian ', 'Bo ', 'Duo ', 'Ke ', + 0xF0 => 'Nai ', 'Zhu ', 'Bi ', 'Liu ', 'Chai ', 'Zha ', 'Si ', 'Zhu ', 'Pei ', 'Shi ', 'Guai ', 'Cha ', 'Yao ', 'Jue ', 'Jiu ', 'Shi ', +]; diff --git a/resources/transliteration-data/x68.php b/resources/transliteration-data/x68.php new file mode 100644 index 000000000..6734e76de --- /dev/null +++ b/resources/transliteration-data/x68.php @@ -0,0 +1,20 @@ + 'Zhi ', 'Liu ', 'Mei ', 'Hoy ', 'Rong ', 'Zha ', null, 'Biao ', 'Zhan ', 'Jie ', 'Long ', 'Dong ', 'Lu ', 'Sayng ', 'Li ', 'Lan ', + 0x10 => 'Yong ', 'Shu ', 'Xun ', 'Shuan ', 'Qi ', 'Zhen ', 'Qi ', 'Li ', 'Yi ', 'Xiang ', 'Zhen ', 'Li ', 'Su ', 'Gua ', 'Kan ', 'Bing ', + 0x20 => 'Ren ', 'Xiao ', 'Bo ', 'Ren ', 'Bing ', 'Zi ', 'Chou ', 'Yi ', 'Jie ', 'Xu ', 'Zhu ', 'Jian ', 'Zui ', 'Er ', 'Er ', 'You ', + 0x30 => 'Fa ', 'Gong ', 'Kao ', 'Lao ', 'Zhan ', 'Li ', 'Yin ', 'Yang ', 'He ', 'Gen ', 'Zhi ', 'Chi ', 'Ge ', 'Zai ', 'Luan ', 'Fu ', + 0x40 => 'Jie ', 'Hang ', 'Gui ', 'Tao ', 'Guang ', 'Wei ', 'Kuang ', 'Ru ', 'An ', 'An ', 'Juan ', 'Yi ', 'Zhuo ', 'Ku ', 'Zhi ', 'Qiong ', + 0x50 => 'Tong ', 'Sang ', 'Sang ', 'Huan ', 'Jie ', 'Jiu ', 'Xue ', 'Duo ', 'Zhui ', 'Yu ', 'Zan ', 'Kasei ', 'Ying ', 'Masu ', null, 'Zhan ', + 0x60 => 'Ya ', 'Nao ', 'Zhen ', 'Dang ', 'Qi ', 'Qiao ', 'Hua ', 'Kuai ', 'Jiang ', 'Zhuang ', 'Xun ', 'Suo ', 'Sha ', 'Zhen ', 'Bei ', 'Ting ', + 0x70 => 'Gua ', 'Jing ', 'Bo ', 'Ben ', 'Fu ', 'Rui ', 'Tong ', 'Jue ', 'Xi ', 'Lang ', 'Liu ', 'Feng ', 'Qi ', 'Wen ', 'Jun ', 'Gan ', + 0x80 => 'Cu ', 'Liang ', 'Qiu ', 'Ting ', 'You ', 'Mei ', 'Bang ', 'Long ', 'Peng ', 'Zhuang ', 'Di ', 'Xuan ', 'Tu ', 'Zao ', 'Ao ', 'Gu ', + 0x90 => 'Bi ', 'Di ', 'Han ', 'Zi ', 'Zhi ', 'Ren ', 'Bei ', 'Geng ', 'Jian ', 'Huan ', 'Wan ', 'Nuo ', 'Jia ', 'Tiao ', 'Ji ', 'Xiao ', + 0xA0 => 'Lu ', 'Huan ', 'Shao ', 'Cen ', 'Fen ', 'Song ', 'Meng ', 'Wu ', 'Li ', 'Li ', 'Dou ', 'Cen ', 'Ying ', 'Suo ', 'Ju ', 'Ti ', + 0xB0 => 'Jie ', 'Kun ', 'Zhuo ', 'Shu ', 'Chan ', 'Fan ', 'Wei ', 'Jing ', 'Li ', 'Bing ', 'Fumoto ', 'Shikimi ', 'Tao ', 'Zhi ', 'Lai ', 'Lian ', + 0xC0 => 'Jian ', 'Zhuo ', 'Ling ', 'Li ', 'Qi ', 'Bing ', 'Zhun ', 'Cong ', 'Qian ', 'Mian ', 'Qi ', 'Qi ', 'Cai ', 'Gun ', 'Chan ', 'Te ', + 0xD0 => 'Fei ', 'Pai ', 'Bang ', 'Pou ', 'Hun ', 'Zong ', 'Cheng ', 'Zao ', 'Ji ', 'Li ', 'Peng ', 'Yu ', 'Yu ', 'Gu ', 'Hun ', 'Dong ', + 0xE0 => 'Tang ', 'Gang ', 'Wang ', 'Di ', 'Xi ', 'Fan ', 'Cheng ', 'Zhan ', 'Qi ', 'Yuan ', 'Yan ', 'Yu ', 'Quan ', 'Yi ', 'Sen ', 'Ren ', + 0xF0 => 'Chui ', 'Leng ', 'Qi ', 'Zhuo ', 'Fu ', 'Ke ', 'Lai ', 'Zou ', 'Zou ', 'Zhuo ', 'Guan ', 'Fen ', 'Fen ', 'Chen ', 'Qiong ', 'Nie ', +]; diff --git a/resources/transliteration-data/x69.php b/resources/transliteration-data/x69.php new file mode 100644 index 000000000..a8142a626 --- /dev/null +++ b/resources/transliteration-data/x69.php @@ -0,0 +1,20 @@ + 'Wan ', 'Guo ', 'Lu ', 'Hao ', 'Jie ', 'Yi ', 'Chou ', 'Ju ', 'Ju ', 'Cheng ', 'Zuo ', 'Liang ', 'Qiang ', 'Zhi ', 'Zhui ', 'Ya ', + 0x10 => 'Ju ', 'Bei ', 'Jiao ', 'Zhuo ', 'Zi ', 'Bin ', 'Peng ', 'Ding ', 'Chu ', 'Chang ', 'Kunugi ', 'Momiji ', 'Jian ', 'Gui ', 'Xi ', 'Du ', + 0x20 => 'Qian ', 'Kunugi ', 'Soko ', 'Shide ', 'Luo ', 'Zhi ', 'Ken ', 'Myeng ', 'Tafu ', null, 'Peng ', 'Zhan ', null, 'Tuo ', 'Sen ', 'Duo ', + 0x30 => 'Ye ', 'Fou ', 'Wei ', 'Wei ', 'Duan ', 'Jia ', 'Zong ', 'Jian ', 'Yi ', 'Shen ', 'Xi ', 'Yan ', 'Yan ', 'Chuan ', 'Zhan ', 'Chun ', + 0x40 => 'Yu ', 'He ', 'Zha ', 'Wo ', 'Pian ', 'Bi ', 'Yao ', 'Huo ', 'Xu ', 'Ruo ', 'Yang ', 'La ', 'Yan ', 'Ben ', 'Hun ', 'Kui ', + 0x50 => 'Jie ', 'Kui ', 'Si ', 'Feng ', 'Xie ', 'Tuo ', 'Zhi ', 'Jian ', 'Mu ', 'Mao ', 'Chu ', 'Hu ', 'Hu ', 'Lian ', 'Leng ', 'Ting ', + 0x60 => 'Nan ', 'Yu ', 'You ', 'Mei ', 'Song ', 'Xuan ', 'Xuan ', 'Ying ', 'Zhen ', 'Pian ', 'Ye ', 'Ji ', 'Jie ', 'Ye ', 'Chu ', 'Shun ', + 0x70 => 'Yu ', 'Cou ', 'Wei ', 'Mei ', 'Di ', 'Ji ', 'Jie ', 'Kai ', 'Qiu ', 'Ying ', 'Rou ', 'Heng ', 'Lou ', 'Le ', 'Hazou ', 'Katsura ', + 0x80 => 'Pin ', 'Muro ', 'Gai ', 'Tan ', 'Lan ', 'Yun ', 'Yu ', 'Chen ', 'Lu ', 'Ju ', 'Sakaki ', null, 'Pi ', 'Xie ', 'Jia ', 'Yi ', + 0x90 => 'Zhan ', 'Fu ', 'Nai ', 'Mi ', 'Lang ', 'Rong ', 'Gu ', 'Jian ', 'Ju ', 'Ta ', 'Yao ', 'Zhen ', 'Bang ', 'Sha ', 'Yuan ', 'Zi ', + 0xA0 => 'Ming ', 'Su ', 'Jia ', 'Yao ', 'Jie ', 'Huang ', 'Gan ', 'Fei ', 'Zha ', 'Qian ', 'Ma ', 'Sun ', 'Yuan ', 'Xie ', 'Rong ', 'Shi ', + 0xB0 => 'Zhi ', 'Cui ', 'Yun ', 'Ting ', 'Liu ', 'Rong ', 'Tang ', 'Que ', 'Zhai ', 'Si ', 'Sheng ', 'Ta ', 'Ke ', 'Xi ', 'Gu ', 'Qi ', + 0xC0 => 'Kao ', 'Gao ', 'Sun ', 'Pan ', 'Tao ', 'Ge ', 'Xun ', 'Dian ', 'Nou ', 'Ji ', 'Shuo ', 'Gou ', 'Chui ', 'Qiang ', 'Cha ', 'Qian ', + 0xD0 => 'Huai ', 'Mei ', 'Xu ', 'Gang ', 'Gao ', 'Zhuo ', 'Tuo ', 'Hashi ', 'Yang ', 'Dian ', 'Jia ', 'Jian ', 'Zui ', 'Kashi ', 'Ori ', 'Bin ', + 0xE0 => 'Zhu ', null, 'Xi ', 'Qi ', 'Lian ', 'Hui ', 'Yong ', 'Qian ', 'Guo ', 'Gai ', 'Gai ', 'Tuan ', 'Hua ', 'Cu ', 'Sen ', 'Cui ', + 0xF0 => 'Beng ', 'You ', 'Hu ', 'Jiang ', 'Hu ', 'Huan ', 'Kui ', 'Yi ', 'Nie ', 'Gao ', 'Kang ', 'Gui ', 'Gui ', 'Cao ', 'Man ', 'Jin ', +]; diff --git a/resources/transliteration-data/x6a.php b/resources/transliteration-data/x6a.php new file mode 100644 index 000000000..7588f2d19 --- /dev/null +++ b/resources/transliteration-data/x6a.php @@ -0,0 +1,20 @@ + 'Di ', 'Zhuang ', 'Le ', 'Lang ', 'Chen ', 'Cong ', 'Li ', 'Xiu ', 'Qing ', 'Shuang ', 'Fan ', 'Tong ', 'Guan ', 'Ji ', 'Suo ', 'Lei ', + 0x10 => 'Lu ', 'Liang ', 'Mi ', 'Lou ', 'Chao ', 'Su ', 'Ke ', 'Shu ', 'Tang ', 'Biao ', 'Lu ', 'Jiu ', 'Shu ', 'Zha ', 'Shu ', 'Zhang ', + 0x20 => 'Men ', 'Mo ', 'Niao ', 'Yang ', 'Tiao ', 'Peng ', 'Zhu ', 'Sha ', 'Xi ', 'Quan ', 'Heng ', 'Jian ', 'Cong ', null, 'Hokuso ', 'Qiang ', + 0x30 => 'Tara ', 'Ying ', 'Er ', 'Xin ', 'Zhi ', 'Qiao ', 'Zui ', 'Cong ', 'Pu ', 'Shu ', 'Hua ', 'Kui ', 'Zhen ', 'Zun ', 'Yue ', 'Zhan ', + 0x40 => 'Xi ', 'Xun ', 'Dian ', 'Fa ', 'Gan ', 'Mo ', 'Wu ', 'Qiao ', 'Nao ', 'Lin ', 'Liu ', 'Qiao ', 'Xian ', 'Run ', 'Fan ', 'Zhan ', + 0x50 => 'Tuo ', 'Lao ', 'Yun ', 'Shun ', 'Tui ', 'Cheng ', 'Tang ', 'Meng ', 'Ju ', 'Cheng ', 'Su ', 'Jue ', 'Jue ', 'Tan ', 'Hui ', 'Ji ', + 0x60 => 'Nuo ', 'Xiang ', 'Tuo ', 'Ning ', 'Rui ', 'Zhu ', 'Chuang ', 'Zeng ', 'Fen ', 'Qiong ', 'Ran ', 'Heng ', 'Cen ', 'Gu ', 'Liu ', 'Lao ', + 0x70 => 'Gao ', 'Chu ', 'Zusa ', 'Nude ', 'Ca ', 'San ', 'Ji ', 'Dou ', 'Shou ', 'Lu ', null, null, 'Yuan ', 'Ta ', 'Shu ', 'Jiang ', + 0x80 => 'Tan ', 'Lin ', 'Nong ', 'Yin ', 'Xi ', 'Sui ', 'Shan ', 'Zui ', 'Xuan ', 'Cheng ', 'Gan ', 'Ju ', 'Zui ', 'Yi ', 'Qin ', 'Pu ', + 0x90 => 'Yan ', 'Lei ', 'Feng ', 'Hui ', 'Dang ', 'Ji ', 'Sui ', 'Bo ', 'Bi ', 'Ding ', 'Chu ', 'Zhua ', 'Kuai ', 'Ji ', 'Jie ', 'Jia ', + 0xA0 => 'Qing ', 'Zhe ', 'Jian ', 'Qiang ', 'Dao ', 'Yi ', 'Biao ', 'Song ', 'She ', 'Lin ', 'Kunugi ', 'Cha ', 'Meng ', 'Yin ', 'Tao ', 'Tai ', + 0xB0 => 'Mian ', 'Qi ', 'Toan ', 'Bin ', 'Huo ', 'Ji ', 'Qian ', 'Mi ', 'Ning ', 'Yi ', 'Gao ', 'Jian ', 'Yin ', 'Er ', 'Qing ', 'Yan ', + 0xC0 => 'Qi ', 'Mi ', 'Zhao ', 'Gui ', 'Chun ', 'Ji ', 'Kui ', 'Po ', 'Deng ', 'Chu ', null, 'Mian ', 'You ', 'Zhi ', 'Guang ', 'Qian ', + 0xD0 => 'Lei ', 'Lei ', 'Sa ', 'Lu ', 'Li ', 'Cuan ', 'Lu ', 'Mie ', 'Hui ', 'Ou ', 'Lu ', 'Jie ', 'Gao ', 'Du ', 'Yuan ', 'Li ', + 0xE0 => 'Fei ', 'Zhuo ', 'Sou ', 'Lian ', 'Tamo ', 'Chu ', null, 'Zhu ', 'Lu ', 'Yan ', 'Li ', 'Zhu ', 'Chen ', 'Jie ', 'E ', 'Su ', + 0xF0 => 'Huai ', 'Nie ', 'Yu ', 'Long ', 'Lai ', null, 'Xian ', 'Kwi ', 'Ju ', 'Xiao ', 'Ling ', 'Ying ', 'Jian ', 'Yin ', 'You ', 'Ying ', +]; diff --git a/resources/transliteration-data/x6b.php b/resources/transliteration-data/x6b.php new file mode 100644 index 000000000..bee6729e0 --- /dev/null +++ b/resources/transliteration-data/x6b.php @@ -0,0 +1,20 @@ + 'Xiang ', 'Nong ', 'Bo ', 'Chan ', 'Lan ', 'Ju ', 'Shuang ', 'She ', 'Wei ', 'Cong ', 'Quan ', 'Qu ', 'Cang ', null, 'Yu ', 'Luo ', + 0x10 => 'Li ', 'Zan ', 'Luan ', 'Dang ', 'Jue ', 'Em ', 'Lan ', 'Lan ', 'Zhu ', 'Lei ', 'Li ', 'Ba ', 'Nang ', 'Yu ', 'Ling ', 'Tsuki ', + 0x20 => 'Qian ', 'Ci ', 'Huan ', 'Xin ', 'Yu ', 'Yu ', 'Qian ', 'Ou ', 'Xu ', 'Chao ', 'Chu ', 'Chi ', 'Kai ', 'Yi ', 'Jue ', 'Xi ', + 0x30 => 'Xu ', 'Xia ', 'Yu ', 'Kuai ', 'Lang ', 'Kuan ', 'Shuo ', 'Xi ', 'Ai ', 'Yi ', 'Qi ', 'Hu ', 'Chi ', 'Qin ', 'Kuan ', 'Kan ', + 0x40 => 'Kuan ', 'Kan ', 'Chuan ', 'Sha ', 'Gua ', 'Yin ', 'Xin ', 'Xie ', 'Yu ', 'Qian ', 'Xiao ', 'Yi ', 'Ge ', 'Wu ', 'Tan ', 'Jin ', + 0x50 => 'Ou ', 'Hu ', 'Ti ', 'Huan ', 'Xu ', 'Pen ', 'Xi ', 'Xiao ', 'Xu ', 'Xi ', 'Sen ', 'Lian ', 'Chu ', 'Yi ', 'Kan ', 'Yu ', + 0x60 => 'Chuo ', 'Huan ', 'Zhi ', 'Zheng ', 'Ci ', 'Bu ', 'Wu ', 'Qi ', 'Bu ', 'Bu ', 'Wai ', 'Ju ', 'Qian ', 'Chi ', 'Se ', 'Chi ', + 0x70 => 'Se ', 'Zhong ', 'Sui ', 'Sui ', 'Li ', 'Cuo ', 'Yu ', 'Li ', 'Gui ', 'Dai ', 'Dai ', 'Si ', 'Jian ', 'Zhe ', 'Mo ', 'Mo ', + 0x80 => 'Yao ', 'Mo ', 'Cu ', 'Yang ', 'Tian ', 'Sheng ', 'Dai ', 'Shang ', 'Xu ', 'Xun ', 'Shu ', 'Can ', 'Jue ', 'Piao ', 'Qia ', 'Qiu ', + 0x90 => 'Su ', 'Qing ', 'Yun ', 'Lian ', 'Yi ', 'Fou ', 'Zhi ', 'Ye ', 'Can ', 'Hun ', 'Dan ', 'Ji ', 'Ye ', 'Zhen ', 'Yun ', 'Wen ', + 0xA0 => 'Chou ', 'Bin ', 'Ti ', 'Jin ', 'Shang ', 'Yin ', 'Diao ', 'Cu ', 'Hui ', 'Cuan ', 'Yi ', 'Dan ', 'Du ', 'Jiang ', 'Lian ', 'Bin ', + 0xB0 => 'Du ', 'Tsukusu ', 'Jian ', 'Shu ', 'Ou ', 'Duan ', 'Zhu ', 'Yin ', 'Qing ', 'Yi ', 'Sha ', 'Que ', 'Ke ', 'Yao ', 'Jun ', 'Dian ', + 0xC0 => 'Hui ', 'Hui ', 'Gu ', 'Que ', 'Ji ', 'Yi ', 'Ou ', 'Hui ', 'Duan ', 'Yi ', 'Xiao ', 'Wu ', 'Guan ', 'Mu ', 'Mei ', 'Mei ', + 0xD0 => 'Ai ', 'Zuo ', 'Du ', 'Yu ', 'Bi ', 'Bi ', 'Bi ', 'Pi ', 'Pi ', 'Bi ', 'Chan ', 'Mao ', null, null, 'Pu ', 'Mushiru ', + 0xE0 => 'Jia ', 'Zhan ', 'Sai ', 'Mu ', 'Tuo ', 'Xun ', 'Er ', 'Rong ', 'Xian ', 'Ju ', 'Mu ', 'Hao ', 'Qiu ', 'Dou ', 'Mushiru ', 'Tan ', + 0xF0 => 'Pei ', 'Ju ', 'Duo ', 'Cui ', 'Bi ', 'San ', null, 'Mao ', 'Sui ', 'Yu ', 'Yu ', 'Tuo ', 'He ', 'Jian ', 'Ta ', 'San ', +]; diff --git a/resources/transliteration-data/x6c.php b/resources/transliteration-data/x6c.php new file mode 100644 index 000000000..59cd0495d --- /dev/null +++ b/resources/transliteration-data/x6c.php @@ -0,0 +1,20 @@ + 'Lu ', 'Mu ', 'Li ', 'Tong ', 'Rong ', 'Chang ', 'Pu ', 'Luo ', 'Zhan ', 'Sao ', 'Zhan ', 'Meng ', 'Luo ', 'Qu ', 'Die ', 'Shi ', + 0x10 => 'Di ', 'Min ', 'Jue ', 'Mang ', 'Qi ', 'Pie ', 'Nai ', 'Qi ', 'Dao ', 'Xian ', 'Chuan ', 'Fen ', 'Ri ', 'Nei ', null, 'Fu ', + 0x20 => 'Shen ', 'Dong ', 'Qing ', 'Qi ', 'Yin ', 'Xi ', 'Hai ', 'Yang ', 'An ', 'Ya ', 'Ke ', 'Qing ', 'Ya ', 'Dong ', 'Dan ', 'Lu ', + 0x30 => 'Qing ', 'Yang ', 'Yun ', 'Yun ', 'Shui ', 'San ', 'Zheng ', 'Bing ', 'Yong ', 'Dang ', 'Shitamizu ', 'Le ', 'Ni ', 'Tun ', 'Fan ', 'Gui ', + 0x40 => 'Ting ', 'Zhi ', 'Qiu ', 'Bin ', 'Ze ', 'Mian ', 'Cuan ', 'Hui ', 'Diao ', 'Yi ', 'Cha ', 'Zhuo ', 'Chuan ', 'Wan ', 'Fan ', 'Dai ', + 0x50 => 'Xi ', 'Tuo ', 'Mang ', 'Qiu ', 'Qi ', 'Shan ', 'Pai ', 'Han ', 'Qian ', 'Wu ', 'Wu ', 'Xun ', 'Si ', 'Ru ', 'Gong ', 'Jiang ', + 0x60 => 'Chi ', 'Wu ', 'Tsuchi ', null, 'Tang ', 'Zhi ', 'Chi ', 'Qian ', 'Mi ', 'Yu ', 'Wang ', 'Qing ', 'Jing ', 'Rui ', 'Jun ', 'Hong ', + 0x70 => 'Tai ', 'Quan ', 'Ji ', 'Bian ', 'Bian ', 'Gan ', 'Wen ', 'Zhong ', 'Fang ', 'Xiong ', 'Jue ', 'Hang ', 'Niou ', 'Qi ', 'Fen ', 'Xu ', + 0x80 => 'Xu ', 'Qin ', 'Yi ', 'Wo ', 'Yun ', 'Yuan ', 'Hang ', 'Yan ', 'Chen ', 'Chen ', 'Dan ', 'You ', 'Dun ', 'Hu ', 'Huo ', 'Qie ', + 0x90 => 'Mu ', 'Rou ', 'Mei ', 'Ta ', 'Mian ', 'Wu ', 'Chong ', 'Tian ', 'Bi ', 'Sha ', 'Zhi ', 'Pei ', 'Pan ', 'Zhui ', 'Za ', 'Gou ', + 0xA0 => 'Liu ', 'Mei ', 'Ze ', 'Feng ', 'Ou ', 'Li ', 'Lun ', 'Cang ', 'Feng ', 'Wei ', 'Hu ', 'Mo ', 'Mei ', 'Shu ', 'Ju ', 'Zan ', + 0xB0 => 'Tuo ', 'Tuo ', 'Tuo ', 'He ', 'Li ', 'Mi ', 'Yi ', 'Fa ', 'Fei ', 'You ', 'Tian ', 'Zhi ', 'Zhao ', 'Gu ', 'Zhan ', 'Yan ', + 0xC0 => 'Si ', 'Kuang ', 'Jiong ', 'Ju ', 'Xie ', 'Qiu ', 'Yi ', 'Jia ', 'Zhong ', 'Quan ', 'Bo ', 'Hui ', 'Mi ', 'Ben ', 'Zhuo ', 'Chu ', + 0xD0 => 'Le ', 'You ', 'Gu ', 'Hong ', 'Gan ', 'Fa ', 'Mao ', 'Si ', 'Hu ', 'Ping ', 'Ci ', 'Fan ', 'Chi ', 'Su ', 'Ning ', 'Cheng ', + 0xE0 => 'Ling ', 'Pao ', 'Bo ', 'Qi ', 'Si ', 'Ni ', 'Ju ', 'Yue ', 'Zhu ', 'Sheng ', 'Lei ', 'Xuan ', 'Xue ', 'Fu ', 'Pan ', 'Min ', + 0xF0 => 'Tai ', 'Yang ', 'Ji ', 'Yong ', 'Guan ', 'Beng ', 'Xue ', 'Long ', 'Lu ', null, 'Bo ', 'Xie ', 'Po ', 'Ze ', 'Jing ', 'Yin ', +]; diff --git a/resources/transliteration-data/x6d.php b/resources/transliteration-data/x6d.php new file mode 100644 index 000000000..514781879 --- /dev/null +++ b/resources/transliteration-data/x6d.php @@ -0,0 +1,20 @@ + 'Zhou ', 'Ji ', 'Yi ', 'Hui ', 'Hui ', 'Zui ', 'Cheng ', 'Yin ', 'Wei ', 'Hou ', 'Jian ', 'Yang ', 'Lie ', 'Si ', 'Ji ', 'Er ', + 0x10 => 'Xing ', 'Fu ', 'Sa ', 'Suo ', 'Zhi ', 'Yin ', 'Wu ', 'Xi ', 'Kao ', 'Zhu ', 'Jiang ', 'Luo ', null, 'An ', 'Dong ', 'Yi ', + 0x20 => 'Mou ', 'Lei ', 'Yi ', 'Mi ', 'Quan ', 'Jin ', 'Mo ', 'Wei ', 'Xiao ', 'Xie ', 'Hong ', 'Xu ', 'Shuo ', 'Kuang ', 'Tao ', 'Qie ', + 0x30 => 'Ju ', 'Er ', 'Zhou ', 'Ru ', 'Ping ', 'Xun ', 'Xiong ', 'Zhi ', 'Guang ', 'Huan ', 'Ming ', 'Huo ', 'Wa ', 'Qia ', 'Pai ', 'Wu ', + 0x40 => 'Qu ', 'Liu ', 'Yi ', 'Jia ', 'Jing ', 'Qian ', 'Jiang ', 'Jiao ', 'Cheng ', 'Shi ', 'Zhuo ', 'Ce ', 'Pal ', 'Kuai ', 'Ji ', 'Liu ', + 0x50 => 'Chan ', 'Hun ', 'Hu ', 'Nong ', 'Xun ', 'Jin ', 'Lie ', 'Qiu ', 'Wei ', 'Zhe ', 'Jun ', 'Han ', 'Bang ', 'Mang ', 'Zhuo ', 'You ', + 0x60 => 'Xi ', 'Bo ', 'Dou ', 'Wan ', 'Hong ', 'Yi ', 'Pu ', 'Ying ', 'Lan ', 'Hao ', 'Lang ', 'Han ', 'Li ', 'Geng ', 'Fu ', 'Wu ', + 0x70 => 'Lian ', 'Chun ', 'Feng ', 'Yi ', 'Yu ', 'Tong ', 'Lao ', 'Hai ', 'Jin ', 'Jia ', 'Chong ', 'Weng ', 'Mei ', 'Sui ', 'Cheng ', 'Pei ', + 0x80 => 'Xian ', 'Shen ', 'Tu ', 'Kun ', 'Pin ', 'Nie ', 'Han ', 'Jing ', 'Xiao ', 'She ', 'Nian ', 'Tu ', 'Yong ', 'Xiao ', 'Xian ', 'Ting ', + 0x90 => 'E ', 'Su ', 'Tun ', 'Juan ', 'Cen ', 'Ti ', 'Li ', 'Shui ', 'Si ', 'Lei ', 'Shui ', 'Tao ', 'Du ', 'Lao ', 'Lai ', 'Lian ', + 0xA0 => 'Wei ', 'Wo ', 'Yun ', 'Huan ', 'Di ', null, 'Run ', 'Jian ', 'Zhang ', 'Se ', 'Fu ', 'Guan ', 'Xing ', 'Shou ', 'Shuan ', 'Ya ', + 0xB0 => 'Chuo ', 'Zhang ', 'Ye ', 'Kong ', 'Wo ', 'Han ', 'Tuo ', 'Dong ', 'He ', 'Wo ', 'Ju ', 'Gan ', 'Liang ', 'Hun ', 'Ta ', 'Zhuo ', + 0xC0 => 'Dian ', 'Qie ', 'De ', 'Juan ', 'Zi ', 'Xi ', 'Yao ', 'Qi ', 'Gu ', 'Guo ', 'Han ', 'Lin ', 'Tang ', 'Zhou ', 'Peng ', 'Hao ', + 0xD0 => 'Chang ', 'Shu ', 'Qi ', 'Fang ', 'Chi ', 'Lu ', 'Nao ', 'Ju ', 'Tao ', 'Cong ', 'Lei ', 'Zhi ', 'Peng ', 'Fei ', 'Song ', 'Tian ', + 0xE0 => 'Pi ', 'Dan ', 'Yu ', 'Ni ', 'Yu ', 'Lu ', 'Gan ', 'Mi ', 'Jing ', 'Ling ', 'Lun ', 'Yin ', 'Cui ', 'Qu ', 'Huai ', 'Yu ', + 0xF0 => 'Nian ', 'Shen ', 'Piao ', 'Chun ', 'Wa ', 'Yuan ', 'Lai ', 'Hun ', 'Qing ', 'Yan ', 'Qian ', 'Tian ', 'Miao ', 'Zhi ', 'Yin ', 'Mi ', +]; diff --git a/resources/transliteration-data/x6e.php b/resources/transliteration-data/x6e.php new file mode 100644 index 000000000..64701e7ba --- /dev/null +++ b/resources/transliteration-data/x6e.php @@ -0,0 +1,20 @@ + 'Ben ', 'Yuan ', 'Wen ', 'Re ', 'Fei ', 'Qing ', 'Yuan ', 'Ke ', 'Ji ', 'She ', 'Yuan ', 'Shibui ', 'Lu ', 'Zi ', 'Du ', null, + 0x10 => 'Jian ', 'Min ', 'Pi ', 'Tani ', 'Yu ', 'Yuan ', 'Shen ', 'Shen ', 'Rou ', 'Huan ', 'Zhu ', 'Jian ', 'Nuan ', 'Yu ', 'Qiu ', 'Ting ', + 0x20 => 'Qu ', 'Du ', 'Feng ', 'Zha ', 'Bo ', 'Wo ', 'Wo ', 'Di ', 'Wei ', 'Wen ', 'Ru ', 'Xie ', 'Ce ', 'Wei ', 'Ge ', 'Gang ', + 0x30 => 'Yan ', 'Hong ', 'Xuan ', 'Mi ', 'Ke ', 'Mao ', 'Ying ', 'Yan ', 'You ', 'Hong ', 'Miao ', 'Xing ', 'Mei ', 'Zai ', 'Hun ', 'Nai ', + 0x40 => 'Kui ', 'Shi ', 'E ', 'Pai ', 'Mei ', 'Lian ', 'Qi ', 'Qi ', 'Mei ', 'Tian ', 'Cou ', 'Wei ', 'Can ', 'Tuan ', 'Mian ', 'Hui ', + 0x50 => 'Mo ', 'Xu ', 'Ji ', 'Pen ', 'Jian ', 'Jian ', 'Hu ', 'Feng ', 'Xiang ', 'Yi ', 'Yin ', 'Zhan ', 'Shi ', 'Jie ', 'Cheng ', 'Huang ', + 0x60 => 'Tan ', 'Yu ', 'Bi ', 'Min ', 'Shi ', 'Tu ', 'Sheng ', 'Yong ', 'Qu ', 'Zhong ', 'Suei ', 'Jiu ', 'Jiao ', 'Qiou ', 'Yin ', 'Tang ', + 0x70 => 'Long ', 'Huo ', 'Yuan ', 'Nan ', 'Ban ', 'You ', 'Quan ', 'Chui ', 'Liang ', 'Chan ', 'Yan ', 'Chun ', 'Nie ', 'Zi ', 'Wan ', 'Shi ', + 0x80 => 'Man ', 'Ying ', 'Ratsu ', 'Kui ', null, 'Jian ', 'Xu ', 'Lu ', 'Gui ', 'Gai ', null, null, 'Po ', 'Jin ', 'Gui ', 'Tang ', + 0x90 => 'Yuan ', 'Suo ', 'Yuan ', 'Lian ', 'Yao ', 'Meng ', 'Zhun ', 'Sheng ', 'Ke ', 'Tai ', 'Da ', 'Wa ', 'Liu ', 'Gou ', 'Sao ', 'Ming ', + 0xA0 => 'Zha ', 'Shi ', 'Yi ', 'Lun ', 'Ma ', 'Pu ', 'Wei ', 'Li ', 'Cai ', 'Wu ', 'Xi ', 'Wen ', 'Qiang ', 'Ze ', 'Shi ', 'Su ', + 0xB0 => 'Yi ', 'Zhen ', 'Sou ', 'Yun ', 'Xiu ', 'Yin ', 'Rong ', 'Hun ', 'Su ', 'Su ', 'Ni ', 'Ta ', 'Shi ', 'Ru ', 'Wei ', 'Pan ', + 0xC0 => 'Chu ', 'Chu ', 'Pang ', 'Weng ', 'Cang ', 'Mie ', 'He ', 'Dian ', 'Hao ', 'Huang ', 'Xi ', 'Zi ', 'Di ', 'Zhi ', 'Ying ', 'Fu ', + 0xD0 => 'Jie ', 'Hua ', 'Ge ', 'Zi ', 'Tao ', 'Teng ', 'Sui ', 'Bi ', 'Jiao ', 'Hui ', 'Gun ', 'Yin ', 'Gao ', 'Long ', 'Zhi ', 'Yan ', + 0xE0 => 'She ', 'Man ', 'Ying ', 'Chun ', 'Lu ', 'Lan ', 'Luan ', null, 'Bin ', 'Tan ', 'Yu ', 'Sou ', 'Hu ', 'Bi ', 'Biao ', 'Zhi ', + 0xF0 => 'Jiang ', 'Kou ', 'Shen ', 'Shang ', 'Di ', 'Mi ', 'Ao ', 'Lu ', 'Hu ', 'Hu ', 'You ', 'Chan ', 'Fan ', 'Yong ', 'Gun ', 'Man ', +]; diff --git a/resources/transliteration-data/x6f.php b/resources/transliteration-data/x6f.php new file mode 100644 index 000000000..81754d1ce --- /dev/null +++ b/resources/transliteration-data/x6f.php @@ -0,0 +1,20 @@ + 'Qing ', 'Yu ', 'Piao ', 'Ji ', 'Ya ', 'Jiao ', 'Qi ', 'Xi ', 'Ji ', 'Lu ', 'Lu ', 'Long ', 'Jin ', 'Guo ', 'Cong ', 'Lou ', + 0x10 => 'Zhi ', 'Gai ', 'Qiang ', 'Li ', 'Yan ', 'Cao ', 'Jiao ', 'Cong ', 'Qun ', 'Tuan ', 'Ou ', 'Teng ', 'Ye ', 'Xi ', 'Mi ', 'Tang ', + 0x20 => 'Mo ', 'Shang ', 'Han ', 'Lian ', 'Lan ', 'Wa ', 'Li ', 'Qian ', 'Feng ', 'Xuan ', 'Yi ', 'Man ', 'Zi ', 'Mang ', 'Kang ', 'Lei ', + 0x30 => 'Peng ', 'Shu ', 'Zhang ', 'Zhang ', 'Chong ', 'Xu ', 'Huan ', 'Kuo ', 'Jian ', 'Yan ', 'Chuang ', 'Liao ', 'Cui ', 'Ti ', 'Yang ', 'Jiang ', + 0x40 => 'Cong ', 'Ying ', 'Hong ', 'Xun ', 'Shu ', 'Guan ', 'Ying ', 'Xiao ', null, null, 'Xu ', 'Lian ', 'Zhi ', 'Wei ', 'Pi ', 'Jue ', + 0x50 => 'Jiao ', 'Po ', 'Dang ', 'Hui ', 'Jie ', 'Wu ', 'Pa ', 'Ji ', 'Pan ', 'Gui ', 'Xiao ', 'Qian ', 'Qian ', 'Xi ', 'Lu ', 'Xi ', + 0x60 => 'Xuan ', 'Dun ', 'Huang ', 'Min ', 'Run ', 'Su ', 'Liao ', 'Zhen ', 'Zhong ', 'Yi ', 'Di ', 'Wan ', 'Dan ', 'Tan ', 'Chao ', 'Xun ', + 0x70 => 'Kui ', 'Yie ', 'Shao ', 'Tu ', 'Zhu ', 'San ', 'Hei ', 'Bi ', 'Shan ', 'Chan ', 'Chan ', 'Shu ', 'Tong ', 'Pu ', 'Lin ', 'Wei ', + 0x80 => 'Se ', 'Se ', 'Cheng ', 'Jiong ', 'Cheng ', 'Hua ', 'Jiao ', 'Lao ', 'Che ', 'Gan ', 'Cun ', 'Heng ', 'Si ', 'Shu ', 'Peng ', 'Han ', + 0x90 => 'Yun ', 'Liu ', 'Hong ', 'Fu ', 'Hao ', 'He ', 'Xian ', 'Jian ', 'Shan ', 'Xi ', 'Oki ', null, 'Lan ', null, 'Yu ', 'Lin ', + 0xA0 => 'Min ', 'Zao ', 'Dang ', 'Wan ', 'Ze ', 'Xie ', 'Yu ', 'Li ', 'Shi ', 'Xue ', 'Ling ', 'Man ', 'Zi ', 'Yong ', 'Kuai ', 'Can ', + 0xB0 => 'Lian ', 'Dian ', 'Ye ', 'Ao ', 'Huan ', 'Zhen ', 'Chan ', 'Man ', 'Dan ', 'Dan ', 'Yi ', 'Sui ', 'Pi ', 'Ju ', 'Ta ', 'Qin ', + 0xC0 => 'Ji ', 'Zhuo ', 'Lian ', 'Nong ', 'Guo ', 'Jin ', 'Fen ', 'Se ', 'Ji ', 'Sui ', 'Hui ', 'Chu ', 'Ta ', 'Song ', 'Ding ', null, + 0xD0 => 'Zhu ', 'Lai ', 'Bin ', 'Lian ', 'Mi ', 'Shi ', 'Shu ', 'Mi ', 'Ning ', 'Ying ', 'Ying ', 'Meng ', 'Jin ', 'Qi ', 'Pi ', 'Ji ', + 0xE0 => 'Hao ', 'Ru ', 'Zui ', 'Wo ', 'Tao ', 'Yin ', 'Yin ', 'Dui ', 'Ci ', 'Huo ', 'Jing ', 'Lan ', 'Jun ', 'Ai ', 'Pu ', 'Zhuo ', + 0xF0 => 'Wei ', 'Bin ', 'Gu ', 'Qian ', 'Xing ', 'Hama ', 'Kuo ', 'Fei ', null, 'Boku ', 'Jian ', 'Wei ', 'Luo ', 'Zan ', 'Lu ', 'Li ', +]; diff --git a/resources/transliteration-data/x70.php b/resources/transliteration-data/x70.php new file mode 100644 index 000000000..97a18f74d --- /dev/null +++ b/resources/transliteration-data/x70.php @@ -0,0 +1,20 @@ + 'You ', 'Yang ', 'Lu ', 'Si ', 'Jie ', 'Ying ', 'Du ', 'Wang ', 'Hui ', 'Xie ', 'Pan ', 'Shen ', 'Biao ', 'Chan ', 'Mo ', 'Liu ', + 0x10 => 'Jian ', 'Pu ', 'Se ', 'Cheng ', 'Gu ', 'Bin ', 'Huo ', 'Xian ', 'Lu ', 'Qin ', 'Han ', 'Ying ', 'Yong ', 'Li ', 'Jing ', 'Xiao ', + 0x20 => 'Ying ', 'Sui ', 'Wei ', 'Xie ', 'Huai ', 'Hao ', 'Zhu ', 'Long ', 'Lai ', 'Dui ', 'Fan ', 'Hu ', 'Lai ', null, null, 'Ying ', + 0x30 => 'Mi ', 'Ji ', 'Lian ', 'Jian ', 'Ying ', 'Fen ', 'Lin ', 'Yi ', 'Jian ', 'Yue ', 'Chan ', 'Dai ', 'Rang ', 'Jian ', 'Lan ', 'Fan ', + 0x40 => 'Shuang ', 'Yuan ', 'Zhuo ', 'Feng ', 'She ', 'Lei ', 'Lan ', 'Cong ', 'Qu ', 'Yong ', 'Qian ', 'Fa ', 'Guan ', 'Que ', 'Yan ', 'Hao ', + 0x50 => 'Hyeng ', 'Sa ', 'Zan ', 'Luan ', 'Yan ', 'Li ', 'Mi ', 'Shan ', 'Tan ', 'Dang ', 'Jiao ', 'Chan ', null, 'Hao ', 'Ba ', 'Zhu ', + 0x60 => 'Lan ', 'Lan ', 'Nang ', 'Wan ', 'Luan ', 'Xun ', 'Xian ', 'Yan ', 'Gan ', 'Yan ', 'Yu ', 'Huo ', 'Si ', 'Mie ', 'Guang ', 'Deng ', + 0x70 => 'Hui ', 'Xiao ', 'Xiao ', 'Hu ', 'Hong ', 'Ling ', 'Zao ', 'Zhuan ', 'Jiu ', 'Zha ', 'Xie ', 'Chi ', 'Zhuo ', 'Zai ', 'Zai ', 'Can ', + 0x80 => 'Yang ', 'Qi ', 'Zhong ', 'Fen ', 'Niu ', 'Jiong ', 'Wen ', 'Po ', 'Yi ', 'Lu ', 'Chui ', 'Pi ', 'Kai ', 'Pan ', 'Yan ', 'Kai ', + 0x90 => 'Pang ', 'Mu ', 'Chao ', 'Liao ', 'Gui ', 'Kang ', 'Tun ', 'Guang ', 'Xin ', 'Zhi ', 'Guang ', 'Guang ', 'Wei ', 'Qiang ', null, 'Da ', + 0xA0 => 'Xia ', 'Zheng ', 'Zhu ', 'Ke ', 'Zhao ', 'Fu ', 'Ba ', 'Duo ', 'Duo ', 'Ling ', 'Zhuo ', 'Xuan ', 'Ju ', 'Tan ', 'Pao ', 'Jiong ', + 0xB0 => 'Pao ', 'Tai ', 'Tai ', 'Bing ', 'Yang ', 'Tong ', 'Han ', 'Zhu ', 'Zha ', 'Dian ', 'Wei ', 'Shi ', 'Lian ', 'Chi ', 'Huang ', null, + 0xC0 => 'Hu ', 'Shuo ', 'Lan ', 'Jing ', 'Jiao ', 'Xu ', 'Xing ', 'Quan ', 'Lie ', 'Huan ', 'Yang ', 'Xiao ', 'Xiu ', 'Xian ', 'Yin ', 'Wu ', + 0xD0 => 'Zhou ', 'Yao ', 'Shi ', 'Wei ', 'Tong ', 'Xue ', 'Zai ', 'Kai ', 'Hong ', 'Luo ', 'Xia ', 'Zhu ', 'Xuan ', 'Zheng ', 'Po ', 'Yan ', + 0xE0 => 'Hui ', 'Guang ', 'Zhe ', 'Hui ', 'Kao ', null, 'Fan ', 'Shao ', 'Ye ', 'Hui ', null, 'Tang ', 'Jin ', 'Re ', null, 'Xi ', + 0xF0 => 'Fu ', 'Jiong ', 'Che ', 'Pu ', 'Jing ', 'Zhuo ', 'Ting ', 'Wan ', 'Hai ', 'Peng ', 'Lang ', 'Shan ', 'Hu ', 'Feng ', 'Chi ', 'Rong ', +]; diff --git a/resources/transliteration-data/x71.php b/resources/transliteration-data/x71.php new file mode 100644 index 000000000..6105a4877 --- /dev/null +++ b/resources/transliteration-data/x71.php @@ -0,0 +1,20 @@ + 'Hu ', 'Xi ', 'Shu ', 'He ', 'Xun ', 'Ku ', 'Jue ', 'Xiao ', 'Xi ', 'Yan ', 'Han ', 'Zhuang ', 'Jun ', 'Di ', 'Xie ', 'Ji ', + 0x10 => 'Wu ', null, null, 'Han ', 'Yan ', 'Huan ', 'Men ', 'Ju ', 'Chou ', 'Bei ', 'Fen ', 'Lin ', 'Kun ', 'Hun ', 'Tun ', 'Xi ', + 0x20 => 'Cui ', 'Wu ', 'Hong ', 'Ju ', 'Fu ', 'Wo ', 'Jiao ', 'Cong ', 'Feng ', 'Ping ', 'Qiong ', 'Ruo ', 'Xi ', 'Qiong ', 'Xin ', 'Zhuo ', + 0x30 => 'Yan ', 'Yan ', 'Yi ', 'Jue ', 'Yu ', 'Gang ', 'Ran ', 'Pi ', 'Gu ', null, 'Sheng ', 'Chang ', 'Shao ', null, null, null, + 0x40 => null, 'Chen ', 'He ', 'Kui ', 'Zhong ', 'Duan ', 'Xia ', 'Hui ', 'Feng ', 'Lian ', 'Xuan ', 'Xing ', 'Huang ', 'Jiao ', 'Jian ', 'Bi ', + 0x50 => 'Ying ', 'Zhu ', 'Wei ', 'Tuan ', 'Tian ', 'Xi ', 'Nuan ', 'Nuan ', 'Chan ', 'Yan ', 'Jiong ', 'Jiong ', 'Yu ', 'Mei ', 'Sha ', 'Wei ', + 0x60 => 'Ye ', 'Xin ', 'Qiong ', 'Rou ', 'Mei ', 'Huan ', 'Xu ', 'Zhao ', 'Wei ', 'Fan ', 'Qiu ', 'Sui ', 'Yang ', 'Lie ', 'Zhu ', 'Jie ', + 0x70 => 'Gao ', 'Gua ', 'Bao ', 'Hu ', 'Yun ', 'Xia ', null, null, 'Bian ', 'Gou ', 'Tui ', 'Tang ', 'Chao ', 'Shan ', 'N ', 'Bo ', + 0x80 => 'Huang ', 'Xie ', 'Xi ', 'Wu ', 'Xi ', 'Yun ', 'He ', 'He ', 'Xi ', 'Yun ', 'Xiong ', 'Nai ', 'Shan ', 'Qiong ', 'Yao ', 'Xun ', + 0x90 => 'Mi ', 'Lian ', 'Ying ', 'Wen ', 'Rong ', 'Oozutsu ', null, 'Qiang ', 'Liu ', 'Xi ', 'Bi ', 'Biao ', 'Zong ', 'Lu ', 'Jian ', 'Shou ', + 0xA0 => 'Yi ', 'Lou ', 'Feng ', 'Sui ', 'Yi ', 'Tong ', 'Jue ', 'Zong ', 'Yun ', 'Hu ', 'Yi ', 'Zhi ', 'Ao ', 'Wei ', 'Liao ', 'Han ', + 0xB0 => 'Ou ', 'Re ', 'Jiong ', 'Man ', null, 'Shang ', 'Cuan ', 'Zeng ', 'Jian ', 'Xi ', 'Xi ', 'Xi ', 'Yi ', 'Xiao ', 'Chi ', 'Huang ', + 0xC0 => 'Chan ', 'Ye ', 'Qian ', 'Ran ', 'Yan ', 'Xian ', 'Qiao ', 'Zun ', 'Deng ', 'Dun ', 'Shen ', 'Jiao ', 'Fen ', 'Si ', 'Liao ', 'Yu ', + 0xD0 => 'Lin ', 'Tong ', 'Shao ', 'Fen ', 'Fan ', 'Yan ', 'Xun ', 'Lan ', 'Mei ', 'Tang ', 'Yi ', 'Jing ', 'Men ', null, null, 'Ying ', + 0xE0 => 'Yu ', 'Yi ', 'Xue ', 'Lan ', 'Tai ', 'Zao ', 'Can ', 'Sui ', 'Xi ', 'Que ', 'Cong ', 'Lian ', 'Hui ', 'Zhu ', 'Xie ', 'Ling ', + 0xF0 => 'Wei ', 'Yi ', 'Xie ', 'Zhao ', 'Hui ', 'Tatsu ', 'Nung ', 'Lan ', 'Ru ', 'Xian ', 'Kao ', 'Xun ', 'Jin ', 'Chou ', 'Chou ', 'Yao ', +]; diff --git a/resources/transliteration-data/x72.php b/resources/transliteration-data/x72.php new file mode 100644 index 000000000..5860cbe70 --- /dev/null +++ b/resources/transliteration-data/x72.php @@ -0,0 +1,20 @@ + 'He ', 'Lan ', 'Biao ', 'Rong ', 'Li ', 'Mo ', 'Bao ', 'Ruo ', 'Lu ', 'La ', 'Ao ', 'Xun ', 'Kuang ', 'Shuo ', null, 'Li ', + 0x10 => 'Lu ', 'Jue ', 'Liao ', 'Yan ', 'Xi ', 'Xie ', 'Long ', 'Ye ', null, 'Rang ', 'Yue ', 'Lan ', 'Cong ', 'Jue ', 'Tong ', 'Guan ', + 0x20 => null, 'Che ', 'Mi ', 'Tang ', 'Lan ', 'Zhu ', null, 'Ling ', 'Cuan ', 'Yu ', 'Zhua ', 'Tsumekanmuri ', 'Pa ', 'Zheng ', 'Pao ', 'Cheng ', + 0x30 => 'Yuan ', 'Ai ', 'Wei ', null, 'Jue ', 'Jue ', 'Fu ', 'Ye ', 'Ba ', 'Die ', 'Ye ', 'Yao ', 'Zu ', 'Shuang ', 'Er ', 'Qiang ', + 0x40 => 'Chuang ', 'Ge ', 'Zang ', 'Die ', 'Qiang ', 'Yong ', 'Qiang ', 'Pian ', 'Ban ', 'Pan ', 'Shao ', 'Jian ', 'Pai ', 'Du ', 'Chuang ', 'Tou ', + 0x50 => 'Zha ', 'Bian ', 'Die ', 'Bang ', 'Bo ', 'Chuang ', 'You ', null, 'Du ', 'Ya ', 'Cheng ', 'Niu ', 'Ushihen ', 'Pin ', 'Jiu ', 'Mou ', + 0x60 => 'Tuo ', 'Mu ', 'Lao ', 'Ren ', 'Mang ', 'Fang ', 'Mao ', 'Mu ', 'Gang ', 'Wu ', 'Yan ', 'Ge ', 'Bei ', 'Si ', 'Jian ', 'Gu ', + 0x70 => 'You ', 'Ge ', 'Sheng ', 'Mu ', 'Di ', 'Qian ', 'Quan ', 'Quan ', 'Zi ', 'Te ', 'Xi ', 'Mang ', 'Keng ', 'Qian ', 'Wu ', 'Gu ', + 0x80 => 'Xi ', 'Li ', 'Li ', 'Pou ', 'Ji ', 'Gang ', 'Zhi ', 'Ben ', 'Quan ', 'Run ', 'Du ', 'Ju ', 'Jia ', 'Jian ', 'Feng ', 'Pian ', + 0x90 => 'Ke ', 'Ju ', 'Kao ', 'Chu ', 'Xi ', 'Bei ', 'Luo ', 'Jie ', 'Ma ', 'San ', 'Wei ', 'Li ', 'Dun ', 'Tong ', null, 'Jiang ', + 0xA0 => 'Ikenie ', 'Li ', 'Du ', 'Lie ', 'Pi ', 'Piao ', 'Bao ', 'Xi ', 'Chou ', 'Wei ', 'Kui ', 'Chou ', 'Quan ', 'Fan ', 'Ba ', 'Fan ', + 0xB0 => 'Qiu ', 'Ji ', 'Cai ', 'Chuo ', 'An ', 'Jie ', 'Zhuang ', 'Guang ', 'Ma ', 'You ', 'Kang ', 'Bo ', 'Hou ', 'Ya ', 'Yin ', 'Huan ', + 0xC0 => 'Zhuang ', 'Yun ', 'Kuang ', 'Niu ', 'Di ', 'Qing ', 'Zhong ', 'Mu ', 'Bei ', 'Pi ', 'Ju ', 'Ni ', 'Sheng ', 'Pao ', 'Xia ', 'Tuo ', + 0xD0 => 'Hu ', 'Ling ', 'Fei ', 'Pi ', 'Ni ', 'Ao ', 'You ', 'Gou ', 'Yue ', 'Ju ', 'Dan ', 'Po ', 'Gu ', 'Xian ', 'Ning ', 'Huan ', + 0xE0 => 'Hen ', 'Jiao ', 'He ', 'Zhao ', 'Ji ', 'Xun ', 'Shan ', 'Ta ', 'Rong ', 'Shou ', 'Tong ', 'Lao ', 'Du ', 'Xia ', 'Shi ', 'Hua ', + 0xF0 => 'Zheng ', 'Yu ', 'Sun ', 'Yu ', 'Bi ', 'Mang ', 'Xi ', 'Juan ', 'Li ', 'Xia ', 'Yin ', 'Suan ', 'Lang ', 'Bei ', 'Zhi ', 'Yan ', +]; diff --git a/resources/transliteration-data/x73.php b/resources/transliteration-data/x73.php new file mode 100644 index 000000000..74e96ebd7 --- /dev/null +++ b/resources/transliteration-data/x73.php @@ -0,0 +1,20 @@ + 'Sha ', 'Li ', 'Han ', 'Xian ', 'Jing ', 'Pai ', 'Fei ', 'Yao ', 'Ba ', 'Qi ', 'Ni ', 'Biao ', 'Yin ', 'Lai ', 'Xi ', 'Jian ', + 0x10 => 'Qiang ', 'Kun ', 'Yan ', 'Guo ', 'Zong ', 'Mi ', 'Chang ', 'Yi ', 'Zhi ', 'Zheng ', 'Ya ', 'Meng ', 'Cai ', 'Cu ', 'She ', 'Kari ', + 0x20 => 'Cen ', 'Luo ', 'Hu ', 'Zong ', 'Ji ', 'Wei ', 'Feng ', 'Wo ', 'Yuan ', 'Xing ', 'Zhu ', 'Mao ', 'Wei ', 'Yuan ', 'Xian ', 'Tuan ', + 0x30 => 'Ya ', 'Nao ', 'Xie ', 'Jia ', 'Hou ', 'Bian ', 'You ', 'You ', 'Mei ', 'Zha ', 'Yao ', 'Sun ', 'Bo ', 'Ming ', 'Hua ', 'Yuan ', + 0x40 => 'Sou ', 'Ma ', 'Yuan ', 'Dai ', 'Yu ', 'Shi ', 'Hao ', null, 'Yi ', 'Zhen ', 'Chuang ', 'Hao ', 'Man ', 'Jing ', 'Jiang ', 'Mu ', + 0x50 => 'Zhang ', 'Chan ', 'Ao ', 'Ao ', 'Hao ', 'Cui ', 'Fen ', 'Jue ', 'Bi ', 'Bi ', 'Huang ', 'Pu ', 'Lin ', 'Yu ', 'Tong ', 'Yao ', + 0x60 => 'Liao ', 'Shuo ', 'Xiao ', 'Swu ', 'Ton ', 'Xi ', 'Ge ', 'Juan ', 'Du ', 'Hui ', 'Kuai ', 'Xian ', 'Xie ', 'Ta ', 'Xian ', 'Xun ', + 0x70 => 'Ning ', 'Pin ', 'Huo ', 'Nou ', 'Meng ', 'Lie ', 'Nao ', 'Guang ', 'Shou ', 'Lu ', 'Ta ', 'Xian ', 'Mi ', 'Rang ', 'Huan ', 'Nao ', + 0x80 => 'Luo ', 'Xian ', 'Qi ', 'Jue ', 'Xuan ', 'Miao ', 'Zi ', 'Lu ', 'Lu ', 'Yu ', 'Su ', 'Wang ', 'Qiu ', 'Ga ', 'Ding ', 'Le ', + 0x90 => 'Ba ', 'Ji ', 'Hong ', 'Di ', 'Quan ', 'Gan ', 'Jiu ', 'Yu ', 'Ji ', 'Yu ', 'Yang ', 'Ma ', 'Gong ', 'Wu ', 'Fu ', 'Wen ', + 0xA0 => 'Jie ', 'Ya ', 'Fen ', 'Bian ', 'Beng ', 'Yue ', 'Jue ', 'Yun ', 'Jue ', 'Wan ', 'Jian ', 'Mei ', 'Dan ', 'Pi ', 'Wei ', 'Huan ', + 0xB0 => 'Xian ', 'Qiang ', 'Ling ', 'Dai ', 'Yi ', 'An ', 'Ping ', 'Dian ', 'Fu ', 'Xuan ', 'Xi ', 'Bo ', 'Ci ', 'Gou ', 'Jia ', 'Shao ', + 0xC0 => 'Po ', 'Ci ', 'Ke ', 'Ran ', 'Sheng ', 'Shen ', 'Yi ', 'Zu ', 'Jia ', 'Min ', 'Shan ', 'Liu ', 'Bi ', 'Zhen ', 'Zhen ', 'Jue ', + 0xD0 => 'Fa ', 'Long ', 'Jin ', 'Jiao ', 'Jian ', 'Li ', 'Guang ', 'Xian ', 'Zhou ', 'Gong ', 'Yan ', 'Xiu ', 'Yang ', 'Xu ', 'Luo ', 'Su ', + 0xE0 => 'Zhu ', 'Qin ', 'Ken ', 'Xun ', 'Bao ', 'Er ', 'Xiang ', 'Yao ', 'Xia ', 'Heng ', 'Gui ', 'Chong ', 'Xu ', 'Ban ', 'Pei ', null, + 0xF0 => 'Dang ', 'Ei ', 'Hun ', 'Wen ', 'E ', 'Cheng ', 'Ti ', 'Wu ', 'Wu ', 'Cheng ', 'Jun ', 'Mei ', 'Bei ', 'Ting ', 'Xian ', 'Chuo ', +]; diff --git a/resources/transliteration-data/x74.php b/resources/transliteration-data/x74.php new file mode 100644 index 000000000..c566dfaab --- /dev/null +++ b/resources/transliteration-data/x74.php @@ -0,0 +1,20 @@ + 'Han ', 'Xuan ', 'Yan ', 'Qiu ', 'Quan ', 'Lang ', 'Li ', 'Xiu ', 'Fu ', 'Liu ', 'Ye ', 'Xi ', 'Ling ', 'Li ', 'Jin ', 'Lian ', + 0x10 => 'Suo ', 'Chiisai ', null, 'Wan ', 'Dian ', 'Pin ', 'Zhan ', 'Cui ', 'Min ', 'Yu ', 'Ju ', 'Chen ', 'Lai ', 'Wen ', 'Sheng ', 'Wei ', + 0x20 => 'Dian ', 'Chu ', 'Zhuo ', 'Pei ', 'Cheng ', 'Hu ', 'Qi ', 'E ', 'Kun ', 'Chang ', 'Qi ', 'Beng ', 'Wan ', 'Lu ', 'Cong ', 'Guan ', + 0x30 => 'Yan ', 'Diao ', 'Bei ', 'Lin ', 'Qin ', 'Pi ', 'Pa ', 'Que ', 'Zhuo ', 'Qin ', 'Fa ', null, 'Qiong ', 'Du ', 'Jie ', 'Hun ', + 0x40 => 'Yu ', 'Mao ', 'Mei ', 'Chun ', 'Xuan ', 'Ti ', 'Xing ', 'Dai ', 'Rou ', 'Min ', 'Zhen ', 'Wei ', 'Ruan ', 'Huan ', 'Jie ', 'Chuan ', + 0x50 => 'Jian ', 'Zhuan ', 'Yang ', 'Lian ', 'Quan ', 'Xia ', 'Duan ', 'Yuan ', 'Ye ', 'Nao ', 'Hu ', 'Ying ', 'Yu ', 'Huang ', 'Rui ', 'Se ', + 0x60 => 'Liu ', 'Shi ', 'Rong ', 'Suo ', 'Yao ', 'Wen ', 'Wu ', 'Jin ', 'Jin ', 'Ying ', 'Ma ', 'Tao ', 'Liu ', 'Tang ', 'Li ', 'Lang ', + 0x70 => 'Gui ', 'Zhen ', 'Qiang ', 'Cuo ', 'Jue ', 'Zhao ', 'Yao ', 'Ai ', 'Bin ', 'Tu ', 'Chang ', 'Kun ', 'Zhuan ', 'Cong ', 'Jin ', 'Yi ', + 0x80 => 'Cui ', 'Cong ', 'Qi ', 'Li ', 'Ying ', 'Suo ', 'Qiu ', 'Xuan ', 'Ao ', 'Lian ', 'Man ', 'Zhang ', 'Yin ', null, 'Ying ', 'Zhi ', + 0x90 => 'Lu ', 'Wu ', 'Deng ', 'Xiou ', 'Zeng ', 'Xun ', 'Qu ', 'Dang ', 'Lin ', 'Liao ', 'Qiong ', 'Su ', 'Huang ', 'Gui ', 'Pu ', 'Jing ', + 0xA0 => 'Fan ', 'Jin ', 'Liu ', 'Ji ', null, 'Jing ', 'Ai ', 'Bi ', 'Can ', 'Qu ', 'Zao ', 'Dang ', 'Jiao ', 'Gun ', 'Tan ', 'Hui ', + 0xB0 => 'Huan ', 'Se ', 'Sui ', 'Tian ', null, 'Yu ', 'Jin ', 'Lu ', 'Bin ', 'Shou ', 'Wen ', 'Zui ', 'Lan ', 'Xi ', 'Ji ', 'Xuan ', + 0xC0 => 'Ruan ', 'Huo ', 'Gai ', 'Lei ', 'Du ', 'Li ', 'Zhi ', 'Rou ', 'Li ', 'Zan ', 'Qiong ', 'Zhe ', 'Gui ', 'Sui ', 'La ', 'Long ', + 0xD0 => 'Lu ', 'Li ', 'Zan ', 'Lan ', 'Ying ', 'Mi ', 'Xiang ', 'Xi ', 'Guan ', 'Dao ', 'Zan ', 'Huan ', 'Gua ', 'Bo ', 'Die ', 'Bao ', + 0xE0 => 'Hu ', 'Zhi ', 'Piao ', 'Ban ', 'Rang ', 'Li ', 'Wa ', 'Dekaguramu ', 'Jiang ', 'Qian ', 'Fan ', 'Pen ', 'Fang ', 'Dan ', 'Weng ', 'Ou ', + 0xF0 => 'Deshiguramu ', 'Miriguramu ', 'Thon ', 'Hu ', 'Ling ', 'Yi ', 'Ping ', 'Ci ', 'Hekutogura ', 'Juan ', 'Chang ', 'Chi ', 'Sarake ', 'Dang ', 'Meng ', 'Pou ', +]; diff --git a/resources/transliteration-data/x75.php b/resources/transliteration-data/x75.php new file mode 100644 index 000000000..c4d631f79 --- /dev/null +++ b/resources/transliteration-data/x75.php @@ -0,0 +1,20 @@ + 'Zhui ', 'Ping ', 'Bian ', 'Zhou ', 'Zhen ', 'Senchigura ', 'Ci ', 'Ying ', 'Qi ', 'Xian ', 'Lou ', 'Di ', 'Ou ', 'Meng ', 'Zhuan ', 'Peng ', + 0x10 => 'Lin ', 'Zeng ', 'Wu ', 'Pi ', 'Dan ', 'Weng ', 'Ying ', 'Yan ', 'Gan ', 'Dai ', 'Shen ', 'Tian ', 'Tian ', 'Han ', 'Chang ', 'Sheng ', + 0x20 => 'Qing ', 'Sheng ', 'Chan ', 'Chan ', 'Rui ', 'Sheng ', 'Su ', 'Sen ', 'Yong ', 'Shuai ', 'Lu ', 'Fu ', 'Yong ', 'Beng ', 'Feng ', 'Ning ', + 0x30 => 'Tian ', 'You ', 'Jia ', 'Shen ', 'Zha ', 'Dian ', 'Fu ', 'Nan ', 'Dian ', 'Ping ', 'Ting ', 'Hua ', 'Ting ', 'Quan ', 'Zi ', 'Meng ', + 0x40 => 'Bi ', 'Qi ', 'Liu ', 'Xun ', 'Liu ', 'Chang ', 'Mu ', 'Yun ', 'Fan ', 'Fu ', 'Geng ', 'Tian ', 'Jie ', 'Jie ', 'Quan ', 'Wei ', + 0x50 => 'Fu ', 'Tian ', 'Mu ', 'Tap ', 'Pan ', 'Jiang ', 'Wa ', 'Da ', 'Nan ', 'Liu ', 'Ben ', 'Zhen ', 'Chu ', 'Mu ', 'Mu ', 'Ce ', + 0x60 => 'Cen ', 'Gai ', 'Bi ', 'Da ', 'Zhi ', 'Lue ', 'Qi ', 'Lue ', 'Pan ', 'Kesa ', 'Fan ', 'Hua ', 'Yu ', 'Yu ', 'Mu ', 'Jun ', + 0x70 => 'Yi ', 'Liu ', 'Yu ', 'Die ', 'Chou ', 'Hua ', 'Dang ', 'Chuo ', 'Ji ', 'Wan ', 'Jiang ', 'Sheng ', 'Chang ', 'Tuan ', 'Lei ', 'Ji ', + 0x80 => 'Cha ', 'Liu ', 'Tatamu ', 'Tuan ', 'Lin ', 'Jiang ', 'Jiang ', 'Chou ', 'Bo ', 'Die ', 'Die ', 'Pi ', 'Nie ', 'Dan ', 'Shu ', 'Shu ', + 0x90 => 'Zhi ', 'Yi ', 'Chuang ', 'Nai ', 'Ding ', 'Bi ', 'Jie ', 'Liao ', 'Gong ', 'Ge ', 'Jiu ', 'Zhou ', 'Xia ', 'Shan ', 'Xu ', 'Nue ', + 0xA0 => 'Li ', 'Yang ', 'Chen ', 'You ', 'Ba ', 'Jie ', 'Jue ', 'Zhi ', 'Xia ', 'Cui ', 'Bi ', 'Yi ', 'Li ', 'Zong ', 'Chuang ', 'Feng ', + 0xB0 => 'Zhu ', 'Pao ', 'Pi ', 'Gan ', 'Ke ', 'Ci ', 'Xie ', 'Qi ', 'Dan ', 'Zhen ', 'Fa ', 'Zhi ', 'Teng ', 'Ju ', 'Ji ', 'Fei ', + 0xC0 => 'Qu ', 'Dian ', 'Jia ', 'Xian ', 'Cha ', 'Bing ', 'Ni ', 'Zheng ', 'Yong ', 'Jing ', 'Quan ', 'Chong ', 'Tong ', 'Yi ', 'Kai ', 'Wei ', + 0xD0 => 'Hui ', 'Duo ', 'Yang ', 'Chi ', 'Zhi ', 'Hen ', 'Ya ', 'Mei ', 'Dou ', 'Jing ', 'Xiao ', 'Tong ', 'Tu ', 'Mang ', 'Pi ', 'Xiao ', + 0xE0 => 'Suan ', 'Pu ', 'Li ', 'Zhi ', 'Cuo ', 'Duo ', 'Wu ', 'Sha ', 'Lao ', 'Shou ', 'Huan ', 'Xian ', 'Yi ', 'Peng ', 'Zhang ', 'Guan ', + 0xF0 => 'Tan ', 'Fei ', 'Ma ', 'Lin ', 'Chi ', 'Ji ', 'Dian ', 'An ', 'Chi ', 'Bi ', 'Bei ', 'Min ', 'Gu ', 'Dui ', 'E ', 'Wei ', +]; diff --git a/resources/transliteration-data/x76.php b/resources/transliteration-data/x76.php new file mode 100644 index 000000000..6362f61da --- /dev/null +++ b/resources/transliteration-data/x76.php @@ -0,0 +1,20 @@ + 'Yu ', 'Cui ', 'Ya ', 'Zhu ', 'Cu ', 'Dan ', 'Shen ', 'Zhung ', 'Ji ', 'Yu ', 'Hou ', 'Feng ', 'La ', 'Yang ', 'Shen ', 'Tu ', + 0x10 => 'Yu ', 'Gua ', 'Wen ', 'Huan ', 'Ku ', 'Jia ', 'Yin ', 'Yi ', 'Lu ', 'Sao ', 'Jue ', 'Chi ', 'Xi ', 'Guan ', 'Yi ', 'Wen ', + 0x20 => 'Ji ', 'Chuang ', 'Ban ', 'Lei ', 'Liu ', 'Chai ', 'Shou ', 'Nue ', 'Dian ', 'Da ', 'Pie ', 'Tan ', 'Zhang ', 'Biao ', 'Shen ', 'Cu ', + 0x30 => 'Luo ', 'Yi ', 'Zong ', 'Chou ', 'Zhang ', 'Zhai ', 'Sou ', 'Suo ', 'Que ', 'Diao ', 'Lou ', 'Lu ', 'Mo ', 'Jin ', 'Yin ', 'Ying ', + 0x40 => 'Huang ', 'Fu ', 'Liao ', 'Long ', 'Qiao ', 'Liu ', 'Lao ', 'Xian ', 'Fei ', 'Dan ', 'Yin ', 'He ', 'Yan ', 'Ban ', 'Xian ', 'Guan ', + 0x50 => 'Guai ', 'Nong ', 'Yu ', 'Wei ', 'Yi ', 'Yong ', 'Pi ', 'Lei ', 'Li ', 'Shu ', 'Dan ', 'Lin ', 'Dian ', 'Lin ', 'Lai ', 'Pie ', + 0x60 => 'Ji ', 'Chi ', 'Yang ', 'Xian ', 'Jie ', 'Zheng ', null, 'Li ', 'Huo ', 'Lai ', 'Shaku ', 'Dian ', 'Xian ', 'Ying ', 'Yin ', 'Qu ', + 0x70 => 'Yong ', 'Tan ', 'Dian ', 'Luo ', 'Luan ', 'Luan ', 'Bo ', null, 'Gui ', 'Po ', 'Fa ', 'Deng ', 'Fa ', 'Bai ', 'Bai ', 'Qie ', + 0x80 => 'Bi ', 'Zao ', 'Zao ', 'Mao ', 'De ', 'Pa ', 'Jie ', 'Huang ', 'Gui ', 'Ci ', 'Ling ', 'Gao ', 'Mo ', 'Ji ', 'Jiao ', 'Peng ', + 0x90 => 'Gao ', 'Ai ', 'E ', 'Hao ', 'Han ', 'Bi ', 'Wan ', 'Chou ', 'Qian ', 'Xi ', 'Ai ', 'Jiong ', 'Hao ', 'Huang ', 'Hao ', 'Ze ', + 0xA0 => 'Cui ', 'Hao ', 'Xiao ', 'Ye ', 'Po ', 'Hao ', 'Jiao ', 'Ai ', 'Xing ', 'Huang ', 'Li ', 'Piao ', 'He ', 'Jiao ', 'Pi ', 'Gan ', + 0xB0 => 'Pao ', 'Zhou ', 'Jun ', 'Qiu ', 'Cun ', 'Que ', 'Zha ', 'Gu ', 'Jun ', 'Jun ', 'Zhou ', 'Zha ', 'Gu ', 'Zhan ', 'Du ', 'Min ', + 0xC0 => 'Qi ', 'Ying ', 'Yu ', 'Bei ', 'Zhao ', 'Zhong ', 'Pen ', 'He ', 'Ying ', 'He ', 'Yi ', 'Bo ', 'Wan ', 'He ', 'Ang ', 'Zhan ', + 0xD0 => 'Yan ', 'Jian ', 'He ', 'Yu ', 'Kui ', 'Fan ', 'Gai ', 'Dao ', 'Pan ', 'Fu ', 'Qiu ', 'Sheng ', 'Dao ', 'Lu ', 'Zhan ', 'Meng ', + 0xE0 => 'Li ', 'Jin ', 'Xu ', 'Jian ', 'Pan ', 'Guan ', 'An ', 'Lu ', 'Shu ', 'Zhou ', 'Dang ', 'An ', 'Gu ', 'Li ', 'Mu ', 'Cheng ', + 0xF0 => 'Gan ', 'Xu ', 'Mang ', 'Mang ', 'Zhi ', 'Qi ', 'Ruan ', 'Tian ', 'Xiang ', 'Dun ', 'Xin ', 'Xi ', 'Pan ', 'Feng ', 'Dun ', 'Min ', +]; diff --git a/resources/transliteration-data/x77.php b/resources/transliteration-data/x77.php new file mode 100644 index 000000000..4ed2aa48b --- /dev/null +++ b/resources/transliteration-data/x77.php @@ -0,0 +1,20 @@ + 'Ming ', 'Sheng ', 'Shi ', 'Yun ', 'Mian ', 'Pan ', 'Fang ', 'Miao ', 'Dan ', 'Mei ', 'Mao ', 'Kan ', 'Xian ', 'Ou ', 'Shi ', 'Yang ', + 0x10 => 'Zheng ', 'Yao ', 'Shen ', 'Huo ', 'Da ', 'Zhen ', 'Kuang ', 'Ju ', 'Shen ', 'Chi ', 'Sheng ', 'Mei ', 'Mo ', 'Zhu ', 'Zhen ', 'Zhen ', + 0x20 => 'Mian ', 'Di ', 'Yuan ', 'Die ', 'Yi ', 'Zi ', 'Zi ', 'Chao ', 'Zha ', 'Xuan ', 'Bing ', 'Mi ', 'Long ', 'Sui ', 'Dong ', 'Mi ', + 0x30 => 'Die ', 'Yi ', 'Er ', 'Ming ', 'Xuan ', 'Chi ', 'Kuang ', 'Juan ', 'Mou ', 'Zhen ', 'Tiao ', 'Yang ', 'Yan ', 'Mo ', 'Zhong ', 'Mai ', + 0x40 => 'Zhao ', 'Zheng ', 'Mei ', 'Jun ', 'Shao ', 'Han ', 'Huan ', 'Di ', 'Cheng ', 'Cuo ', 'Juan ', 'E ', 'Wan ', 'Xian ', 'Xi ', 'Kun ', + 0x50 => 'Lai ', 'Jian ', 'Shan ', 'Tian ', 'Hun ', 'Wan ', 'Ling ', 'Shi ', 'Qiong ', 'Lie ', 'Yai ', 'Jing ', 'Zheng ', 'Li ', 'Lai ', 'Sui ', + 0x60 => 'Juan ', 'Shui ', 'Sui ', 'Du ', 'Bi ', 'Bi ', 'Mu ', 'Hun ', 'Ni ', 'Lu ', 'Yi ', 'Jie ', 'Cai ', 'Zhou ', 'Yu ', 'Hun ', + 0x70 => 'Ma ', 'Xia ', 'Xing ', 'Xi ', 'Gun ', 'Cai ', 'Chun ', 'Jian ', 'Mei ', 'Du ', 'Hou ', 'Xuan ', 'Ti ', 'Kui ', 'Gao ', 'Rui ', + 0x80 => 'Mou ', 'Xu ', 'Fa ', 'Wen ', 'Miao ', 'Chou ', 'Kui ', 'Mi ', 'Weng ', 'Kou ', 'Dang ', 'Chen ', 'Ke ', 'Sou ', 'Xia ', 'Qiong ', + 0x90 => 'Mao ', 'Ming ', 'Man ', 'Shui ', 'Ze ', 'Zhang ', 'Yi ', 'Diao ', 'Ou ', 'Mo ', 'Shun ', 'Cong ', 'Lou ', 'Chi ', 'Man ', 'Piao ', + 0xA0 => 'Cheng ', 'Ji ', 'Meng ', null, 'Run ', 'Pie ', 'Xi ', 'Qiao ', 'Pu ', 'Zhu ', 'Deng ', 'Shen ', 'Shun ', 'Liao ', 'Che ', 'Xian ', + 0xB0 => 'Kan ', 'Ye ', 'Xu ', 'Tong ', 'Mou ', 'Lin ', 'Kui ', 'Xian ', 'Ye ', 'Ai ', 'Hui ', 'Zhan ', 'Jian ', 'Gu ', 'Zhao ', 'Qu ', + 0xC0 => 'Wei ', 'Chou ', 'Sao ', 'Ning ', 'Xun ', 'Yao ', 'Huo ', 'Meng ', 'Mian ', 'Bin ', 'Mian ', 'Li ', 'Kuang ', 'Jue ', 'Xuan ', 'Mian ', + 0xD0 => 'Huo ', 'Lu ', 'Meng ', 'Long ', 'Guan ', 'Man ', 'Xi ', 'Chu ', 'Tang ', 'Kan ', 'Zhu ', 'Mao ', 'Jin ', 'Lin ', 'Yu ', 'Shuo ', + 0xE0 => 'Ce ', 'Jue ', 'Shi ', 'Yi ', 'Shen ', 'Zhi ', 'Hou ', 'Shen ', 'Ying ', 'Ju ', 'Zhou ', 'Jiao ', 'Cuo ', 'Duan ', 'Ai ', 'Jiao ', + 0xF0 => 'Zeng ', 'Huo ', 'Bai ', 'Shi ', 'Ding ', 'Qi ', 'Ji ', 'Zi ', 'Gan ', 'Wu ', 'Tuo ', 'Ku ', 'Qiang ', 'Xi ', 'Fan ', 'Kuang ', +]; diff --git a/resources/transliteration-data/x78.php b/resources/transliteration-data/x78.php new file mode 100644 index 000000000..adfedfc64 --- /dev/null +++ b/resources/transliteration-data/x78.php @@ -0,0 +1,20 @@ + 'Dang ', 'Ma ', 'Sha ', 'Dan ', 'Jue ', 'Li ', 'Fu ', 'Min ', 'Nuo ', 'Huo ', 'Kang ', 'Zhi ', 'Qi ', 'Kan ', 'Jie ', 'Fen ', + 0x10 => 'E ', 'Ya ', 'Pi ', 'Zhe ', 'Yan ', 'Sui ', 'Zhuan ', 'Che ', 'Dun ', 'Pan ', 'Yan ', null, 'Feng ', 'Fa ', 'Mo ', 'Zha ', + 0x20 => 'Qu ', 'Yu ', 'Luo ', 'Tuo ', 'Tuo ', 'Di ', 'Zhai ', 'Zhen ', 'Ai ', 'Fei ', 'Mu ', 'Zhu ', 'Li ', 'Bian ', 'Nu ', 'Ping ', + 0x30 => 'Peng ', 'Ling ', 'Pao ', 'Le ', 'Po ', 'Bo ', 'Po ', 'Shen ', 'Za ', 'Nuo ', 'Li ', 'Long ', 'Tong ', null, 'Li ', 'Aragane ', + 0x40 => 'Chu ', 'Keng ', 'Quan ', 'Zhu ', 'Kuang ', 'Huo ', 'E ', 'Nao ', 'Jia ', 'Lu ', 'Wei ', 'Ai ', 'Luo ', 'Ken ', 'Xing ', 'Yan ', + 0x50 => 'Tong ', 'Peng ', 'Xi ', null, 'Hong ', 'Shuo ', 'Xia ', 'Qiao ', null, 'Wei ', 'Qiao ', null, 'Keng ', 'Xiao ', 'Que ', 'Chan ', + 0x60 => 'Lang ', 'Hong ', 'Yu ', 'Xiao ', 'Xia ', 'Mang ', 'Long ', 'Iong ', 'Che ', 'Che ', 'E ', 'Liu ', 'Ying ', 'Mang ', 'Que ', 'Yan ', + 0x70 => 'Sha ', 'Kun ', 'Yu ', null, 'Kaki ', 'Lu ', 'Chen ', 'Jian ', 'Nue ', 'Song ', 'Zhuo ', 'Keng ', 'Peng ', 'Yan ', 'Zhui ', 'Kong ', + 0x80 => 'Ceng ', 'Qi ', 'Zong ', 'Qing ', 'Lin ', 'Jun ', 'Bo ', 'Ding ', 'Min ', 'Diao ', 'Jian ', 'He ', 'Lu ', 'Ai ', 'Sui ', 'Que ', + 0x90 => 'Ling ', 'Bei ', 'Yin ', 'Dui ', 'Wu ', 'Qi ', 'Lun ', 'Wan ', 'Dian ', 'Gang ', 'Pei ', 'Qi ', 'Chen ', 'Ruan ', 'Yan ', 'Die ', + 0xA0 => 'Ding ', 'Du ', 'Tuo ', 'Jie ', 'Ying ', 'Bian ', 'Ke ', 'Bi ', 'Wei ', 'Shuo ', 'Zhen ', 'Duan ', 'Xia ', 'Dang ', 'Ti ', 'Nao ', + 0xB0 => 'Peng ', 'Jian ', 'Di ', 'Tan ', 'Cha ', 'Seki ', 'Qi ', null, 'Feng ', 'Xuan ', 'Que ', 'Que ', 'Ma ', 'Gong ', 'Nian ', 'Su ', + 0xC0 => 'E ', 'Ci ', 'Liu ', 'Si ', 'Tang ', 'Bang ', 'Hua ', 'Pi ', 'Wei ', 'Sang ', 'Lei ', 'Cuo ', 'Zhen ', 'Xia ', 'Qi ', 'Lian ', + 0xD0 => 'Pan ', 'Wei ', 'Yun ', 'Dui ', 'Zhe ', 'Ke ', 'La ', null, 'Qing ', 'Gun ', 'Zhuan ', 'Chan ', 'Qi ', 'Ao ', 'Peng ', 'Lu ', + 0xE0 => 'Lu ', 'Kan ', 'Qiang ', 'Chen ', 'Yin ', 'Lei ', 'Biao ', 'Qi ', 'Mo ', 'Qi ', 'Cui ', 'Zong ', 'Qing ', 'Chuo ', null, 'Ji ', + 0xF0 => 'Shan ', 'Lao ', 'Qu ', 'Zeng ', 'Deng ', 'Jian ', 'Xi ', 'Lin ', 'Ding ', 'Dian ', 'Huang ', 'Pan ', 'Za ', 'Qiao ', 'Di ', 'Li ', +]; diff --git a/resources/transliteration-data/x79.php b/resources/transliteration-data/x79.php new file mode 100644 index 000000000..418c0bff9 --- /dev/null +++ b/resources/transliteration-data/x79.php @@ -0,0 +1,20 @@ + 'Tani ', 'Jiao ', null, 'Zhang ', 'Qiao ', 'Dun ', 'Xian ', 'Yu ', 'Zhui ', 'He ', 'Huo ', 'Zhai ', 'Lei ', 'Ke ', 'Chu ', 'Ji ', + 0x10 => 'Que ', 'Dang ', 'Yi ', 'Jiang ', 'Pi ', 'Pi ', 'Yu ', 'Pin ', 'Qi ', 'Ai ', 'Kai ', 'Jian ', 'Yu ', 'Ruan ', 'Meng ', 'Pao ', + 0x20 => 'Ci ', null, null, 'Mie ', 'Ca ', 'Xian ', 'Kuang ', 'Lei ', 'Lei ', 'Zhi ', 'Li ', 'Li ', 'Fan ', 'Que ', 'Pao ', 'Ying ', + 0x30 => 'Li ', 'Long ', 'Long ', 'Mo ', 'Bo ', 'Shuang ', 'Guan ', 'Lan ', 'Zan ', 'Yan ', 'Shi ', 'Shi ', 'Li ', 'Reng ', 'She ', 'Yue ', + 0x40 => 'Si ', 'Qi ', 'Ta ', 'Ma ', 'Xie ', 'Xian ', 'Xian ', 'Zhi ', 'Qi ', 'Zhi ', 'Beng ', 'Dui ', 'Zhong ', null, 'Yi ', 'Shi ', + 0x50 => 'You ', 'Zhi ', 'Tiao ', 'Fu ', 'Fu ', 'Mi ', 'Zu ', 'Zhi ', 'Suan ', 'Mei ', 'Zuo ', 'Qu ', 'Hu ', 'Zhu ', 'Shen ', 'Sui ', + 0x60 => 'Ci ', 'Chai ', 'Mi ', 'Lu ', 'Yu ', 'Xiang ', 'Wu ', 'Tiao ', 'Piao ', 'Zhu ', 'Gui ', 'Xia ', 'Zhi ', 'Ji ', 'Gao ', 'Zhen ', + 0x70 => 'Gao ', 'Shui ', 'Jin ', 'Chen ', 'Gai ', 'Kun ', 'Di ', 'Dao ', 'Huo ', 'Tao ', 'Qi ', 'Gu ', 'Guan ', 'Zui ', 'Ling ', 'Lu ', + 0x80 => 'Bing ', 'Jin ', 'Dao ', 'Zhi ', 'Lu ', 'Shan ', 'Bei ', 'Zhe ', 'Hui ', 'You ', 'Xi ', 'Yin ', 'Zi ', 'Huo ', 'Zhen ', 'Fu ', + 0x90 => 'Yuan ', 'Wu ', 'Xian ', 'Yang ', 'Ti ', 'Yi ', 'Mei ', 'Si ', 'Di ', null, 'Zhuo ', 'Zhen ', 'Yong ', 'Ji ', 'Gao ', 'Tang ', + 0xA0 => 'Si ', 'Ma ', 'Ta ', null, 'Xuan ', 'Qi ', 'Yu ', 'Xi ', 'Ji ', 'Si ', 'Chan ', 'Tan ', 'Kuai ', 'Sui ', 'Li ', 'Nong ', + 0xB0 => 'Ni ', 'Dao ', 'Li ', 'Rang ', 'Yue ', 'Ti ', 'Zan ', 'Lei ', 'Rou ', 'Yu ', 'Yu ', 'Chi ', 'Xie ', 'Qin ', 'He ', 'Tu ', + 0xC0 => 'Xiu ', 'Si ', 'Ren ', 'Tu ', 'Zi ', 'Cha ', 'Gan ', 'Yi ', 'Xian ', 'Bing ', 'Nian ', 'Qiu ', 'Qiu ', 'Chong ', 'Fen ', 'Hao ', + 0xD0 => 'Yun ', 'Ke ', 'Miao ', 'Zhi ', 'Geng ', 'Bi ', 'Zhi ', 'Yu ', 'Mi ', 'Ku ', 'Ban ', 'Pi ', 'Ni ', 'Li ', 'You ', 'Zu ', + 0xE0 => 'Pi ', 'Ba ', 'Ling ', 'Mo ', 'Cheng ', 'Nian ', 'Qin ', 'Yang ', 'Zuo ', 'Zhi ', 'Zhi ', 'Shu ', 'Ju ', 'Zi ', 'Huo ', 'Ji ', + 0xF0 => 'Cheng ', 'Tong ', 'Zhi ', 'Huo ', 'He ', 'Yin ', 'Zi ', 'Zhi ', 'Jie ', 'Ren ', 'Du ', 'Yi ', 'Zhu ', 'Hui ', 'Nong ', 'Fu ', +]; diff --git a/resources/transliteration-data/x7a.php b/resources/transliteration-data/x7a.php new file mode 100644 index 000000000..4f791931f --- /dev/null +++ b/resources/transliteration-data/x7a.php @@ -0,0 +1,20 @@ + 'Xi ', 'Kao ', 'Lang ', 'Fu ', 'Ze ', 'Shui ', 'Lu ', 'Kun ', 'Gan ', 'Geng ', 'Ti ', 'Cheng ', 'Tu ', 'Shao ', 'Shui ', 'Ya ', + 0x10 => 'Lun ', 'Lu ', 'Gu ', 'Zuo ', 'Ren ', 'Zhun ', 'Bang ', 'Bai ', 'Ji ', 'Zhi ', 'Zhi ', 'Kun ', 'Leng ', 'Peng ', 'Ke ', 'Bing ', + 0x20 => 'Chou ', 'Zu ', 'Yu ', 'Su ', 'Lue ', null, 'Yi ', 'Xi ', 'Bian ', 'Ji ', 'Fu ', 'Bi ', 'Nuo ', 'Jie ', 'Zhong ', 'Zong ', + 0x30 => 'Xu ', 'Cheng ', 'Dao ', 'Wen ', 'Lian ', 'Zi ', 'Yu ', 'Ji ', 'Xu ', 'Zhen ', 'Zhi ', 'Dao ', 'Jia ', 'Ji ', 'Gao ', 'Gao ', + 0x40 => 'Gu ', 'Rong ', 'Sui ', 'You ', 'Ji ', 'Kang ', 'Mu ', 'Shan ', 'Men ', 'Zhi ', 'Ji ', 'Lu ', 'Su ', 'Ji ', 'Ying ', 'Wen ', + 0x50 => 'Qiu ', 'Se ', null, 'Yi ', 'Huang ', 'Qie ', 'Ji ', 'Sui ', 'Xiao ', 'Pu ', 'Jiao ', 'Zhuo ', 'Tong ', 'Sai ', 'Lu ', 'Sui ', + 0x60 => 'Nong ', 'Se ', 'Hui ', 'Rang ', 'Nuo ', 'Yu ', 'Bin ', 'Ji ', 'Tui ', 'Wen ', 'Cheng ', 'Huo ', 'Gong ', 'Lu ', 'Biao ', null, + 0x70 => 'Rang ', 'Zhuo ', 'Li ', 'Zan ', 'Xue ', 'Wa ', 'Jiu ', 'Qiong ', 'Xi ', 'Qiong ', 'Kong ', 'Yu ', 'Sen ', 'Jing ', 'Yao ', 'Chuan ', + 0x80 => 'Zhun ', 'Tu ', 'Lao ', 'Qie ', 'Zhai ', 'Yao ', 'Bian ', 'Bao ', 'Yao ', 'Bing ', 'Wa ', 'Zhu ', 'Jiao ', 'Qiao ', 'Diao ', 'Wu ', + 0x90 => 'Gui ', 'Yao ', 'Zhi ', 'Chuang ', 'Yao ', 'Tiao ', 'Jiao ', 'Chuang ', 'Jiong ', 'Xiao ', 'Cheng ', 'Kou ', 'Cuan ', 'Wo ', 'Dan ', 'Ku ', + 0xA0 => 'Ke ', 'Zhui ', 'Xu ', 'Su ', 'Guan ', 'Kui ', 'Dou ', null, 'Yin ', 'Wo ', 'Wa ', 'Ya ', 'Yu ', 'Ju ', 'Qiong ', 'Yao ', + 0xB0 => 'Yao ', 'Tiao ', 'Chao ', 'Yu ', 'Tian ', 'Diao ', 'Ju ', 'Liao ', 'Xi ', 'Wu ', 'Kui ', 'Chuang ', 'Zhao ', null, 'Kuan ', 'Long ', + 0xC0 => 'Cheng ', 'Cui ', 'Piao ', 'Zao ', 'Cuan ', 'Qiao ', 'Qiong ', 'Dou ', 'Zao ', 'Long ', 'Qie ', 'Li ', 'Chu ', 'Shi ', 'Fou ', 'Qian ', + 0xD0 => 'Chu ', 'Hong ', 'Qi ', 'Qian ', 'Gong ', 'Shi ', 'Shu ', 'Miao ', 'Ju ', 'Zhan ', 'Zhu ', 'Ling ', 'Long ', 'Bing ', 'Jing ', 'Jing ', + 0xE0 => 'Zhang ', 'Yi ', 'Si ', 'Jun ', 'Hong ', 'Tong ', 'Song ', 'Jing ', 'Diao ', 'Yi ', 'Shu ', 'Jing ', 'Qu ', 'Jie ', 'Ping ', 'Duan ', + 0xF0 => 'Shao ', 'Zhuan ', 'Ceng ', 'Deng ', 'Cui ', 'Huai ', 'Jing ', 'Kan ', 'Jing ', 'Zhu ', 'Zhu ', 'Le ', 'Peng ', 'Yu ', 'Chi ', 'Gan ', +]; diff --git a/resources/transliteration-data/x7b.php b/resources/transliteration-data/x7b.php new file mode 100644 index 000000000..cd1fc7f7b --- /dev/null +++ b/resources/transliteration-data/x7b.php @@ -0,0 +1,20 @@ + 'Mang ', 'Zhu ', 'Utsubo ', 'Du ', 'Ji ', 'Xiao ', 'Ba ', 'Suan ', 'Ji ', 'Zhen ', 'Zhao ', 'Sun ', 'Ya ', 'Zhui ', 'Yuan ', 'Hu ', + 0x10 => 'Gang ', 'Xiao ', 'Cen ', 'Pi ', 'Bi ', 'Jian ', 'Yi ', 'Dong ', 'Shan ', 'Sheng ', 'Xia ', 'Di ', 'Zhu ', 'Na ', 'Chi ', 'Gu ', + 0x20 => 'Li ', 'Qie ', 'Min ', 'Bao ', 'Tiao ', 'Si ', 'Fu ', 'Ce ', 'Ben ', 'Pei ', 'Da ', 'Zi ', 'Di ', 'Ling ', 'Ze ', 'Nu ', + 0x30 => 'Fu ', 'Gou ', 'Fan ', 'Jia ', 'Ge ', 'Fan ', 'Shi ', 'Mao ', 'Po ', 'Sey ', 'Jian ', 'Qiong ', 'Long ', 'Souke ', 'Bian ', 'Luo ', + 0x40 => 'Gui ', 'Qu ', 'Chi ', 'Yin ', 'Yao ', 'Xian ', 'Bi ', 'Qiong ', 'Gua ', 'Deng ', 'Jiao ', 'Jin ', 'Quan ', 'Sun ', 'Ru ', 'Fa ', + 0x50 => 'Kuang ', 'Zhu ', 'Tong ', 'Ji ', 'Da ', 'Xing ', 'Ce ', 'Zhong ', 'Kou ', 'Lai ', 'Bi ', 'Shai ', 'Dang ', 'Zheng ', 'Ce ', 'Fu ', + 0x60 => 'Yun ', 'Tu ', 'Pa ', 'Li ', 'Lang ', 'Ju ', 'Guan ', 'Jian ', 'Han ', 'Tong ', 'Xia ', 'Zhi ', 'Cheng ', 'Suan ', 'Shi ', 'Zhu ', + 0x70 => 'Zuo ', 'Xiao ', 'Shao ', 'Ting ', 'Ce ', 'Yan ', 'Gao ', 'Kuai ', 'Gan ', 'Chou ', 'Kago ', 'Gang ', 'Yun ', 'O ', 'Qian ', 'Xiao ', + 0x80 => 'Jian ', 'Pu ', 'Lai ', 'Zou ', 'Bi ', 'Bi ', 'Bi ', 'Ge ', 'Chi ', 'Guai ', 'Yu ', 'Jian ', 'Zhao ', 'Gu ', 'Chi ', 'Zheng ', + 0x90 => 'Jing ', 'Sha ', 'Zhou ', 'Lu ', 'Bo ', 'Ji ', 'Lin ', 'Suan ', 'Jun ', 'Fu ', 'Zha ', 'Gu ', 'Kong ', 'Qian ', 'Quan ', 'Jun ', + 0xA0 => 'Chui ', 'Guan ', 'Yuan ', 'Ce ', 'Ju ', 'Bo ', 'Ze ', 'Qie ', 'Tuo ', 'Luo ', 'Dan ', 'Xiao ', 'Ruo ', 'Jian ', 'Xuan ', 'Bian ', + 0xB0 => 'Sun ', 'Xiang ', 'Xian ', 'Ping ', 'Zhen ', 'Sheng ', 'Hu ', 'Shi ', 'Zhu ', 'Yue ', 'Chun ', 'Lu ', 'Wu ', 'Dong ', 'Xiao ', 'Ji ', + 0xC0 => 'Jie ', 'Huang ', 'Xing ', 'Mei ', 'Fan ', 'Chui ', 'Zhuan ', 'Pian ', 'Feng ', 'Zhu ', 'Hong ', 'Qie ', 'Hou ', 'Qiu ', 'Miao ', 'Qian ', + 0xD0 => null, 'Kui ', 'Sik ', 'Lou ', 'Yun ', 'He ', 'Tang ', 'Yue ', 'Chou ', 'Gao ', 'Fei ', 'Ruo ', 'Zheng ', 'Gou ', 'Nie ', 'Qian ', + 0xE0 => 'Xiao ', 'Cuan ', 'Gong ', 'Pang ', 'Du ', 'Li ', 'Bi ', 'Zhuo ', 'Chu ', 'Shai ', 'Chi ', 'Zhu ', 'Qiang ', 'Long ', 'Lan ', 'Jian ', + 0xF0 => 'Bu ', 'Li ', 'Hui ', 'Bi ', 'Di ', 'Cong ', 'Yan ', 'Peng ', 'Sen ', 'Zhuan ', 'Pai ', 'Piao ', 'Dou ', 'Yu ', 'Mie ', 'Zhuan ', +]; diff --git a/resources/transliteration-data/x7c.php b/resources/transliteration-data/x7c.php new file mode 100644 index 000000000..04ce0c06e --- /dev/null +++ b/resources/transliteration-data/x7c.php @@ -0,0 +1,20 @@ + 'Ze ', 'Xi ', 'Guo ', 'Yi ', 'Hu ', 'Chan ', 'Kou ', 'Cu ', 'Ping ', 'Chou ', 'Ji ', 'Gui ', 'Su ', 'Lou ', 'Zha ', 'Lu ', + 0x10 => 'Nian ', 'Suo ', 'Cuan ', 'Sasara ', 'Suo ', 'Le ', 'Duan ', 'Yana ', 'Xiao ', 'Bo ', 'Mi ', 'Si ', 'Dang ', 'Liao ', 'Dan ', 'Dian ', + 0x20 => 'Fu ', 'Jian ', 'Min ', 'Kui ', 'Dai ', 'Qiao ', 'Deng ', 'Huang ', 'Sun ', 'Lao ', 'Zan ', 'Xiao ', 'Du ', 'Shi ', 'Zan ', null, + 0x30 => 'Pai ', 'Hata ', 'Pai ', 'Gan ', 'Ju ', 'Du ', 'Lu ', 'Yan ', 'Bo ', 'Dang ', 'Sai ', 'Ke ', 'Long ', 'Qian ', 'Lian ', 'Bo ', + 0x40 => 'Zhou ', 'Lai ', null, 'Lan ', 'Kui ', 'Yu ', 'Yue ', 'Hao ', 'Zhen ', 'Tai ', 'Ti ', 'Mi ', 'Chou ', 'Ji ', null, 'Hata ', + 0x50 => 'Teng ', 'Zhuan ', 'Zhou ', 'Fan ', 'Sou ', 'Zhou ', 'Kuji ', 'Zhuo ', 'Teng ', 'Lu ', 'Lu ', 'Jian ', 'Tuo ', 'Ying ', 'Yu ', 'Lai ', + 0x60 => 'Long ', 'Shinshi ', 'Lian ', 'Lan ', 'Qian ', 'Yue ', 'Zhong ', 'Qu ', 'Lian ', 'Bian ', 'Duan ', 'Zuan ', 'Li ', 'Si ', 'Luo ', 'Ying ', + 0x70 => 'Yue ', 'Zhuo ', 'Xu ', 'Mi ', 'Di ', 'Fan ', 'Shen ', 'Zhe ', 'Shen ', 'Nu ', 'Xie ', 'Lei ', 'Xian ', 'Zi ', 'Ni ', 'Cun ', + 0x80 => null, 'Qian ', 'Kume ', 'Bi ', 'Ban ', 'Wu ', 'Sha ', 'Kang ', 'Rou ', 'Fen ', 'Bi ', 'Cui ', null, 'Li ', 'Chi ', 'Nukamiso ', + 0x90 => 'Ro ', 'Ba ', 'Li ', 'Gan ', 'Ju ', 'Po ', 'Mo ', 'Cu ', 'Nian ', 'Zhou ', 'Li ', 'Su ', 'Tiao ', 'Li ', 'Qi ', 'Su ', + 0xA0 => 'Hong ', 'Tong ', 'Zi ', 'Ce ', 'Yue ', 'Zhou ', 'Lin ', 'Zhuang ', 'Bai ', null, 'Fen ', 'Ji ', null, 'Sukumo ', 'Liang ', 'Xian ', + 0xB0 => 'Fu ', 'Liang ', 'Can ', 'Geng ', 'Li ', 'Yue ', 'Lu ', 'Ju ', 'Qi ', 'Cui ', 'Bai ', 'Zhang ', 'Lin ', 'Zong ', 'Jing ', 'Guo ', + 0xC0 => 'Kouji ', 'San ', 'San ', 'Tang ', 'Bian ', 'Rou ', 'Mian ', 'Hou ', 'Xu ', 'Zong ', 'Hu ', 'Jian ', 'Zan ', 'Ci ', 'Li ', 'Xie ', + 0xD0 => 'Fu ', 'Ni ', 'Bei ', 'Gu ', 'Xiu ', 'Gao ', 'Tang ', 'Qiu ', 'Sukumo ', 'Cao ', 'Zhuang ', 'Tang ', 'Mi ', 'San ', 'Fen ', 'Zao ', + 0xE0 => 'Kang ', 'Jiang ', 'Mo ', 'San ', 'San ', 'Nuo ', 'Xi ', 'Liang ', 'Jiang ', 'Kuai ', 'Bo ', 'Huan ', null, 'Zong ', 'Xian ', 'Nuo ', + 0xF0 => 'Tuan ', 'Nie ', 'Li ', 'Zuo ', 'Di ', 'Nie ', 'Tiao ', 'Lan ', 'Mi ', 'Jiao ', 'Jiu ', 'Xi ', 'Gong ', 'Zheng ', 'Jiu ', 'You ', +]; diff --git a/resources/transliteration-data/x7d.php b/resources/transliteration-data/x7d.php new file mode 100644 index 000000000..f2363a06a --- /dev/null +++ b/resources/transliteration-data/x7d.php @@ -0,0 +1,20 @@ + 'Ji ', 'Cha ', 'Zhou ', 'Xun ', 'Yue ', 'Hong ', 'Yu ', 'He ', 'Wan ', 'Ren ', 'Wen ', 'Wen ', 'Qiu ', 'Na ', 'Zi ', 'Tou ', + 0x10 => 'Niu ', 'Fou ', 'Jie ', 'Shu ', 'Chun ', 'Pi ', 'Yin ', 'Sha ', 'Hong ', 'Zhi ', 'Ji ', 'Fen ', 'Yun ', 'Ren ', 'Dan ', 'Jin ', + 0x20 => 'Su ', 'Fang ', 'Suo ', 'Cui ', 'Jiu ', 'Zha ', 'Kinu ', 'Jin ', 'Fu ', 'Zhi ', 'Ci ', 'Zi ', 'Chou ', 'Hong ', 'Zha ', 'Lei ', + 0x30 => 'Xi ', 'Fu ', 'Xie ', 'Shen ', 'Bei ', 'Zhu ', 'Qu ', 'Ling ', 'Zhu ', 'Shao ', 'Gan ', 'Yang ', 'Fu ', 'Tuo ', 'Zhen ', 'Dai ', + 0x40 => 'Zhuo ', 'Shi ', 'Zhong ', 'Xian ', 'Zu ', 'Jiong ', 'Ban ', 'Ju ', 'Mo ', 'Shu ', 'Zui ', 'Wata ', 'Jing ', 'Ren ', 'Heng ', 'Xie ', + 0x50 => 'Jie ', 'Zhu ', 'Chou ', 'Gua ', 'Bai ', 'Jue ', 'Kuang ', 'Hu ', 'Ci ', 'Geng ', 'Geng ', 'Tao ', 'Xie ', 'Ku ', 'Jiao ', 'Quan ', + 0x60 => 'Gai ', 'Luo ', 'Xuan ', 'Bing ', 'Xian ', 'Fu ', 'Gei ', 'Tong ', 'Rong ', 'Tiao ', 'Yin ', 'Lei ', 'Xie ', 'Quan ', 'Xu ', 'Lun ', + 0x70 => 'Die ', 'Tong ', 'Si ', 'Jiang ', 'Xiang ', 'Hui ', 'Jue ', 'Zhi ', 'Jian ', 'Juan ', 'Chi ', 'Mian ', 'Zhen ', 'Lu ', 'Cheng ', 'Qiu ', + 0x80 => 'Shu ', 'Bang ', 'Tong ', 'Xiao ', 'Wan ', 'Qin ', 'Geng ', 'Xiu ', 'Ti ', 'Xiu ', 'Xie ', 'Hong ', 'Xi ', 'Fu ', 'Ting ', 'Sui ', + 0x90 => 'Dui ', 'Kun ', 'Fu ', 'Jing ', 'Hu ', 'Zhi ', 'Yan ', 'Jiong ', 'Feng ', 'Ji ', 'Sok ', 'Kase ', 'Zong ', 'Lin ', 'Duo ', 'Li ', + 0xA0 => 'Lu ', 'Liang ', 'Chou ', 'Quan ', 'Shao ', 'Qi ', 'Qi ', 'Zhun ', 'Qi ', 'Wan ', 'Qian ', 'Xian ', 'Shou ', 'Wei ', 'Qi ', 'Tao ', + 0xB0 => 'Wan ', 'Gang ', 'Wang ', 'Beng ', 'Zhui ', 'Cai ', 'Guo ', 'Cui ', 'Lun ', 'Liu ', 'Qi ', 'Zhan ', 'Bei ', 'Chuo ', 'Ling ', 'Mian ', + 0xC0 => 'Qi ', 'Qie ', 'Tan ', 'Zong ', 'Gun ', 'Zou ', 'Yi ', 'Zi ', 'Xing ', 'Liang ', 'Jin ', 'Fei ', 'Rui ', 'Min ', 'Yu ', 'Zong ', + 0xD0 => 'Fan ', 'Lu ', 'Xu ', 'Yingl ', 'Zhang ', 'Kasuri ', 'Xu ', 'Xiang ', 'Jian ', 'Ke ', 'Xian ', 'Ruan ', 'Mian ', 'Qi ', 'Duan ', 'Zhong ', + 0xE0 => 'Di ', 'Min ', 'Miao ', 'Yuan ', 'Xie ', 'Bao ', 'Si ', 'Qiu ', 'Bian ', 'Huan ', 'Geng ', 'Cong ', 'Mian ', 'Wei ', 'Fu ', 'Wei ', + 0xF0 => 'Yu ', 'Gou ', 'Miao ', 'Xie ', 'Lian ', 'Zong ', 'Bian ', 'Yun ', 'Yin ', 'Ti ', 'Gua ', 'Zhi ', 'Yun ', 'Cheng ', 'Chan ', 'Dai ', +]; diff --git a/resources/transliteration-data/x7e.php b/resources/transliteration-data/x7e.php new file mode 100644 index 000000000..d9e4d04e7 --- /dev/null +++ b/resources/transliteration-data/x7e.php @@ -0,0 +1,20 @@ + 'Xia ', 'Yuan ', 'Zong ', 'Xu ', 'Nawa ', 'Odoshi ', 'Geng ', 'Sen ', 'Ying ', 'Jin ', 'Yi ', 'Zhui ', 'Ni ', 'Bang ', 'Gu ', 'Pan ', + 0x10 => 'Zhou ', 'Jian ', 'Cuo ', 'Quan ', 'Shuang ', 'Yun ', 'Xia ', 'Shuai ', 'Xi ', 'Rong ', 'Tao ', 'Fu ', 'Yun ', 'Zhen ', 'Gao ', 'Ru ', + 0x20 => 'Hu ', 'Zai ', 'Teng ', 'Xian ', 'Su ', 'Zhen ', 'Zong ', 'Tao ', 'Horo ', 'Cai ', 'Bi ', 'Feng ', 'Cu ', 'Li ', 'Suo ', 'Yin ', + 0x30 => 'Xi ', 'Zong ', 'Lei ', 'Zhuan ', 'Qian ', 'Man ', 'Zhi ', 'Lu ', 'Mo ', 'Piao ', 'Lian ', 'Mi ', 'Xuan ', 'Zong ', 'Ji ', 'Shan ', + 0x40 => 'Sui ', 'Fan ', 'Shuai ', 'Beng ', 'Yi ', 'Sao ', 'Mou ', 'Zhou ', 'Qiang ', 'Hun ', 'Sem ', 'Xi ', 'Jung ', 'Xiu ', 'Ran ', 'Xuan ', + 0x50 => 'Hui ', 'Qiao ', 'Zeng ', 'Zuo ', 'Zhi ', 'Shan ', 'San ', 'Lin ', 'Yu ', 'Fan ', 'Liao ', 'Chuo ', 'Zun ', 'Jian ', 'Rao ', 'Chan ', + 0x60 => 'Rui ', 'Xiu ', 'Hui ', 'Hua ', 'Zuan ', 'Xi ', 'Qiang ', 'Un ', 'Da ', 'Sheng ', 'Hui ', 'Xi ', 'Se ', 'Jian ', 'Jiang ', 'Huan ', + 0x70 => 'Zao ', 'Cong ', 'Jie ', 'Jiao ', 'Bo ', 'Chan ', 'Yi ', 'Nao ', 'Sui ', 'Yi ', 'Shai ', 'Xu ', 'Ji ', 'Bin ', 'Qian ', 'Lan ', + 0x80 => 'Pu ', 'Xun ', 'Zuan ', 'Qi ', 'Peng ', 'Li ', 'Mo ', 'Lei ', 'Xie ', 'Zuan ', 'Kuang ', 'You ', 'Xu ', 'Lei ', 'Xian ', 'Chan ', + 0x90 => 'Kou ', 'Lu ', 'Chan ', 'Ying ', 'Cai ', 'Xiang ', 'Xian ', 'Zui ', 'Zuan ', 'Luo ', 'Xi ', 'Dao ', 'Lan ', 'Lei ', 'Lian ', 'Si ', + 0xA0 => 'Jiu ', 'Yu ', 'Hong ', 'Zhou ', 'Xian ', 'He ', 'Yue ', 'Ji ', 'Wan ', 'Kuang ', 'Ji ', 'Ren ', 'Wei ', 'Yun ', 'Hong ', 'Chun ', + 0xB0 => 'Pi ', 'Sha ', 'Gang ', 'Na ', 'Ren ', 'Zong ', 'Lun ', 'Fen ', 'Zhi ', 'Wen ', 'Fang ', 'Zhu ', 'Yin ', 'Niu ', 'Shu ', 'Xian ', + 0xC0 => 'Gan ', 'Xie ', 'Fu ', 'Lian ', 'Zu ', 'Shen ', 'Xi ', 'Zhi ', 'Zhong ', 'Zhou ', 'Ban ', 'Fu ', 'Zhuo ', 'Shao ', 'Yi ', 'Jing ', + 0xD0 => 'Dai ', 'Bang ', 'Rong ', 'Jie ', 'Ku ', 'Rao ', 'Die ', 'Heng ', 'Hui ', 'Gei ', 'Xuan ', 'Jiang ', 'Luo ', 'Jue ', 'Jiao ', 'Tong ', + 0xE0 => 'Geng ', 'Xiao ', 'Juan ', 'Xiu ', 'Xi ', 'Sui ', 'Tao ', 'Ji ', 'Ti ', 'Ji ', 'Xu ', 'Ling ', null, 'Xu ', 'Qi ', 'Fei ', + 0xF0 => 'Chuo ', 'Zhang ', 'Gun ', 'Sheng ', 'Wei ', 'Mian ', 'Shou ', 'Beng ', 'Chou ', 'Tao ', 'Liu ', 'Quan ', 'Zong ', 'Zhan ', 'Wan ', 'Lu ', +]; diff --git a/resources/transliteration-data/x7f.php b/resources/transliteration-data/x7f.php new file mode 100644 index 000000000..a7dee654c --- /dev/null +++ b/resources/transliteration-data/x7f.php @@ -0,0 +1,20 @@ + 'Zhui ', 'Zi ', 'Ke ', 'Xiang ', 'Jian ', 'Mian ', 'Lan ', 'Ti ', 'Miao ', 'Qi ', 'Yun ', 'Hui ', 'Si ', 'Duo ', 'Duan ', 'Bian ', + 0x10 => 'Xian ', 'Gou ', 'Zhui ', 'Huan ', 'Di ', 'Lu ', 'Bian ', 'Min ', 'Yuan ', 'Jin ', 'Fu ', 'Ru ', 'Zhen ', 'Feng ', 'Shuai ', 'Gao ', + 0x20 => 'Chan ', 'Li ', 'Yi ', 'Jian ', 'Bin ', 'Piao ', 'Man ', 'Lei ', 'Ying ', 'Suo ', 'Mou ', 'Sao ', 'Xie ', 'Liao ', 'Shan ', 'Zeng ', + 0x30 => 'Jiang ', 'Qian ', 'Zao ', 'Huan ', 'Jiao ', 'Zuan ', 'Fou ', 'Xie ', 'Gang ', 'Fou ', 'Que ', 'Fou ', 'Kaakeru ', 'Bo ', 'Ping ', 'Hou ', + 0x40 => null, 'Gang ', 'Ying ', 'Ying ', 'Qing ', 'Xia ', 'Guan ', 'Zun ', 'Tan ', 'Chang ', 'Qi ', 'Weng ', 'Ying ', 'Lei ', 'Tan ', 'Lu ', + 0x50 => 'Guan ', 'Wang ', 'Wang ', 'Gang ', 'Wang ', 'Han ', null, 'Luo ', 'Fu ', 'Mi ', 'Fa ', 'Gu ', 'Zhu ', 'Ju ', 'Mao ', 'Gu ', + 0x60 => 'Min ', 'Gang ', 'Ba ', 'Gua ', 'Ti ', 'Juan ', 'Fu ', 'Lin ', 'Yan ', 'Zhao ', 'Zui ', 'Gua ', 'Zhuo ', 'Yu ', 'Zhi ', 'An ', + 0x70 => 'Fa ', 'Nan ', 'Shu ', 'Si ', 'Pi ', 'Ma ', 'Liu ', 'Ba ', 'Fa ', 'Li ', 'Chao ', 'Wei ', 'Bi ', 'Ji ', 'Zeng ', 'Tong ', + 0x80 => 'Liu ', 'Ji ', 'Juan ', 'Mi ', 'Zhao ', 'Luo ', 'Pi ', 'Ji ', 'Ji ', 'Luan ', 'Yang ', 'Mie ', 'Qiang ', 'Ta ', 'Mei ', 'Yang ', + 0x90 => 'You ', 'You ', 'Fen ', 'Ba ', 'Gao ', 'Yang ', 'Gu ', 'Qiang ', 'Zang ', 'Gao ', 'Ling ', 'Yi ', 'Zhu ', 'Di ', 'Xiu ', 'Qian ', + 0xA0 => 'Yi ', 'Xian ', 'Rong ', 'Qun ', 'Qun ', 'Qian ', 'Huan ', 'Zui ', 'Xian ', 'Yi ', 'Yashinau ', 'Qiang ', 'Xian ', 'Yu ', 'Geng ', 'Jie ', + 0xB0 => 'Tang ', 'Yuan ', 'Xi ', 'Fan ', 'Shan ', 'Fen ', 'Shan ', 'Lian ', 'Lei ', 'Geng ', 'Nou ', 'Qiang ', 'Chan ', 'Yu ', 'Gong ', 'Yi ', + 0xC0 => 'Chong ', 'Weng ', 'Fen ', 'Hong ', 'Chi ', 'Chi ', 'Cui ', 'Fu ', 'Xia ', 'Pen ', 'Yi ', 'La ', 'Yi ', 'Pi ', 'Ling ', 'Liu ', + 0xD0 => 'Zhi ', 'Qu ', 'Xi ', 'Xie ', 'Xiang ', 'Xi ', 'Xi ', 'Qi ', 'Qiao ', 'Hui ', 'Hui ', 'Xiao ', 'Se ', 'Hong ', 'Jiang ', 'Di ', + 0xE0 => 'Cui ', 'Fei ', 'Tao ', 'Sha ', 'Chi ', 'Zhu ', 'Jian ', 'Xuan ', 'Shi ', 'Pian ', 'Zong ', 'Wan ', 'Hui ', 'Hou ', 'He ', 'He ', + 0xF0 => 'Han ', 'Ao ', 'Piao ', 'Yi ', 'Lian ', 'Qu ', null, 'Lin ', 'Pen ', 'Qiao ', 'Ao ', 'Fan ', 'Yi ', 'Hui ', 'Xuan ', 'Dao ', +]; diff --git a/resources/transliteration-data/x80.php b/resources/transliteration-data/x80.php new file mode 100644 index 000000000..7ea3641a1 --- /dev/null +++ b/resources/transliteration-data/x80.php @@ -0,0 +1,20 @@ + 'Yao ', 'Lao ', null, 'Kao ', 'Mao ', 'Zhe ', 'Qi ', 'Gou ', 'Gou ', 'Gou ', 'Die ', 'Die ', 'Er ', 'Shua ', 'Ruan ', 'Er ', + 0x10 => 'Nai ', 'Zhuan ', 'Lei ', 'Ting ', 'Zi ', 'Geng ', 'Chao ', 'Hao ', 'Yun ', 'Pa ', 'Pi ', 'Chi ', 'Si ', 'Chu ', 'Jia ', 'Ju ', + 0x20 => 'He ', 'Chu ', 'Lao ', 'Lun ', 'Ji ', 'Tang ', 'Ou ', 'Lou ', 'Nou ', 'Gou ', 'Pang ', 'Ze ', 'Lou ', 'Ji ', 'Lao ', 'Huo ', + 0x30 => 'You ', 'Mo ', 'Huai ', 'Er ', 'Zhe ', 'Ting ', 'Ye ', 'Da ', 'Song ', 'Qin ', 'Yun ', 'Chi ', 'Dan ', 'Dan ', 'Hong ', 'Geng ', + 0x40 => 'Zhi ', null, 'Nie ', 'Dan ', 'Zhen ', 'Che ', 'Ling ', 'Zheng ', 'You ', 'Wa ', 'Liao ', 'Long ', 'Zhi ', 'Ning ', 'Tiao ', 'Er ', + 0x50 => 'Ya ', 'Die ', 'Gua ', null, 'Lian ', 'Hao ', 'Sheng ', 'Lie ', 'Pin ', 'Jing ', 'Ju ', 'Bi ', 'Di ', 'Guo ', 'Wen ', 'Xu ', + 0x60 => 'Ping ', 'Cong ', 'Shikato ', null, 'Ting ', 'Yu ', 'Cong ', 'Kui ', 'Tsuraneru ', 'Kui ', 'Cong ', 'Lian ', 'Weng ', 'Kui ', 'Lian ', 'Lian ', + 0x70 => 'Cong ', 'Ao ', 'Sheng ', 'Song ', 'Ting ', 'Kui ', 'Nie ', 'Zhi ', 'Dan ', 'Ning ', 'Qie ', 'Ji ', 'Ting ', 'Ting ', 'Long ', 'Yu ', + 0x80 => 'Yu ', 'Zhao ', 'Si ', 'Su ', 'Yi ', 'Su ', 'Si ', 'Zhao ', 'Zhao ', 'Rou ', 'Yi ', 'Le ', 'Ji ', 'Qiu ', 'Ken ', 'Cao ', + 0x90 => 'Ge ', 'Di ', 'Huan ', 'Huang ', 'Yi ', 'Ren ', 'Xiao ', 'Ru ', 'Zhou ', 'Yuan ', 'Du ', 'Gang ', 'Rong ', 'Gan ', 'Cha ', 'Wo ', + 0xA0 => 'Chang ', 'Gu ', 'Zhi ', 'Han ', 'Fu ', 'Fei ', 'Fen ', 'Pei ', 'Pang ', 'Jian ', 'Fang ', 'Zhun ', 'You ', 'Na ', 'Hang ', 'Ken ', + 0xB0 => 'Ran ', 'Gong ', 'Yu ', 'Wen ', 'Yao ', 'Jin ', 'Pi ', 'Qian ', 'Xi ', 'Xi ', 'Fei ', 'Ken ', 'Jing ', 'Tai ', 'Shen ', 'Zhong ', + 0xC0 => 'Zhang ', 'Xie ', 'Shen ', 'Wei ', 'Zhou ', 'Die ', 'Dan ', 'Fei ', 'Ba ', 'Bo ', 'Qu ', 'Tian ', 'Bei ', 'Gua ', 'Tai ', 'Zi ', + 0xD0 => 'Ku ', 'Zhi ', 'Ni ', 'Ping ', 'Zi ', 'Fu ', 'Pang ', 'Zhen ', 'Xian ', 'Zuo ', 'Pei ', 'Jia ', 'Sheng ', 'Zhi ', 'Bao ', 'Mu ', + 0xE0 => 'Qu ', 'Hu ', 'Ke ', 'Yi ', 'Yin ', 'Xu ', 'Yang ', 'Long ', 'Dong ', 'Ka ', 'Lu ', 'Jing ', 'Nu ', 'Yan ', 'Pang ', 'Kua ', + 0xF0 => 'Yi ', 'Guang ', 'Gai ', 'Ge ', 'Dong ', 'Zhi ', 'Xiao ', 'Xiong ', 'Xiong ', 'Er ', 'E ', 'Xing ', 'Pian ', 'Neng ', 'Zi ', 'Gui ', +]; diff --git a/resources/transliteration-data/x81.php b/resources/transliteration-data/x81.php new file mode 100644 index 000000000..afb7202f6 --- /dev/null +++ b/resources/transliteration-data/x81.php @@ -0,0 +1,20 @@ + 'Cheng ', 'Tiao ', 'Zhi ', 'Cui ', 'Mei ', 'Xie ', 'Cui ', 'Xie ', 'Mo ', 'Mai ', 'Ji ', 'Obiyaakasu ', null, 'Kuai ', 'Sa ', 'Zang ', + 0x10 => 'Qi ', 'Nao ', 'Mi ', 'Nong ', 'Luan ', 'Wan ', 'Bo ', 'Wen ', 'Guan ', 'Qiu ', 'Jiao ', 'Jing ', 'Rou ', 'Heng ', 'Cuo ', 'Lie ', + 0x20 => 'Shan ', 'Ting ', 'Mei ', 'Chun ', 'Shen ', 'Xie ', 'De ', 'Zui ', 'Cu ', 'Xiu ', 'Xin ', 'Tuo ', 'Pao ', 'Cheng ', 'Nei ', 'Fu ', + 0x30 => 'Dou ', 'Tuo ', 'Niao ', 'Noy ', 'Pi ', 'Gu ', 'Gua ', 'Li ', 'Lian ', 'Zhang ', 'Cui ', 'Jie ', 'Liang ', 'Zhou ', 'Pi ', 'Biao ', + 0x40 => 'Lun ', 'Pian ', 'Guo ', 'Kui ', 'Chui ', 'Dan ', 'Tian ', 'Nei ', 'Jing ', 'Jie ', 'La ', 'Yi ', 'An ', 'Ren ', 'Shen ', 'Chuo ', + 0x50 => 'Fu ', 'Fu ', 'Ju ', 'Fei ', 'Qiang ', 'Wan ', 'Dong ', 'Pi ', 'Guo ', 'Zong ', 'Ding ', 'Wu ', 'Mei ', 'Ruan ', 'Zhuan ', 'Zhi ', + 0x60 => 'Cou ', 'Gua ', 'Ou ', 'Di ', 'An ', 'Xing ', 'Nao ', 'Yu ', 'Chuan ', 'Nan ', 'Yun ', 'Zhong ', 'Rou ', 'E ', 'Sai ', 'Tu ', + 0x70 => 'Yao ', 'Jian ', 'Wei ', 'Jiao ', 'Yu ', 'Jia ', 'Duan ', 'Bi ', 'Chang ', 'Fu ', 'Xian ', 'Ni ', 'Mian ', 'Wa ', 'Teng ', 'Tui ', + 0x80 => 'Bang ', 'Qian ', 'Lu ', 'Wa ', 'Sou ', 'Tang ', 'Su ', 'Zhui ', 'Ge ', 'Yi ', 'Bo ', 'Liao ', 'Ji ', 'Pi ', 'Xie ', 'Gao ', + 0x90 => 'Lu ', 'Bin ', 'Ou ', 'Chang ', 'Lu ', 'Guo ', 'Pang ', 'Chuai ', 'Piao ', 'Jiang ', 'Fu ', 'Tang ', 'Mo ', 'Xi ', 'Zhuan ', 'Lu ', + 0xA0 => 'Jiao ', 'Ying ', 'Lu ', 'Zhi ', 'Tara ', 'Chun ', 'Lian ', 'Tong ', 'Peng ', 'Ni ', 'Zha ', 'Liao ', 'Cui ', 'Gui ', 'Xiao ', 'Teng ', + 0xB0 => 'Fan ', 'Zhi ', 'Jiao ', 'Shan ', 'Wu ', 'Cui ', 'Run ', 'Xiang ', 'Sui ', 'Fen ', 'Ying ', 'Tan ', 'Zhua ', 'Dan ', 'Kuai ', 'Nong ', + 0xC0 => 'Tun ', 'Lian ', 'Bi ', 'Yong ', 'Jue ', 'Chu ', 'Yi ', 'Juan ', 'La ', 'Lian ', 'Sao ', 'Tun ', 'Gu ', 'Qi ', 'Cui ', 'Bin ', + 0xD0 => 'Xun ', 'Ru ', 'Huo ', 'Zang ', 'Xian ', 'Biao ', 'Xing ', 'Kuan ', 'La ', 'Yan ', 'Lu ', 'Huo ', 'Zang ', 'Luo ', 'Qu ', 'Zang ', + 0xE0 => 'Luan ', 'Ni ', 'Zang ', 'Chen ', 'Qian ', 'Wo ', 'Guang ', 'Zang ', 'Lin ', 'Guang ', 'Zi ', 'Jiao ', 'Nie ', 'Chou ', 'Ji ', 'Gao ', + 0xF0 => 'Chou ', 'Mian ', 'Nie ', 'Zhi ', 'Zhi ', 'Ge ', 'Jian ', 'Die ', 'Zhi ', 'Xiu ', 'Tai ', 'Zhen ', 'Jiu ', 'Xian ', 'Yu ', 'Cha ', +]; diff --git a/resources/transliteration-data/x82.php b/resources/transliteration-data/x82.php new file mode 100644 index 000000000..ad6cd7bc1 --- /dev/null +++ b/resources/transliteration-data/x82.php @@ -0,0 +1,20 @@ + 'Yao ', 'Yu ', 'Chong ', 'Xi ', 'Xi ', 'Jiu ', 'Yu ', 'Yu ', 'Xing ', 'Ju ', 'Jiu ', 'Xin ', 'She ', 'She ', 'Yadoru ', 'Jiu ', + 0x10 => 'Shi ', 'Tan ', 'Shu ', 'Shi ', 'Tian ', 'Dan ', 'Pu ', 'Pu ', 'Guan ', 'Hua ', 'Tan ', 'Chuan ', 'Shun ', 'Xia ', 'Wu ', 'Zhou ', + 0x20 => 'Dao ', 'Gang ', 'Shan ', 'Yi ', null, 'Pa ', 'Tai ', 'Fan ', 'Ban ', 'Chuan ', 'Hang ', 'Fang ', 'Ban ', 'Que ', 'Hesaki ', 'Zhong ', + 0x30 => 'Jian ', 'Cang ', 'Ling ', 'Zhu ', 'Ze ', 'Duo ', 'Bo ', 'Xian ', 'Ge ', 'Chuan ', 'Jia ', 'Lu ', 'Hong ', 'Pang ', 'Xi ', null, + 0x40 => 'Fu ', 'Zao ', 'Feng ', 'Li ', 'Shao ', 'Yu ', 'Lang ', 'Ting ', null, 'Wei ', 'Bo ', 'Meng ', 'Nian ', 'Ju ', 'Huang ', 'Shou ', + 0x50 => 'Zong ', 'Bian ', 'Mao ', 'Die ', null, 'Bang ', 'Cha ', 'Yi ', 'Sao ', 'Cang ', 'Cao ', 'Lou ', 'Dai ', 'Sori ', 'Yao ', 'Tong ', + 0x60 => 'Yofune ', 'Dang ', 'Tan ', 'Lu ', 'Yi ', 'Jie ', 'Jian ', 'Huo ', 'Meng ', 'Qi ', 'Lu ', 'Lu ', 'Chan ', 'Shuang ', 'Gen ', 'Liang ', + 0x70 => 'Jian ', 'Jian ', 'Se ', 'Yan ', 'Fu ', 'Ping ', 'Yan ', 'Yan ', 'Cao ', 'Cao ', 'Yi ', 'Le ', 'Ting ', 'Qiu ', 'Ai ', 'Nai ', + 0x80 => 'Tiao ', 'Jiao ', 'Jie ', 'Peng ', 'Wan ', 'Yi ', 'Chai ', 'Mian ', 'Mie ', 'Gan ', 'Qian ', 'Yu ', 'Yu ', 'Shuo ', 'Qiong ', 'Tu ', + 0x90 => 'Xia ', 'Qi ', 'Mang ', 'Zi ', 'Hui ', 'Sui ', 'Zhi ', 'Xiang ', 'Bi ', 'Fu ', 'Tun ', 'Wei ', 'Wu ', 'Zhi ', 'Qi ', 'Shan ', + 0xA0 => 'Wen ', 'Qian ', 'Ren ', 'Fou ', 'Kou ', 'Jie ', 'Lu ', 'Xu ', 'Ji ', 'Qin ', 'Qi ', 'Yuan ', 'Fen ', 'Ba ', 'Rui ', 'Xin ', + 0xB0 => 'Ji ', 'Hua ', 'Hua ', 'Fang ', 'Wu ', 'Jue ', 'Gou ', 'Zhi ', 'Yun ', 'Qin ', 'Ao ', 'Chu ', 'Mao ', 'Ya ', 'Fei ', 'Reng ', + 0xC0 => 'Hang ', 'Cong ', 'Yin ', 'You ', 'Bian ', 'Yi ', 'Susa ', 'Wei ', 'Li ', 'Pi ', 'E ', 'Xian ', 'Chang ', 'Cang ', 'Meng ', 'Su ', + 0xD0 => 'Yi ', 'Yuan ', 'Ran ', 'Ling ', 'Tai ', 'Tiao ', 'Di ', 'Miao ', 'Qiong ', 'Li ', 'Yong ', 'Ke ', 'Mu ', 'Pei ', 'Bao ', 'Gou ', + 0xE0 => 'Min ', 'Yi ', 'Yi ', 'Ju ', 'Pi ', 'Ruo ', 'Ku ', 'Zhu ', 'Ni ', 'Bo ', 'Bing ', 'Shan ', 'Qiu ', 'Yao ', 'Xian ', 'Ben ', + 0xF0 => 'Hong ', 'Ying ', 'Zha ', 'Dong ', 'Ju ', 'Die ', 'Nie ', 'Gan ', 'Hu ', 'Ping ', 'Mei ', 'Fu ', 'Sheng ', 'Gu ', 'Bi ', 'Wei ', +]; diff --git a/resources/transliteration-data/x83.php b/resources/transliteration-data/x83.php new file mode 100644 index 000000000..c81a96df6 --- /dev/null +++ b/resources/transliteration-data/x83.php @@ -0,0 +1,20 @@ + 'Fu ', 'Zhuo ', 'Mao ', 'Fan ', 'Qie ', 'Mao ', 'Mao ', 'Ba ', 'Zi ', 'Mo ', 'Zi ', 'Di ', 'Chi ', 'Ji ', 'Jing ', 'Long ', + 0x10 => null, 'Niao ', null, 'Xue ', 'Ying ', 'Qiong ', 'Ge ', 'Ming ', 'Li ', 'Rong ', 'Yin ', 'Gen ', 'Qian ', 'Chai ', 'Chen ', 'Yu ', + 0x20 => 'Xiu ', 'Zi ', 'Lie ', 'Wu ', 'Ji ', 'Kui ', 'Ce ', 'Chong ', 'Ci ', 'Gou ', 'Guang ', 'Mang ', 'Chi ', 'Jiao ', 'Jiao ', 'Fu ', + 0x30 => 'Yu ', 'Zhu ', 'Zi ', 'Jiang ', 'Hui ', 'Yin ', 'Cha ', 'Fa ', 'Rong ', 'Ru ', 'Chong ', 'Mang ', 'Tong ', 'Zhong ', null, 'Zhu ', + 0x40 => 'Xun ', 'Huan ', 'Kua ', 'Quan ', 'Gai ', 'Da ', 'Jing ', 'Xing ', 'Quan ', 'Cao ', 'Jing ', 'Er ', 'An ', 'Shou ', 'Chi ', 'Ren ', + 0x50 => 'Jian ', 'Ti ', 'Huang ', 'Ping ', 'Li ', 'Jin ', 'Lao ', 'Shu ', 'Zhuang ', 'Da ', 'Jia ', 'Rao ', 'Bi ', 'Ze ', 'Qiao ', 'Hui ', + 0x60 => 'Qi ', 'Dang ', null, 'Rong ', 'Hun ', 'Ying ', 'Luo ', 'Ying ', 'Xun ', 'Jin ', 'Sun ', 'Yin ', 'Mai ', 'Hong ', 'Zhou ', 'Yao ', + 0x70 => 'Du ', 'Wei ', 'Chu ', 'Dou ', 'Fu ', 'Ren ', 'Yin ', 'He ', 'Bi ', 'Bu ', 'Yun ', 'Di ', 'Tu ', 'Sui ', 'Sui ', 'Cheng ', + 0x80 => 'Chen ', 'Wu ', 'Bie ', 'Xi ', 'Geng ', 'Li ', 'Fu ', 'Zhu ', 'Mo ', 'Li ', 'Zhuang ', 'Ji ', 'Duo ', 'Qiu ', 'Sha ', 'Suo ', + 0x90 => 'Chen ', 'Feng ', 'Ju ', 'Mei ', 'Meng ', 'Xing ', 'Jing ', 'Che ', 'Xin ', 'Jun ', 'Yan ', 'Ting ', 'Diao ', 'Cuo ', 'Wan ', 'Han ', + 0xA0 => 'You ', 'Cuo ', 'Jia ', 'Wang ', 'You ', 'Niu ', 'Shao ', 'Xian ', 'Lang ', 'Fu ', 'E ', 'Mo ', 'Wen ', 'Jie ', 'Nan ', 'Mu ', + 0xB0 => 'Kan ', 'Lai ', 'Lian ', 'Shi ', 'Wo ', 'Usagi ', 'Lian ', 'Huo ', 'You ', 'Ying ', 'Ying ', 'Nuc ', 'Chun ', 'Mang ', 'Mang ', 'Ci ', + 0xC0 => 'Wan ', 'Jing ', 'Di ', 'Qu ', 'Dong ', 'Jian ', 'Zou ', 'Gu ', 'La ', 'Lu ', 'Ju ', 'Wei ', 'Jun ', 'Nie ', 'Kun ', 'He ', + 0xD0 => 'Pu ', 'Zi ', 'Gao ', 'Guo ', 'Fu ', 'Lun ', 'Chang ', 'Chou ', 'Song ', 'Chui ', 'Zhan ', 'Men ', 'Cai ', 'Ba ', 'Li ', 'Tu ', + 0xE0 => 'Bo ', 'Han ', 'Bao ', 'Qin ', 'Juan ', 'Xi ', 'Qin ', 'Di ', 'Jie ', 'Pu ', 'Dang ', 'Jin ', 'Zhao ', 'Tai ', 'Geng ', 'Hua ', + 0xF0 => 'Gu ', 'Ling ', 'Fei ', 'Jin ', 'An ', 'Wang ', 'Beng ', 'Zhou ', 'Yan ', 'Ju ', 'Jian ', 'Lin ', 'Tan ', 'Shu ', 'Tian ', 'Dao ', +]; diff --git a/resources/transliteration-data/x84.php b/resources/transliteration-data/x84.php new file mode 100644 index 000000000..afa743780 --- /dev/null +++ b/resources/transliteration-data/x84.php @@ -0,0 +1,20 @@ + 'Hu ', 'Qi ', 'He ', 'Cui ', 'Tao ', 'Chun ', 'Bei ', 'Chang ', 'Huan ', 'Fei ', 'Lai ', 'Qi ', 'Meng ', 'Ping ', 'Wei ', 'Dan ', + 0x10 => 'Sha ', 'Huan ', 'Yan ', 'Yi ', 'Tiao ', 'Qi ', 'Wan ', 'Ce ', 'Nai ', 'Kutabireru ', 'Tuo ', 'Jiu ', 'Tie ', 'Luo ', null, null, + 0x20 => 'Meng ', null, 'Yaji ', null, 'Ying ', 'Ying ', 'Ying ', 'Xiao ', 'Sa ', 'Qiu ', 'Ke ', 'Xiang ', 'Wan ', 'Yu ', 'Yu ', 'Fu ', + 0x30 => 'Lian ', 'Xuan ', 'Yuan ', 'Nan ', 'Ze ', 'Wo ', 'Chun ', 'Xiao ', 'Yu ', 'Pian ', 'Mao ', 'An ', 'E ', 'Luo ', 'Ying ', 'Huo ', + 0x40 => 'Gua ', 'Jiang ', 'Mian ', 'Zuo ', 'Zuo ', 'Ju ', 'Bao ', 'Rou ', 'Xi ', 'Xie ', 'An ', 'Qu ', 'Jian ', 'Fu ', 'Lu ', 'Jing ', + 0x50 => 'Pen ', 'Feng ', 'Hong ', 'Hong ', 'Hou ', 'Yan ', 'Tu ', 'Zhu ', 'Zi ', 'Xiang ', 'Shen ', 'Ge ', 'Jie ', 'Jing ', 'Mi ', 'Huang ', + 0x60 => 'Shen ', 'Pu ', 'Gai ', 'Dong ', 'Zhou ', 'Qian ', 'Wei ', 'Bo ', 'Wei ', 'Pa ', 'Ji ', 'Hu ', 'Zang ', 'Jia ', 'Duan ', 'Yao ', + 0x70 => 'Jun ', 'Cong ', 'Quan ', 'Wei ', 'Xian ', 'Kui ', 'Ting ', 'Hun ', 'Xi ', 'Shi ', 'Qi ', 'Lan ', 'Zong ', 'Yao ', 'Yuan ', 'Mei ', + 0x80 => 'Yun ', 'Shu ', 'Di ', 'Zhuan ', 'Guan ', 'Sukumo ', 'Xue ', 'Chan ', 'Kai ', 'Kui ', null, 'Jiang ', 'Lou ', 'Wei ', 'Pai ', null, + 0x90 => 'Sou ', 'Yin ', 'Shi ', 'Chun ', 'Shi ', 'Yun ', 'Zhen ', 'Lang ', 'Nu ', 'Meng ', 'He ', 'Que ', 'Suan ', 'Yuan ', 'Li ', 'Ju ', + 0xA0 => 'Xi ', 'Pang ', 'Chu ', 'Xu ', 'Tu ', 'Liu ', 'Wo ', 'Zhen ', 'Qian ', 'Zu ', 'Po ', 'Cuo ', 'Yuan ', 'Chu ', 'Yu ', 'Kuai ', + 0xB0 => 'Pan ', 'Pu ', 'Pu ', 'Na ', 'Shuo ', 'Xi ', 'Fen ', 'Yun ', 'Zheng ', 'Jian ', 'Ji ', 'Ruo ', 'Cang ', 'En ', 'Mi ', 'Hao ', + 0xC0 => 'Sun ', 'Zhen ', 'Ming ', 'Sou ', 'Xu ', 'Liu ', 'Xi ', 'Gu ', 'Lang ', 'Rong ', 'Weng ', 'Gai ', 'Cuo ', 'Shi ', 'Tang ', 'Luo ', + 0xD0 => 'Ru ', 'Suo ', 'Xian ', 'Bei ', 'Yao ', 'Gui ', 'Bi ', 'Zong ', 'Gun ', 'Za ', 'Xiu ', 'Ce ', 'Hai ', 'Lan ', null, 'Ji ', + 0xE0 => 'Li ', 'Can ', 'Lang ', 'Yu ', null, 'Ying ', 'Mo ', 'Diao ', 'Tiao ', 'Mao ', 'Tong ', 'Zhu ', 'Peng ', 'An ', 'Lian ', 'Cong ', + 0xF0 => 'Xi ', 'Ping ', 'Qiu ', 'Jin ', 'Chun ', 'Jie ', 'Wei ', 'Tui ', 'Cao ', 'Yu ', 'Yi ', 'Ji ', 'Liao ', 'Bi ', 'Lu ', 'Su ', +]; diff --git a/resources/transliteration-data/x85.php b/resources/transliteration-data/x85.php new file mode 100644 index 000000000..e6e34dfd7 --- /dev/null +++ b/resources/transliteration-data/x85.php @@ -0,0 +1,20 @@ + 'Bu ', 'Zhang ', 'Luo ', 'Jiang ', 'Man ', 'Yan ', 'Ling ', 'Ji ', 'Piao ', 'Gun ', 'Han ', 'Di ', 'Su ', 'Lu ', 'She ', 'Shang ', + 0x10 => 'Di ', 'Mie ', 'Xun ', 'Man ', 'Bo ', 'Di ', 'Cuo ', 'Zhe ', 'Sen ', 'Xuan ', 'Wei ', 'Hu ', 'Ao ', 'Mi ', 'Lou ', 'Cu ', + 0x20 => 'Zhong ', 'Cai ', 'Po ', 'Jiang ', 'Mi ', 'Cong ', 'Niao ', 'Hui ', 'Jun ', 'Yin ', 'Jian ', 'Yan ', 'Shu ', 'Yin ', 'Kui ', 'Chen ', + 0x30 => 'Hu ', 'Sha ', 'Kou ', 'Qian ', 'Ma ', 'Zang ', 'Sonoko ', 'Qiang ', 'Dou ', 'Lian ', 'Lin ', 'Kou ', 'Ai ', 'Bi ', 'Li ', 'Wei ', + 0x40 => 'Ji ', 'Xun ', 'Sheng ', 'Fan ', 'Meng ', 'Ou ', 'Chan ', 'Dian ', 'Xun ', 'Jiao ', 'Rui ', 'Rui ', 'Lei ', 'Yu ', 'Qiao ', 'Chu ', + 0x50 => 'Hua ', 'Jian ', 'Mai ', 'Yun ', 'Bao ', 'You ', 'Qu ', 'Lu ', 'Rao ', 'Hui ', 'E ', 'Teng ', 'Fei ', 'Jue ', 'Zui ', 'Fa ', + 0x60 => 'Ru ', 'Fen ', 'Kui ', 'Shun ', 'Rui ', 'Ya ', 'Xu ', 'Fu ', 'Jue ', 'Dang ', 'Wu ', 'Tong ', 'Si ', 'Xiao ', 'Xi ', 'Long ', + 0x70 => 'Yun ', null, 'Qi ', 'Jian ', 'Yun ', 'Sun ', 'Ling ', 'Yu ', 'Xia ', 'Yong ', 'Ji ', 'Hong ', 'Si ', 'Nong ', 'Lei ', 'Xuan ', + 0x80 => 'Yun ', 'Yu ', 'Xi ', 'Hao ', 'Bo ', 'Hao ', 'Ai ', 'Wei ', 'Hui ', 'Wei ', 'Ji ', 'Ci ', 'Xiang ', 'Luan ', 'Mie ', 'Yi ', + 0x90 => 'Leng ', 'Jiang ', 'Can ', 'Shen ', 'Qiang ', 'Lian ', 'Ke ', 'Yuan ', 'Da ', 'Ti ', 'Tang ', 'Xie ', 'Bi ', 'Zhan ', 'Sun ', 'Lian ', + 0xA0 => 'Fan ', 'Ding ', 'Jie ', 'Gu ', 'Xie ', 'Shu ', 'Jian ', 'Kao ', 'Hong ', 'Sa ', 'Xin ', 'Xun ', 'Yao ', 'Hie ', 'Sou ', 'Shu ', + 0xB0 => 'Xun ', 'Dui ', 'Pin ', 'Wei ', 'Neng ', 'Chou ', 'Mai ', 'Ru ', 'Piao ', 'Tai ', 'Qi ', 'Zao ', 'Chen ', 'Zhen ', 'Er ', 'Ni ', + 0xC0 => 'Ying ', 'Gao ', 'Cong ', 'Xiao ', 'Qi ', 'Fa ', 'Jian ', 'Xu ', 'Kui ', 'Jie ', 'Bian ', 'Diao ', 'Mi ', 'Lan ', 'Jin ', 'Cang ', + 0xD0 => 'Miao ', 'Qiong ', 'Qie ', 'Xian ', null, 'Ou ', 'Xian ', 'Su ', 'Lu ', 'Yi ', 'Xu ', 'Xie ', 'Li ', 'Yi ', 'La ', 'Lei ', + 0xE0 => 'Xiao ', 'Di ', 'Zhi ', 'Bei ', 'Teng ', 'Yao ', 'Mo ', 'Huan ', 'Piao ', 'Fan ', 'Sou ', 'Tan ', 'Tui ', 'Qiong ', 'Qiao ', 'Wei ', + 0xF0 => 'Liu ', 'Hui ', null, 'Gao ', 'Yun ', null, 'Li ', 'Shu ', 'Chu ', 'Ai ', 'Lin ', 'Zao ', 'Xuan ', 'Chen ', 'Lai ', 'Huo ', +]; diff --git a/resources/transliteration-data/x86.php b/resources/transliteration-data/x86.php new file mode 100644 index 000000000..ebef61617 --- /dev/null +++ b/resources/transliteration-data/x86.php @@ -0,0 +1,20 @@ + 'Tuo ', 'Wu ', 'Rui ', 'Rui ', 'Qi ', 'Heng ', 'Lu ', 'Su ', 'Tui ', 'Mang ', 'Yun ', 'Pin ', 'Yu ', 'Xun ', 'Ji ', 'Jiong ', + 0x10 => 'Xian ', 'Mo ', 'Hagi ', 'Su ', 'Jiong ', null, 'Nie ', 'Bo ', 'Rang ', 'Yi ', 'Xian ', 'Yu ', 'Ju ', 'Lian ', 'Lian ', 'Yin ', + 0x20 => 'Qiang ', 'Ying ', 'Long ', 'Tong ', 'Wei ', 'Yue ', 'Ling ', 'Qu ', 'Yao ', 'Fan ', 'Mi ', 'Lan ', 'Kui ', 'Lan ', 'Ji ', 'Dang ', + 0x30 => 'Katsura ', 'Lei ', 'Lei ', 'Hua ', 'Feng ', 'Zhi ', 'Wei ', 'Kui ', 'Zhan ', 'Huai ', 'Li ', 'Ji ', 'Mi ', 'Lei ', 'Huai ', 'Luo ', + 0x40 => 'Ji ', 'Kui ', 'Lu ', 'Jian ', 'San ', null, 'Lei ', 'Quan ', 'Xiao ', 'Yi ', 'Luan ', 'Men ', 'Bie ', 'Hu ', 'Hu ', 'Lu ', + 0x50 => 'Nue ', 'Lu ', 'Si ', 'Xiao ', 'Qian ', 'Chu ', 'Hu ', 'Xu ', 'Cuo ', 'Fu ', 'Xu ', 'Xu ', 'Lu ', 'Hu ', 'Yu ', 'Hao ', + 0x60 => 'Jiao ', 'Ju ', 'Guo ', 'Bao ', 'Yan ', 'Zhan ', 'Zhan ', 'Kui ', 'Ban ', 'Xi ', 'Shu ', 'Chong ', 'Qiu ', 'Diao ', 'Ji ', 'Qiu ', + 0x70 => 'Cheng ', 'Shi ', null, 'Di ', 'Zhe ', 'She ', 'Yu ', 'Gan ', 'Zi ', 'Hong ', 'Hui ', 'Meng ', 'Ge ', 'Sui ', 'Xia ', 'Chai ', + 0x80 => 'Shi ', 'Yi ', 'Ma ', 'Xiang ', 'Fang ', 'E ', 'Pa ', 'Chi ', 'Qian ', 'Wen ', 'Wen ', 'Rui ', 'Bang ', 'Bi ', 'Yue ', 'Yue ', + 0x90 => 'Jun ', 'Qi ', 'Ran ', 'Yin ', 'Qi ', 'Tian ', 'Yuan ', 'Jue ', 'Hui ', 'Qin ', 'Qi ', 'Zhong ', 'Ya ', 'Ci ', 'Mu ', 'Wang ', + 0xA0 => 'Fen ', 'Fen ', 'Hang ', 'Gong ', 'Zao ', 'Fu ', 'Ran ', 'Jie ', 'Fu ', 'Chi ', 'Dou ', 'Piao ', 'Xian ', 'Ni ', 'Te ', 'Qiu ', + 0xB0 => 'You ', 'Zha ', 'Ping ', 'Chi ', 'You ', 'He ', 'Han ', 'Ju ', 'Li ', 'Fu ', 'Ran ', 'Zha ', 'Gou ', 'Pi ', 'Bo ', 'Xian ', + 0xC0 => 'Zhu ', 'Diao ', 'Bie ', 'Bing ', 'Gu ', 'Ran ', 'Qu ', 'She ', 'Tie ', 'Ling ', 'Gu ', 'Dan ', 'Gu ', 'Ying ', 'Li ', 'Cheng ', + 0xD0 => 'Qu ', 'Mou ', 'Ge ', 'Ci ', 'Hui ', 'Hui ', 'Mang ', 'Fu ', 'Yang ', 'Wa ', 'Lie ', 'Zhu ', 'Yi ', 'Xian ', 'Kuo ', 'Jiao ', + 0xE0 => 'Li ', 'Yi ', 'Ping ', 'Ji ', 'Ha ', 'She ', 'Yi ', 'Wang ', 'Mo ', 'Qiong ', 'Qie ', 'Gui ', 'Gong ', 'Zhi ', 'Man ', 'Ebi ', + 0xF0 => 'Zhi ', 'Jia ', 'Rao ', 'Si ', 'Qi ', 'Xing ', 'Lie ', 'Qiu ', 'Shao ', 'Yong ', 'Jia ', 'Shui ', 'Che ', 'Bai ', 'E ', 'Han ', +]; diff --git a/resources/transliteration-data/x87.php b/resources/transliteration-data/x87.php new file mode 100644 index 000000000..7d86e5c57 --- /dev/null +++ b/resources/transliteration-data/x87.php @@ -0,0 +1,20 @@ + 'Shu ', 'Xuan ', 'Feng ', 'Shen ', 'Zhen ', 'Fu ', 'Xian ', 'Zhe ', 'Wu ', 'Fu ', 'Li ', 'Lang ', 'Bi ', 'Chu ', 'Yuan ', 'You ', + 0x10 => 'Jie ', 'Dan ', 'Yan ', 'Ting ', 'Dian ', 'Shui ', 'Hui ', 'Gua ', 'Zhi ', 'Song ', 'Fei ', 'Ju ', 'Mi ', 'Qi ', 'Qi ', 'Yu ', + 0x20 => 'Jun ', 'Zha ', 'Meng ', 'Qiang ', 'Si ', 'Xi ', 'Lun ', 'Li ', 'Die ', 'Tiao ', 'Tao ', 'Kun ', 'Gan ', 'Han ', 'Yu ', 'Bang ', + 0x30 => 'Fei ', 'Pi ', 'Wei ', 'Dun ', 'Yi ', 'Yuan ', 'Su ', 'Quan ', 'Qian ', 'Rui ', 'Ni ', 'Qing ', 'Wei ', 'Liang ', 'Guo ', 'Wan ', + 0x40 => 'Dong ', 'E ', 'Ban ', 'Di ', 'Wang ', 'Can ', 'Yang ', 'Ying ', 'Guo ', 'Chan ', null, 'La ', 'Ke ', 'Ji ', 'He ', 'Ting ', + 0x50 => 'Mai ', 'Xu ', 'Mian ', 'Yu ', 'Jie ', 'Shi ', 'Xuan ', 'Huang ', 'Yan ', 'Bian ', 'Rou ', 'Wei ', 'Fu ', 'Yuan ', 'Mei ', 'Wei ', + 0x60 => 'Fu ', 'Ruan ', 'Xie ', 'You ', 'Qiu ', 'Mao ', 'Xia ', 'Ying ', 'Shi ', 'Chong ', 'Tang ', 'Zhu ', 'Zong ', 'Ti ', 'Fu ', 'Yuan ', + 0x70 => 'Hui ', 'Meng ', 'La ', 'Du ', 'Hu ', 'Qiu ', 'Die ', 'Li ', 'Gua ', 'Yun ', 'Ju ', 'Nan ', 'Lou ', 'Qun ', 'Rong ', 'Ying ', + 0x80 => 'Jiang ', null, 'Lang ', 'Pang ', 'Si ', 'Xi ', 'Ci ', 'Xi ', 'Yuan ', 'Weng ', 'Lian ', 'Sou ', 'Ban ', 'Rong ', 'Rong ', 'Ji ', + 0x90 => 'Wu ', 'Qiu ', 'Han ', 'Qin ', 'Yi ', 'Bi ', 'Hua ', 'Tang ', 'Yi ', 'Du ', 'Nai ', 'He ', 'Hu ', 'Hui ', 'Ma ', 'Ming ', + 0xA0 => 'Yi ', 'Wen ', 'Ying ', 'Teng ', 'Yu ', 'Cang ', 'So ', 'Ebi ', 'Man ', null, 'Shang ', 'Zhe ', 'Cao ', 'Chi ', 'Di ', 'Ao ', + 0xB0 => 'Lu ', 'Wei ', 'Zhi ', 'Tang ', 'Chen ', 'Piao ', 'Qu ', 'Pi ', 'Yu ', 'Jian ', 'Luo ', 'Lou ', 'Qin ', 'Zhong ', 'Yin ', 'Jiang ', + 0xC0 => 'Shuai ', 'Wen ', 'Jiao ', 'Wan ', 'Zhi ', 'Zhe ', 'Ma ', 'Ma ', 'Guo ', 'Liu ', 'Mao ', 'Xi ', 'Cong ', 'Li ', 'Man ', 'Xiao ', + 0xD0 => 'Kamakiri ', 'Zhang ', 'Mang ', 'Xiang ', 'Mo ', 'Zui ', 'Si ', 'Qiu ', 'Te ', 'Zhi ', 'Peng ', 'Peng ', 'Jiao ', 'Qu ', 'Bie ', 'Liao ', + 0xE0 => 'Pan ', 'Gui ', 'Xi ', 'Ji ', 'Zhuan ', 'Huang ', 'Fei ', 'Lao ', 'Jue ', 'Jue ', 'Hui ', 'Yin ', 'Chan ', 'Jiao ', 'Shan ', 'Rao ', + 0xF0 => 'Xiao ', 'Mou ', 'Chong ', 'Xun ', 'Si ', null, 'Cheng ', 'Dang ', 'Li ', 'Xie ', 'Shan ', 'Yi ', 'Jing ', 'Da ', 'Chan ', 'Qi ', +]; diff --git a/resources/transliteration-data/x88.php b/resources/transliteration-data/x88.php new file mode 100644 index 000000000..c0256d754 --- /dev/null +++ b/resources/transliteration-data/x88.php @@ -0,0 +1,20 @@ + 'Ci ', 'Xiang ', 'She ', 'Luo ', 'Qin ', 'Ying ', 'Chai ', 'Li ', 'Ze ', 'Xuan ', 'Lian ', 'Zhu ', 'Ze ', 'Xie ', 'Mang ', 'Xie ', + 0x10 => 'Qi ', 'Rong ', 'Jian ', 'Meng ', 'Hao ', 'Ruan ', 'Huo ', 'Zhuo ', 'Jie ', 'Bin ', 'He ', 'Mie ', 'Fan ', 'Lei ', 'Jie ', 'La ', + 0x20 => 'Mi ', 'Li ', 'Chun ', 'Li ', 'Qiu ', 'Nie ', 'Lu ', 'Du ', 'Xiao ', 'Zhu ', 'Long ', 'Li ', 'Long ', 'Feng ', 'Ye ', 'Beng ', + 0x30 => 'Shang ', 'Gu ', 'Juan ', 'Ying ', null, 'Xi ', 'Can ', 'Qu ', 'Quan ', 'Du ', 'Can ', 'Man ', 'Jue ', 'Jie ', 'Zhu ', 'Zha ', + 0x40 => 'Xie ', 'Huang ', 'Niu ', 'Pei ', 'Nu ', 'Xin ', 'Zhong ', 'Mo ', 'Er ', 'Ke ', 'Mie ', 'Xi ', 'Xing ', 'Yan ', 'Kan ', 'Yuan ', + 0x50 => null, 'Ling ', 'Xuan ', 'Shu ', 'Xian ', 'Tong ', 'Long ', 'Jie ', 'Xian ', 'Ya ', 'Hu ', 'Wei ', 'Dao ', 'Chong ', 'Wei ', 'Dao ', + 0x60 => 'Zhun ', 'Heng ', 'Qu ', 'Yi ', 'Yi ', 'Bu ', 'Gan ', 'Yu ', 'Biao ', 'Cha ', 'Yi ', 'Shan ', 'Chen ', 'Fu ', 'Gun ', 'Fen ', + 0x70 => 'Shuai ', 'Jie ', 'Na ', 'Zhong ', 'Dan ', 'Ri ', 'Zhong ', 'Zhong ', 'Xie ', 'Qi ', 'Xie ', 'Ran ', 'Zhi ', 'Ren ', 'Qin ', 'Jin ', + 0x80 => 'Jun ', 'Yuan ', 'Mei ', 'Chai ', 'Ao ', 'Niao ', 'Hui ', 'Ran ', 'Jia ', 'Tuo ', 'Ling ', 'Dai ', 'Bao ', 'Pao ', 'Yao ', 'Zuo ', + 0x90 => 'Bi ', 'Shao ', 'Tan ', 'Ju ', 'He ', 'Shu ', 'Xiu ', 'Zhen ', 'Yi ', 'Pa ', 'Bo ', 'Di ', 'Wa ', 'Fu ', 'Gun ', 'Zhi ', + 0xA0 => 'Zhi ', 'Ran ', 'Pan ', 'Yi ', 'Mao ', 'Tuo ', 'Na ', 'Kou ', 'Xian ', 'Chan ', 'Qu ', 'Bei ', 'Gun ', 'Xi ', 'Ne ', 'Bo ', + 0xB0 => 'Horo ', 'Fu ', 'Yi ', 'Chi ', 'Ku ', 'Ren ', 'Jiang ', 'Jia ', 'Cun ', 'Mo ', 'Jie ', 'Er ', 'Luo ', 'Ru ', 'Zhu ', 'Gui ', + 0xC0 => 'Yin ', 'Cai ', 'Lie ', 'Kamishimo ', 'Yuki ', 'Zhuang ', 'Dang ', null, 'Kun ', 'Ken ', 'Niao ', 'Shu ', 'Jia ', 'Kun ', 'Cheng ', 'Li ', + 0xD0 => 'Juan ', 'Shen ', 'Pou ', 'Ge ', 'Yi ', 'Yu ', 'Zhen ', 'Liu ', 'Qiu ', 'Qun ', 'Ji ', 'Yi ', 'Bu ', 'Zhuang ', 'Shui ', 'Sha ', + 0xE0 => 'Qun ', 'Li ', 'Lian ', 'Lian ', 'Ku ', 'Jian ', 'Fou ', 'Chan ', 'Bi ', 'Gun ', 'Tao ', 'Yuan ', 'Ling ', 'Chi ', 'Chang ', 'Chou ', + 0xF0 => 'Duo ', 'Biao ', 'Liang ', 'Chang ', 'Pei ', 'Pei ', 'Fei ', 'Yuan ', 'Luo ', 'Guo ', 'Yan ', 'Du ', 'Xi ', 'Zhi ', 'Ju ', 'Qi ', +]; diff --git a/resources/transliteration-data/x89.php b/resources/transliteration-data/x89.php new file mode 100644 index 000000000..b0c1ae8e7 --- /dev/null +++ b/resources/transliteration-data/x89.php @@ -0,0 +1,20 @@ + 'Ji ', 'Zhi ', 'Gua ', 'Ken ', 'Che ', 'Ti ', 'Ti ', 'Fu ', 'Chong ', 'Xie ', 'Bian ', 'Die ', 'Kun ', 'Duan ', 'Xiu ', 'Xiu ', + 0x10 => 'He ', 'Yuan ', 'Bao ', 'Bao ', 'Fu ', 'Yu ', 'Tuan ', 'Yan ', 'Hui ', 'Bei ', 'Chu ', 'Lu ', 'Ena ', 'Hitoe ', 'Yun ', 'Da ', + 0x20 => 'Gou ', 'Da ', 'Huai ', 'Rong ', 'Yuan ', 'Ru ', 'Nai ', 'Jiong ', 'Suo ', 'Ban ', 'Tun ', 'Chi ', 'Sang ', 'Niao ', 'Ying ', 'Jie ', + 0x30 => 'Qian ', 'Huai ', 'Ku ', 'Lian ', 'Bao ', 'Li ', 'Zhe ', 'Shi ', 'Lu ', 'Yi ', 'Die ', 'Xie ', 'Xian ', 'Wei ', 'Biao ', 'Cao ', + 0x40 => 'Ji ', 'Jiang ', 'Sen ', 'Bao ', 'Xiang ', 'Chihaya ', 'Pu ', 'Jian ', 'Zhuan ', 'Jian ', 'Zui ', 'Ji ', 'Dan ', 'Za ', 'Fan ', 'Bo ', + 0x50 => 'Xiang ', 'Xin ', 'Bie ', 'Rao ', 'Man ', 'Lan ', 'Ao ', 'Duo ', 'Gui ', 'Cao ', 'Sui ', 'Nong ', 'Chan ', 'Lian ', 'Bi ', 'Jin ', + 0x60 => 'Dang ', 'Shu ', 'Tan ', 'Bi ', 'Lan ', 'Pu ', 'Ru ', 'Zhi ', null, 'Shu ', 'Wa ', 'Shi ', 'Bai ', 'Xie ', 'Bo ', 'Chen ', + 0x70 => 'Lai ', 'Long ', 'Xi ', 'Xian ', 'Lan ', 'Zhe ', 'Dai ', 'Tasuki ', 'Zan ', 'Shi ', 'Jian ', 'Pan ', 'Yi ', 'Ran ', 'Ya ', 'Xi ', + 0x80 => 'Xi ', 'Yao ', 'Feng ', 'Tan ', null, 'Biao ', 'Fu ', 'Ba ', 'He ', 'Ji ', 'Ji ', 'Jian ', 'Guan ', 'Bian ', 'Yan ', 'Gui ', + 0x90 => 'Jue ', 'Pian ', 'Mao ', 'Mi ', 'Mi ', 'Mie ', 'Shi ', 'Si ', 'Zhan ', 'Luo ', 'Jue ', 'Mi ', 'Tiao ', 'Lian ', 'Yao ', 'Zhi ', + 0xA0 => 'Jun ', 'Xi ', 'Shan ', 'Wei ', 'Xi ', 'Tian ', 'Yu ', 'Lan ', 'E ', 'Du ', 'Qin ', 'Pang ', 'Ji ', 'Ming ', 'Ying ', 'Gou ', + 0xB0 => 'Qu ', 'Zhan ', 'Jin ', 'Guan ', 'Deng ', 'Jian ', 'Luo ', 'Qu ', 'Jian ', 'Wei ', 'Jue ', 'Qu ', 'Luo ', 'Lan ', 'Shen ', 'Di ', + 0xC0 => 'Guan ', 'Jian ', 'Guan ', 'Yan ', 'Gui ', 'Mi ', 'Shi ', 'Zhan ', 'Lan ', 'Jue ', 'Ji ', 'Xi ', 'Di ', 'Tian ', 'Yu ', 'Gou ', + 0xD0 => 'Jin ', 'Qu ', 'Jiao ', 'Jiu ', 'Jin ', 'Cu ', 'Jue ', 'Zhi ', 'Chao ', 'Ji ', 'Gu ', 'Dan ', 'Zui ', 'Di ', 'Shang ', 'Hua ', + 0xE0 => 'Quan ', 'Ge ', 'Chi ', 'Jie ', 'Gui ', 'Gong ', 'Hong ', 'Jie ', 'Hun ', 'Qiu ', 'Xing ', 'Su ', 'Ni ', 'Ji ', 'Lu ', 'Zhi ', + 0xF0 => 'Zha ', 'Bi ', 'Xing ', 'Hu ', 'Shang ', 'Gong ', 'Zhi ', 'Xue ', 'Chu ', 'Xi ', 'Yi ', 'Lu ', 'Jue ', 'Xi ', 'Yan ', 'Xi ', +]; diff --git a/resources/transliteration-data/x8a.php b/resources/transliteration-data/x8a.php new file mode 100644 index 000000000..fc7beee21 --- /dev/null +++ b/resources/transliteration-data/x8a.php @@ -0,0 +1,20 @@ + 'Yan ', 'Yan ', 'Ding ', 'Fu ', 'Qiu ', 'Qiu ', 'Jiao ', 'Hong ', 'Ji ', 'Fan ', 'Xun ', 'Diao ', 'Hong ', 'Cha ', 'Tao ', 'Xu ', + 0x10 => 'Jie ', 'Yi ', 'Ren ', 'Xun ', 'Yin ', 'Shan ', 'Qi ', 'Tuo ', 'Ji ', 'Xun ', 'Yin ', 'E ', 'Fen ', 'Ya ', 'Yao ', 'Song ', + 0x20 => 'Shen ', 'Yin ', 'Xin ', 'Jue ', 'Xiao ', 'Ne ', 'Chen ', 'You ', 'Zhi ', 'Xiong ', 'Fang ', 'Xin ', 'Chao ', 'She ', 'Xian ', 'Sha ', + 0x30 => 'Tun ', 'Xu ', 'Yi ', 'Yi ', 'Su ', 'Chi ', 'He ', 'Shen ', 'He ', 'Xu ', 'Zhen ', 'Zhu ', 'Zheng ', 'Gou ', 'Zi ', 'Zi ', + 0x40 => 'Zhan ', 'Gu ', 'Fu ', 'Quan ', 'Die ', 'Ling ', 'Di ', 'Yang ', 'Li ', 'Nao ', 'Pan ', 'Zhou ', 'Gan ', 'Yi ', 'Ju ', 'Ao ', + 0x50 => 'Zha ', 'Tuo ', 'Yi ', 'Qu ', 'Zhao ', 'Ping ', 'Bi ', 'Xiong ', 'Qu ', 'Ba ', 'Da ', 'Zu ', 'Tao ', 'Zhu ', 'Ci ', 'Zhe ', + 0x60 => 'Yong ', 'Xu ', 'Xun ', 'Yi ', 'Huang ', 'He ', 'Shi ', 'Cha ', 'Jiao ', 'Shi ', 'Hen ', 'Cha ', 'Gou ', 'Gui ', 'Quan ', 'Hui ', + 0x70 => 'Jie ', 'Hua ', 'Gai ', 'Xiang ', 'Wei ', 'Shen ', 'Chou ', 'Tong ', 'Mi ', 'Zhan ', 'Ming ', 'E ', 'Hui ', 'Yan ', 'Xiong ', 'Gua ', + 0x80 => 'Er ', 'Beng ', 'Tiao ', 'Chi ', 'Lei ', 'Zhu ', 'Kuang ', 'Kua ', 'Wu ', 'Yu ', 'Teng ', 'Ji ', 'Zhi ', 'Ren ', 'Su ', 'Lang ', + 0x90 => 'E ', 'Kuang ', 'E ', 'Shi ', 'Ting ', 'Dan ', 'Bo ', 'Chan ', 'You ', 'Heng ', 'Qiao ', 'Qin ', 'Shua ', 'An ', 'Yu ', 'Xiao ', + 0xA0 => 'Cheng ', 'Jie ', 'Xian ', 'Wu ', 'Wu ', 'Gao ', 'Song ', 'Pu ', 'Hui ', 'Jing ', 'Shuo ', 'Zhen ', 'Shuo ', 'Du ', 'Yasashi ', 'Chang ', + 0xB0 => 'Shui ', 'Jie ', 'Ke ', 'Qu ', 'Cong ', 'Xiao ', 'Sui ', 'Wang ', 'Xuan ', 'Fei ', 'Chi ', 'Ta ', 'Yi ', 'Na ', 'Yin ', 'Diao ', + 0xC0 => 'Pi ', 'Chuo ', 'Chan ', 'Chen ', 'Zhun ', 'Ji ', 'Qi ', 'Tan ', 'Zhui ', 'Wei ', 'Ju ', 'Qing ', 'Jian ', 'Zheng ', 'Ze ', 'Zou ', + 0xD0 => 'Qian ', 'Zhuo ', 'Liang ', 'Jian ', 'Zhu ', 'Hao ', 'Lun ', 'Shen ', 'Biao ', 'Huai ', 'Pian ', 'Yu ', 'Die ', 'Xu ', 'Pian ', 'Shi ', + 0xE0 => 'Xuan ', 'Shi ', 'Hun ', 'Hua ', 'E ', 'Zhong ', 'Di ', 'Xie ', 'Fu ', 'Pu ', 'Ting ', 'Jian ', 'Qi ', 'Yu ', 'Zi ', 'Chuan ', + 0xF0 => 'Xi ', 'Hui ', 'Yin ', 'An ', 'Xian ', 'Nan ', 'Chen ', 'Feng ', 'Zhu ', 'Yang ', 'Yan ', 'Heng ', 'Xuan ', 'Ge ', 'Nuo ', 'Qi ', +]; diff --git a/resources/transliteration-data/x8b.php b/resources/transliteration-data/x8b.php new file mode 100644 index 000000000..12e92a36b --- /dev/null +++ b/resources/transliteration-data/x8b.php @@ -0,0 +1,20 @@ + 'Mou ', 'Ye ', 'Wei ', null, 'Teng ', 'Zou ', 'Shan ', 'Jian ', 'Bo ', 'Ku ', 'Huang ', 'Huo ', 'Ge ', 'Ying ', 'Mi ', 'Xiao ', + 0x10 => 'Mi ', 'Xi ', 'Qiang ', 'Chen ', 'Nue ', 'Ti ', 'Su ', 'Bang ', 'Chi ', 'Qian ', 'Shi ', 'Jiang ', 'Yuan ', 'Xie ', 'Xue ', 'Tao ', + 0x20 => 'Yao ', 'Yao ', null, 'Yu ', 'Biao ', 'Cong ', 'Qing ', 'Li ', 'Mo ', 'Mo ', 'Shang ', 'Zhe ', 'Miu ', 'Jian ', 'Ze ', 'Jie ', + 0x30 => 'Lian ', 'Lou ', 'Can ', 'Ou ', 'Guan ', 'Xi ', 'Zhuo ', 'Ao ', 'Ao ', 'Jin ', 'Zhe ', 'Yi ', 'Hu ', 'Jiang ', 'Man ', 'Chao ', + 0x40 => 'Han ', 'Hua ', 'Chan ', 'Xu ', 'Zeng ', 'Se ', 'Xi ', 'She ', 'Dui ', 'Zheng ', 'Nao ', 'Lan ', 'E ', 'Ying ', 'Jue ', 'Ji ', + 0x50 => 'Zun ', 'Jiao ', 'Bo ', 'Hui ', 'Zhuan ', 'Mu ', 'Zen ', 'Zha ', 'Shi ', 'Qiao ', 'Tan ', 'Zen ', 'Pu ', 'Sheng ', 'Xuan ', 'Zao ', + 0x60 => 'Tan ', 'Dang ', 'Sui ', 'Qian ', 'Ji ', 'Jiao ', 'Jing ', 'Lian ', 'Nou ', 'Yi ', 'Ai ', 'Zhan ', 'Pi ', 'Hui ', 'Hua ', 'Yi ', + 0x70 => 'Yi ', 'Shan ', 'Rang ', 'Nou ', 'Qian ', 'Zhui ', 'Ta ', 'Hu ', 'Zhou ', 'Hao ', 'Ye ', 'Ying ', 'Jian ', 'Yu ', 'Jian ', 'Hui ', + 0x80 => 'Du ', 'Zhe ', 'Xuan ', 'Zan ', 'Lei ', 'Shen ', 'Wei ', 'Chan ', 'Li ', 'Yi ', 'Bian ', 'Zhe ', 'Yan ', 'E ', 'Chou ', 'Wei ', + 0x90 => 'Chou ', 'Yao ', 'Chan ', 'Rang ', 'Yin ', 'Lan ', 'Chen ', 'Huo ', 'Zhe ', 'Huan ', 'Zan ', 'Yi ', 'Dang ', 'Zhan ', 'Yan ', 'Du ', + 0xA0 => 'Yan ', 'Ji ', 'Ding ', 'Fu ', 'Ren ', 'Ji ', 'Jie ', 'Hong ', 'Tao ', 'Rang ', 'Shan ', 'Qi ', 'Tuo ', 'Xun ', 'Yi ', 'Xun ', + 0xB0 => 'Ji ', 'Ren ', 'Jiang ', 'Hui ', 'Ou ', 'Ju ', 'Ya ', 'Ne ', 'Xu ', 'E ', 'Lun ', 'Xiong ', 'Song ', 'Feng ', 'She ', 'Fang ', + 0xC0 => 'Jue ', 'Zheng ', 'Gu ', 'He ', 'Ping ', 'Zu ', 'Shi ', 'Xiong ', 'Zha ', 'Su ', 'Zhen ', 'Di ', 'Zou ', 'Ci ', 'Qu ', 'Zhao ', + 0xD0 => 'Bi ', 'Yi ', 'Yi ', 'Kuang ', 'Lei ', 'Shi ', 'Gua ', 'Shi ', 'Jie ', 'Hui ', 'Cheng ', 'Zhu ', 'Shen ', 'Hua ', 'Dan ', 'Gou ', + 0xE0 => 'Quan ', 'Gui ', 'Xun ', 'Yi ', 'Zheng ', 'Gai ', 'Xiang ', 'Cha ', 'Hun ', 'Xu ', 'Zhou ', 'Jie ', 'Wu ', 'Yu ', 'Qiao ', 'Wu ', + 0xF0 => 'Gao ', 'You ', 'Hui ', 'Kuang ', 'Shuo ', 'Song ', 'Ai ', 'Qing ', 'Zhu ', 'Zou ', 'Nuo ', 'Du ', 'Zhuo ', 'Fei ', 'Ke ', 'Wei ', +]; diff --git a/resources/transliteration-data/x8c.php b/resources/transliteration-data/x8c.php new file mode 100644 index 000000000..826c8765a --- /dev/null +++ b/resources/transliteration-data/x8c.php @@ -0,0 +1,20 @@ + 'Yu ', 'Shui ', 'Shen ', 'Diao ', 'Chan ', 'Liang ', 'Zhun ', 'Sui ', 'Tan ', 'Shen ', 'Yi ', 'Mou ', 'Chen ', 'Die ', 'Huang ', 'Jian ', + 0x10 => 'Xie ', 'Nue ', 'Ye ', 'Wei ', 'E ', 'Yu ', 'Xuan ', 'Chan ', 'Zi ', 'An ', 'Yan ', 'Di ', 'Mi ', 'Pian ', 'Xu ', 'Mo ', + 0x20 => 'Dang ', 'Su ', 'Xie ', 'Yao ', 'Bang ', 'Shi ', 'Qian ', 'Mi ', 'Jin ', 'Man ', 'Zhe ', 'Jian ', 'Miu ', 'Tan ', 'Zen ', 'Qiao ', + 0x30 => 'Lan ', 'Pu ', 'Jue ', 'Yan ', 'Qian ', 'Zhan ', 'Chen ', 'Gu ', 'Qian ', 'Hong ', 'Xia ', 'Jue ', 'Hong ', 'Han ', 'Hong ', 'Xi ', + 0x40 => 'Xi ', 'Huo ', 'Liao ', 'Han ', 'Du ', 'Long ', 'Dou ', 'Jiang ', 'Qi ', 'Shi ', 'Li ', 'Deng ', 'Wan ', 'Bi ', 'Shu ', 'Xian ', + 0x50 => 'Feng ', 'Zhi ', 'Zhi ', 'Yan ', 'Yan ', 'Shi ', 'Chu ', 'Hui ', 'Tun ', 'Yi ', 'Tun ', 'Yi ', 'Jian ', 'Ba ', 'Hou ', 'E ', + 0x60 => 'Cu ', 'Xiang ', 'Huan ', 'Jian ', 'Ken ', 'Gai ', 'Qu ', 'Fu ', 'Xi ', 'Bin ', 'Hao ', 'Yu ', 'Zhu ', 'Jia ', null, 'Xi ', + 0x70 => 'Bo ', 'Wen ', 'Huan ', 'Bin ', 'Di ', 'Zong ', 'Fen ', 'Yi ', 'Zhi ', 'Bao ', 'Chai ', 'Han ', 'Pi ', 'Na ', 'Pi ', 'Gou ', + 0x80 => 'Na ', 'You ', 'Diao ', 'Mo ', 'Si ', 'Xiu ', 'Huan ', 'Kun ', 'He ', 'He ', 'Mo ', 'Han ', 'Mao ', 'Li ', 'Ni ', 'Bi ', + 0x90 => 'Yu ', 'Jia ', 'Tuan ', 'Mao ', 'Pi ', 'Xi ', 'E ', 'Ju ', 'Mo ', 'Chu ', 'Tan ', 'Huan ', 'Jue ', 'Bei ', 'Zhen ', 'Yuan ', + 0xA0 => 'Fu ', 'Cai ', 'Gong ', 'Te ', 'Yi ', 'Hang ', 'Wan ', 'Pin ', 'Huo ', 'Fan ', 'Tan ', 'Guan ', 'Ze ', 'Zhi ', 'Er ', 'Zhu ', + 0xB0 => 'Shi ', 'Bi ', 'Zi ', 'Er ', 'Gui ', 'Pian ', 'Bian ', 'Mai ', 'Dai ', 'Sheng ', 'Kuang ', 'Fei ', 'Tie ', 'Yi ', 'Chi ', 'Mao ', + 0xC0 => 'He ', 'Bi ', 'Lu ', 'Ren ', 'Hui ', 'Gai ', 'Pian ', 'Zi ', 'Jia ', 'Xu ', 'Zei ', 'Jiao ', 'Gai ', 'Zang ', 'Jian ', 'Ying ', + 0xD0 => 'Xun ', 'Zhen ', 'She ', 'Bin ', 'Bin ', 'Qiu ', 'She ', 'Chuan ', 'Zang ', 'Zhou ', 'Lai ', 'Zan ', 'Si ', 'Chen ', 'Shang ', 'Tian ', + 0xE0 => 'Pei ', 'Geng ', 'Xian ', 'Mai ', 'Jian ', 'Sui ', 'Fu ', 'Tan ', 'Cong ', 'Cong ', 'Zhi ', 'Ji ', 'Zhang ', 'Du ', 'Jin ', 'Xiong ', + 0xF0 => 'Shun ', 'Yun ', 'Bao ', 'Zai ', 'Lai ', 'Feng ', 'Cang ', 'Ji ', 'Sheng ', 'Ai ', 'Zhuan ', 'Fu ', 'Gou ', 'Sai ', 'Ze ', 'Liao ', +]; diff --git a/resources/transliteration-data/x8d.php b/resources/transliteration-data/x8d.php new file mode 100644 index 000000000..3cecb13b4 --- /dev/null +++ b/resources/transliteration-data/x8d.php @@ -0,0 +1,20 @@ + 'Wei ', 'Bai ', 'Chen ', 'Zhuan ', 'Zhi ', 'Zhui ', 'Biao ', 'Yun ', 'Zeng ', 'Tan ', 'Zan ', 'Yan ', null, 'Shan ', 'Wan ', 'Ying ', + 0x10 => 'Jin ', 'Gan ', 'Xian ', 'Zang ', 'Bi ', 'Du ', 'Shu ', 'Yan ', null, 'Xuan ', 'Long ', 'Gan ', 'Zang ', 'Bei ', 'Zhen ', 'Fu ', + 0x20 => 'Yuan ', 'Gong ', 'Cai ', 'Ze ', 'Xian ', 'Bai ', 'Zhang ', 'Huo ', 'Zhi ', 'Fan ', 'Tan ', 'Pin ', 'Bian ', 'Gou ', 'Zhu ', 'Guan ', + 0x30 => 'Er ', 'Jian ', 'Bi ', 'Shi ', 'Tie ', 'Gui ', 'Kuang ', 'Dai ', 'Mao ', 'Fei ', 'He ', 'Yi ', 'Zei ', 'Zhi ', 'Jia ', 'Hui ', + 0x40 => 'Zi ', 'Ren ', 'Lu ', 'Zang ', 'Zi ', 'Gai ', 'Jin ', 'Qiu ', 'Zhen ', 'Lai ', 'She ', 'Fu ', 'Du ', 'Ji ', 'Shu ', 'Shang ', + 0x50 => 'Si ', 'Bi ', 'Zhou ', 'Geng ', 'Pei ', 'Tan ', 'Lai ', 'Feng ', 'Zhui ', 'Fu ', 'Zhuan ', 'Sai ', 'Ze ', 'Yan ', 'Zan ', 'Yun ', + 0x60 => 'Zeng ', 'Shan ', 'Ying ', 'Gan ', 'Chi ', 'Xi ', 'She ', 'Nan ', 'Xiong ', 'Xi ', 'Cheng ', 'He ', 'Cheng ', 'Zhe ', 'Xia ', 'Tang ', + 0x70 => 'Zou ', 'Zou ', 'Li ', 'Jiu ', 'Fu ', 'Zhao ', 'Gan ', 'Qi ', 'Shan ', 'Qiong ', 'Qin ', 'Xian ', 'Ci ', 'Jue ', 'Qin ', 'Chi ', + 0x80 => 'Ci ', 'Chen ', 'Chen ', 'Die ', 'Ju ', 'Chao ', 'Di ', 'Se ', 'Zhan ', 'Zhu ', 'Yue ', 'Qu ', 'Jie ', 'Chi ', 'Chu ', 'Gua ', + 0x90 => 'Xue ', 'Ci ', 'Tiao ', 'Duo ', 'Lie ', 'Gan ', 'Suo ', 'Cu ', 'Xi ', 'Zhao ', 'Su ', 'Yin ', 'Ju ', 'Jian ', 'Que ', 'Tang ', + 0xA0 => 'Chuo ', 'Cui ', 'Lu ', 'Qu ', 'Dang ', 'Qiu ', 'Zi ', 'Ti ', 'Qu ', 'Chi ', 'Huang ', 'Qiao ', 'Qiao ', 'Yao ', 'Zao ', 'Ti ', + 0xB0 => null, 'Zan ', 'Zan ', 'Zu ', 'Pa ', 'Bao ', 'Ku ', 'Ke ', 'Dun ', 'Jue ', 'Fu ', 'Chen ', 'Jian ', 'Fang ', 'Zhi ', 'Sa ', + 0xC0 => 'Yue ', 'Pa ', 'Qi ', 'Yue ', 'Qiang ', 'Tuo ', 'Tai ', 'Yi ', 'Nian ', 'Ling ', 'Mei ', 'Ba ', 'Die ', 'Ku ', 'Tuo ', 'Jia ', + 0xD0 => 'Ci ', 'Pao ', 'Qia ', 'Zhu ', 'Ju ', 'Die ', 'Zhi ', 'Fu ', 'Pan ', 'Ju ', 'Shan ', 'Bo ', 'Ni ', 'Ju ', 'Li ', 'Gen ', + 0xE0 => 'Yi ', 'Ji ', 'Dai ', 'Xian ', 'Jiao ', 'Duo ', 'Zhu ', 'Zhuan ', 'Kua ', 'Zhuai ', 'Gui ', 'Qiong ', 'Kui ', 'Xiang ', 'Chi ', 'Lu ', + 0xF0 => 'Beng ', 'Zhi ', 'Jia ', 'Tiao ', 'Cai ', 'Jian ', 'Ta ', 'Qiao ', 'Bi ', 'Xian ', 'Duo ', 'Ji ', 'Ju ', 'Ji ', 'Shu ', 'Tu ', +]; diff --git a/resources/transliteration-data/x8e.php b/resources/transliteration-data/x8e.php new file mode 100644 index 000000000..6a2f52bf1 --- /dev/null +++ b/resources/transliteration-data/x8e.php @@ -0,0 +1,20 @@ + 'Chu ', 'Jing ', 'Nie ', 'Xiao ', 'Bo ', 'Chi ', 'Qun ', 'Mou ', 'Shu ', 'Lang ', 'Yong ', 'Jiao ', 'Chou ', 'Qiao ', null, 'Ta ', + 0x10 => 'Jian ', 'Qi ', 'Wo ', 'Wei ', 'Zhuo ', 'Jie ', 'Ji ', 'Nie ', 'Ju ', 'Ju ', 'Lun ', 'Lu ', 'Leng ', 'Huai ', 'Ju ', 'Chi ', + 0x20 => 'Wan ', 'Quan ', 'Ti ', 'Bo ', 'Zu ', 'Qie ', 'Ji ', 'Cu ', 'Zong ', 'Cai ', 'Zong ', 'Peng ', 'Zhi ', 'Zheng ', 'Dian ', 'Zhi ', + 0x30 => 'Yu ', 'Duo ', 'Dun ', 'Chun ', 'Yong ', 'Zhong ', 'Di ', 'Zhe ', 'Chen ', 'Chuai ', 'Jian ', 'Gua ', 'Tang ', 'Ju ', 'Fu ', 'Zu ', + 0x40 => 'Die ', 'Pian ', 'Rou ', 'Nuo ', 'Ti ', 'Cha ', 'Tui ', 'Jian ', 'Dao ', 'Cuo ', 'Xi ', 'Ta ', 'Qiang ', 'Zhan ', 'Dian ', 'Ti ', + 0x50 => 'Ji ', 'Nie ', 'Man ', 'Liu ', 'Zhan ', 'Bi ', 'Chong ', 'Lu ', 'Liao ', 'Cu ', 'Tang ', 'Dai ', 'Suo ', 'Xi ', 'Kui ', 'Ji ', + 0x60 => 'Zhi ', 'Qiang ', 'Di ', 'Man ', 'Zong ', 'Lian ', 'Beng ', 'Zao ', 'Nian ', 'Bie ', 'Tui ', 'Ju ', 'Deng ', 'Ceng ', 'Xian ', 'Fan ', + 0x70 => 'Chu ', 'Zhong ', 'Dun ', 'Bo ', 'Cu ', 'Zu ', 'Jue ', 'Jue ', 'Lin ', 'Ta ', 'Qiao ', 'Qiao ', 'Pu ', 'Liao ', 'Dun ', 'Cuan ', + 0x80 => 'Kuang ', 'Zao ', 'Ta ', 'Bi ', 'Bi ', 'Zhu ', 'Ju ', 'Chu ', 'Qiao ', 'Dun ', 'Chou ', 'Ji ', 'Wu ', 'Yue ', 'Nian ', 'Lin ', + 0x90 => 'Lie ', 'Zhi ', 'Li ', 'Zhi ', 'Chan ', 'Chu ', 'Duan ', 'Wei ', 'Long ', 'Lin ', 'Xian ', 'Wei ', 'Zuan ', 'Lan ', 'Xie ', 'Rang ', + 0xA0 => 'Xie ', 'Nie ', 'Ta ', 'Qu ', 'Jie ', 'Cuan ', 'Zuan ', 'Xi ', 'Kui ', 'Jue ', 'Lin ', 'Shen ', 'Gong ', 'Dan ', 'Segare ', 'Qu ', + 0xB0 => 'Ti ', 'Duo ', 'Duo ', 'Gong ', 'Lang ', 'Nerau ', 'Luo ', 'Ai ', 'Ji ', 'Ju ', 'Tang ', 'Utsuke ', null, 'Yan ', 'Shitsuke ', 'Kang ', + 0xC0 => 'Qu ', 'Lou ', 'Lao ', 'Tuo ', 'Zhi ', 'Yagate ', 'Ti ', 'Dao ', 'Yagate ', 'Yu ', 'Che ', 'Ya ', 'Gui ', 'Jun ', 'Wei ', 'Yue ', + 0xD0 => 'Xin ', 'Di ', 'Xuan ', 'Fan ', 'Ren ', 'Shan ', 'Qiang ', 'Shu ', 'Tun ', 'Chen ', 'Dai ', 'E ', 'Na ', 'Qi ', 'Mao ', 'Ruan ', + 0xE0 => 'Ren ', 'Fan ', 'Zhuan ', 'Hong ', 'Hu ', 'Qu ', 'Huang ', 'Di ', 'Ling ', 'Dai ', 'Ao ', 'Zhen ', 'Fan ', 'Kuang ', 'Ang ', 'Peng ', + 0xF0 => 'Bei ', 'Gu ', 'Ku ', 'Pao ', 'Zhu ', 'Rong ', 'E ', 'Ba ', 'Zhou ', 'Zhi ', 'Yao ', 'Ke ', 'Yi ', 'Qing ', 'Shi ', 'Ping ', +]; diff --git a/resources/transliteration-data/x8f.php b/resources/transliteration-data/x8f.php new file mode 100644 index 000000000..457dbcd37 --- /dev/null +++ b/resources/transliteration-data/x8f.php @@ -0,0 +1,20 @@ + 'Er ', 'Qiong ', 'Ju ', 'Jiao ', 'Guang ', 'Lu ', 'Kai ', 'Quan ', 'Zhou ', 'Zai ', 'Zhi ', 'She ', 'Liang ', 'Yu ', 'Shao ', 'You ', + 0x10 => 'Huan ', 'Yun ', 'Zhe ', 'Wan ', 'Fu ', 'Qing ', 'Zhou ', 'Ni ', 'Ling ', 'Zhe ', 'Zhan ', 'Liang ', 'Zi ', 'Hui ', 'Wang ', 'Chuo ', + 0x20 => 'Guo ', 'Kan ', 'Yi ', 'Peng ', 'Qian ', 'Gun ', 'Nian ', 'Pian ', 'Guan ', 'Bei ', 'Lun ', 'Pai ', 'Liang ', 'Ruan ', 'Rou ', 'Ji ', + 0x30 => 'Yang ', 'Xian ', 'Chuan ', 'Cou ', 'Qun ', 'Ge ', 'You ', 'Hong ', 'Shu ', 'Fu ', 'Zi ', 'Fu ', 'Wen ', 'Ben ', 'Zhan ', 'Yu ', + 0x40 => 'Wen ', 'Tao ', 'Gu ', 'Zhen ', 'Xia ', 'Yuan ', 'Lu ', 'Jiu ', 'Chao ', 'Zhuan ', 'Wei ', 'Hun ', 'Sori ', 'Che ', 'Jiao ', 'Zhan ', + 0x50 => 'Pu ', 'Lao ', 'Fen ', 'Fan ', 'Lin ', 'Ge ', 'Se ', 'Kan ', 'Huan ', 'Yi ', 'Ji ', 'Dui ', 'Er ', 'Yu ', 'Xian ', 'Hong ', + 0x60 => 'Lei ', 'Pei ', 'Li ', 'Li ', 'Lu ', 'Lin ', 'Che ', 'Ya ', 'Gui ', 'Xuan ', 'Di ', 'Ren ', 'Zhuan ', 'E ', 'Lun ', 'Ruan ', + 0x70 => 'Hong ', 'Ku ', 'Ke ', 'Lu ', 'Zhou ', 'Zhi ', 'Yi ', 'Hu ', 'Zhen ', 'Li ', 'Yao ', 'Qing ', 'Shi ', 'Zai ', 'Zhi ', 'Jiao ', + 0x80 => 'Zhou ', 'Quan ', 'Lu ', 'Jiao ', 'Zhe ', 'Fu ', 'Liang ', 'Nian ', 'Bei ', 'Hui ', 'Gun ', 'Wang ', 'Liang ', 'Chuo ', 'Zi ', 'Cou ', + 0x90 => 'Fu ', 'Ji ', 'Wen ', 'Shu ', 'Pei ', 'Yuan ', 'Xia ', 'Zhan ', 'Lu ', 'Che ', 'Lin ', 'Xin ', 'Gu ', 'Ci ', 'Ci ', 'Pi ', + 0xA0 => 'Zui ', 'Bian ', 'La ', 'La ', 'Ci ', 'Xue ', 'Ban ', 'Bian ', 'Bian ', 'Bian ', null, 'Bian ', 'Ban ', 'Ci ', 'Bian ', 'Bian ', + 0xB0 => 'Chen ', 'Ru ', 'Nong ', 'Nong ', 'Zhen ', 'Chuo ', 'Chuo ', 'Suberu ', 'Reng ', 'Bian ', 'Bian ', 'Sip ', 'Ip ', 'Liao ', 'Da ', 'Chan ', + 0xC0 => 'Gan ', 'Qian ', 'Yu ', 'Yu ', 'Qi ', 'Xun ', 'Yi ', 'Guo ', 'Mai ', 'Qi ', 'Za ', 'Wang ', 'Jia ', 'Zhun ', 'Ying ', 'Ti ', + 0xD0 => 'Yun ', 'Jin ', 'Hang ', 'Ya ', 'Fan ', 'Wu ', 'Da ', 'E ', 'Huan ', 'Zhe ', 'Totemo ', 'Jin ', 'Yuan ', 'Wei ', 'Lian ', 'Chi ', + 0xE0 => 'Che ', 'Ni ', 'Tiao ', 'Zhi ', 'Yi ', 'Jiong ', 'Jia ', 'Chen ', 'Dai ', 'Er ', 'Di ', 'Po ', 'Wang ', 'Die ', 'Ze ', 'Tao ', + 0xF0 => 'Shu ', 'Tuo ', 'Kep ', 'Jing ', 'Hui ', 'Tong ', 'You ', 'Mi ', 'Beng ', 'Ji ', 'Nai ', 'Yi ', 'Jie ', 'Zhui ', 'Lie ', 'Xun ', +]; diff --git a/resources/transliteration-data/x90.php b/resources/transliteration-data/x90.php new file mode 100644 index 000000000..a62d0ab3a --- /dev/null +++ b/resources/transliteration-data/x90.php @@ -0,0 +1,20 @@ + 'Tui ', 'Song ', 'Gua ', 'Tao ', 'Pang ', 'Hou ', 'Ni ', 'Dun ', 'Jiong ', 'Xuan ', 'Xun ', 'Bu ', 'You ', 'Xiao ', 'Qiu ', 'Tou ', + 0x10 => 'Zhu ', 'Qiu ', 'Di ', 'Di ', 'Tu ', 'Jing ', 'Ti ', 'Dou ', 'Yi ', 'Zhe ', 'Tong ', 'Guang ', 'Wu ', 'Shi ', 'Cheng ', 'Su ', + 0x20 => 'Zao ', 'Qun ', 'Feng ', 'Lian ', 'Suo ', 'Hui ', 'Li ', 'Sako ', 'Lai ', 'Ben ', 'Cuo ', 'Jue ', 'Beng ', 'Huan ', 'Dai ', 'Lu ', + 0x30 => 'You ', 'Zhou ', 'Jin ', 'Yu ', 'Chuo ', 'Kui ', 'Wei ', 'Ti ', 'Yi ', 'Da ', 'Yuan ', 'Luo ', 'Bi ', 'Nuo ', 'Yu ', 'Dang ', + 0x40 => 'Sui ', 'Dun ', 'Sui ', 'Yan ', 'Chuan ', 'Chi ', 'Ti ', 'Yu ', 'Shi ', 'Zhen ', 'You ', 'Yun ', 'E ', 'Bian ', 'Guo ', 'E ', + 0x50 => 'Xia ', 'Huang ', 'Qiu ', 'Dao ', 'Da ', 'Wei ', 'Appare ', 'Yi ', 'Gou ', 'Yao ', 'Chu ', 'Liu ', 'Xun ', 'Ta ', 'Di ', 'Chi ', + 0x60 => 'Yuan ', 'Su ', 'Ta ', 'Qian ', null, 'Yao ', 'Guan ', 'Zhang ', 'Ao ', 'Shi ', 'Ce ', 'Chi ', 'Su ', 'Zao ', 'Zhe ', 'Dun ', + 0x70 => 'Di ', 'Lou ', 'Chi ', 'Cuo ', 'Lin ', 'Zun ', 'Rao ', 'Qian ', 'Xuan ', 'Yu ', 'Yi ', 'Wu ', 'Liao ', 'Ju ', 'Shi ', 'Bi ', + 0x80 => 'Yao ', 'Mai ', 'Xie ', 'Sui ', 'Huan ', 'Zhan ', 'Teng ', 'Er ', 'Miao ', 'Bian ', 'Bian ', 'La ', 'Li ', 'Yuan ', 'Yao ', 'Luo ', + 0x90 => 'Li ', 'Yi ', 'Ting ', 'Deng ', 'Qi ', 'Yong ', 'Shan ', 'Han ', 'Yu ', 'Mang ', 'Ru ', 'Qiong ', null, 'Kuang ', 'Fu ', 'Kang ', + 0xA0 => 'Bin ', 'Fang ', 'Xing ', 'Na ', 'Xin ', 'Shen ', 'Bang ', 'Yuan ', 'Cun ', 'Huo ', 'Xie ', 'Bang ', 'Wu ', 'Ju ', 'You ', 'Han ', + 0xB0 => 'Tai ', 'Qiu ', 'Bi ', 'Pei ', 'Bing ', 'Shao ', 'Bei ', 'Wa ', 'Di ', 'Zou ', 'Ye ', 'Lin ', 'Kuang ', 'Gui ', 'Zhu ', 'Shi ', + 0xC0 => 'Ku ', 'Yu ', 'Gai ', 'Ge ', 'Xi ', 'Zhi ', 'Ji ', 'Xun ', 'Hou ', 'Xing ', 'Jiao ', 'Xi ', 'Gui ', 'Nuo ', 'Lang ', 'Jia ', + 0xD0 => 'Kuai ', 'Zheng ', 'Otoko ', 'Yun ', 'Yan ', 'Cheng ', 'Dou ', 'Chi ', 'Lu ', 'Fu ', 'Wu ', 'Fu ', 'Gao ', 'Hao ', 'Lang ', 'Jia ', + 0xE0 => 'Geng ', 'Jun ', 'Ying ', 'Bo ', 'Xi ', 'Bei ', 'Li ', 'Yun ', 'Bu ', 'Xiao ', 'Qi ', 'Pi ', 'Qing ', 'Guo ', 'Zhou ', 'Tan ', + 0xF0 => 'Zou ', 'Ping ', 'Lai ', 'Ni ', 'Chen ', 'You ', 'Bu ', 'Xiang ', 'Dan ', 'Ju ', 'Yong ', 'Qiao ', 'Yi ', 'Du ', 'Yan ', 'Mei ', +]; diff --git a/resources/transliteration-data/x91.php b/resources/transliteration-data/x91.php new file mode 100644 index 000000000..64b464b0d --- /dev/null +++ b/resources/transliteration-data/x91.php @@ -0,0 +1,20 @@ + 'Ruo ', 'Bei ', 'E ', 'Yu ', 'Juan ', 'Yu ', 'Yun ', 'Hou ', 'Kui ', 'Xiang ', 'Xiang ', 'Sou ', 'Tang ', 'Ming ', 'Xi ', 'Ru ', + 0x10 => 'Chu ', 'Zi ', 'Zou ', 'Ju ', 'Wu ', 'Xiang ', 'Yun ', 'Hao ', 'Yong ', 'Bi ', 'Mo ', 'Chao ', 'Fu ', 'Liao ', 'Yin ', 'Zhuan ', + 0x20 => 'Hu ', 'Qiao ', 'Yan ', 'Zhang ', 'Fan ', 'Qiao ', 'Xu ', 'Deng ', 'Bi ', 'Xin ', 'Bi ', 'Ceng ', 'Wei ', 'Zheng ', 'Mao ', 'Shan ', + 0x30 => 'Lin ', 'Po ', 'Dan ', 'Meng ', 'Ye ', 'Cao ', 'Kuai ', 'Feng ', 'Meng ', 'Zou ', 'Kuang ', 'Lian ', 'Zan ', 'Chan ', 'You ', 'Qi ', + 0x40 => 'Yan ', 'Chan ', 'Zan ', 'Ling ', 'Huan ', 'Xi ', 'Feng ', 'Zan ', 'Li ', 'You ', 'Ding ', 'Qiu ', 'Zhuo ', 'Pei ', 'Zhou ', 'Yi ', + 0x50 => 'Hang ', 'Yu ', 'Jiu ', 'Yan ', 'Zui ', 'Mao ', 'Dan ', 'Xu ', 'Tou ', 'Zhen ', 'Fen ', 'Sakenomoto ', null, 'Yun ', 'Tai ', 'Tian ', + 0x60 => 'Qia ', 'Tuo ', 'Zuo ', 'Han ', 'Gu ', 'Su ', 'Po ', 'Chou ', 'Zai ', 'Ming ', 'Luo ', 'Chuo ', 'Chou ', 'You ', 'Tong ', 'Zhi ', + 0x70 => 'Xian ', 'Jiang ', 'Cheng ', 'Yin ', 'Tu ', 'Xiao ', 'Mei ', 'Ku ', 'Suan ', 'Lei ', 'Pu ', 'Zui ', 'Hai ', 'Yan ', 'Xi ', 'Niang ', + 0x80 => 'Wei ', 'Lu ', 'Lan ', 'Yan ', 'Tao ', 'Pei ', 'Zhan ', 'Chun ', 'Tan ', 'Zui ', 'Chuo ', 'Cu ', 'Kun ', 'Ti ', 'Mian ', 'Du ', + 0x90 => 'Hu ', 'Xu ', 'Xing ', 'Tan ', 'Jiu ', 'Chun ', 'Yun ', 'Po ', 'Ke ', 'Sou ', 'Mi ', 'Quan ', 'Chou ', 'Cuo ', 'Yun ', 'Yong ', + 0xA0 => 'Ang ', 'Zha ', 'Hai ', 'Tang ', 'Jiang ', 'Piao ', 'Shan ', 'Yu ', 'Li ', 'Zao ', 'Lao ', 'Yi ', 'Jiang ', 'Pu ', 'Jiao ', 'Xi ', + 0xB0 => 'Tan ', 'Po ', 'Nong ', 'Yi ', 'Li ', 'Ju ', 'Jiao ', 'Yi ', 'Niang ', 'Ru ', 'Xun ', 'Chou ', 'Yan ', 'Ling ', 'Mi ', 'Mi ', + 0xC0 => 'Niang ', 'Xin ', 'Jiao ', 'Xi ', 'Mi ', 'Yan ', 'Bian ', 'Cai ', 'Shi ', 'You ', 'Shi ', 'Shi ', 'Li ', 'Chong ', 'Ye ', 'Liang ', + 0xD0 => 'Li ', 'Jin ', 'Jin ', 'Qiu ', 'Yi ', 'Diao ', 'Dao ', 'Zhao ', 'Ding ', 'Po ', 'Qiu ', 'He ', 'Fu ', 'Zhen ', 'Zhi ', 'Ba ', + 0xE0 => 'Luan ', 'Fu ', 'Nai ', 'Diao ', 'Shan ', 'Qiao ', 'Kou ', 'Chuan ', 'Zi ', 'Fan ', 'Yu ', 'Hua ', 'Han ', 'Gong ', 'Qi ', 'Mang ', + 0xF0 => 'Ri ', 'Di ', 'Si ', 'Xi ', 'Yi ', 'Chai ', 'Shi ', 'Tu ', 'Xi ', 'Nu ', 'Qian ', 'Ishiyumi ', 'Jian ', 'Pi ', 'Ye ', 'Yin ', +]; diff --git a/resources/transliteration-data/x92.php b/resources/transliteration-data/x92.php new file mode 100644 index 000000000..8543f86d4 --- /dev/null +++ b/resources/transliteration-data/x92.php @@ -0,0 +1,20 @@ + 'Ba ', 'Fang ', 'Chen ', 'Xing ', 'Tou ', 'Yue ', 'Yan ', 'Fu ', 'Pi ', 'Na ', 'Xin ', 'E ', 'Jue ', 'Dun ', 'Gou ', 'Yin ', + 0x10 => 'Qian ', 'Ban ', 'Ji ', 'Ren ', 'Chao ', 'Niu ', 'Fen ', 'Yun ', 'Ji ', 'Qin ', 'Pi ', 'Guo ', 'Hong ', 'Yin ', 'Jun ', 'Shi ', + 0x20 => 'Yi ', 'Zhong ', 'Nie ', 'Gai ', 'Ri ', 'Huo ', 'Tai ', 'Kang ', 'Habaki ', 'Irori ', 'Ngaak ', null, 'Duo ', 'Zi ', 'Ni ', 'Tu ', + 0x30 => 'Shi ', 'Min ', 'Gu ', 'E ', 'Ling ', 'Bing ', 'Yi ', 'Gu ', 'Ba ', 'Pi ', 'Yu ', 'Si ', 'Zuo ', 'Bu ', 'You ', 'Dian ', + 0x40 => 'Jia ', 'Zhen ', 'Shi ', 'Shi ', 'Tie ', 'Ju ', 'Zhan ', 'Shi ', 'She ', 'Xuan ', 'Zhao ', 'Bao ', 'He ', 'Bi ', 'Sheng ', 'Chu ', + 0x50 => 'Shi ', 'Bo ', 'Zhu ', 'Chi ', 'Za ', 'Po ', 'Tong ', 'Qian ', 'Fu ', 'Zhai ', 'Liu ', 'Qian ', 'Fu ', 'Li ', 'Yue ', 'Pi ', + 0x60 => 'Yang ', 'Ban ', 'Bo ', 'Jie ', 'Gou ', 'Shu ', 'Zheng ', 'Mu ', 'Ni ', 'Nie ', 'Di ', 'Jia ', 'Mu ', 'Dan ', 'Shen ', 'Yi ', + 0x70 => 'Si ', 'Kuang ', 'Ka ', 'Bei ', 'Jian ', 'Tong ', 'Xing ', 'Hong ', 'Jiao ', 'Chi ', 'Er ', 'Ge ', 'Bing ', 'Shi ', 'Mou ', 'Jia ', + 0x80 => 'Yin ', 'Jun ', 'Zhou ', 'Chong ', 'Shang ', 'Tong ', 'Mo ', 'Lei ', 'Ji ', 'Yu ', 'Xu ', 'Ren ', 'Zun ', 'Zhi ', 'Qiong ', 'Shan ', + 0x90 => 'Chi ', 'Xian ', 'Xing ', 'Quan ', 'Pi ', 'Tie ', 'Zhu ', 'Hou ', 'Ming ', 'Kua ', 'Yao ', 'Xian ', 'Xian ', 'Xiu ', 'Jun ', 'Cha ', + 0xA0 => 'Lao ', 'Ji ', 'Pi ', 'Ru ', 'Mi ', 'Yi ', 'Yin ', 'Guang ', 'An ', 'Diou ', 'You ', 'Se ', 'Kao ', 'Qian ', 'Luan ', 'Kasugai ', + 0xB0 => 'Ai ', 'Diao ', 'Han ', 'Rui ', 'Shi ', 'Keng ', 'Qiu ', 'Xiao ', 'Zhe ', 'Xiu ', 'Zang ', 'Ti ', 'Cuo ', 'Gua ', 'Gong ', 'Zhong ', + 0xC0 => 'Dou ', 'Lu ', 'Mei ', 'Lang ', 'Wan ', 'Xin ', 'Yun ', 'Bei ', 'Wu ', 'Su ', 'Yu ', 'Chan ', 'Ting ', 'Bo ', 'Han ', 'Jia ', + 0xD0 => 'Hong ', 'Cuan ', 'Feng ', 'Chan ', 'Wan ', 'Zhi ', 'Si ', 'Xuan ', 'Wu ', 'Wu ', 'Tiao ', 'Gong ', 'Zhuo ', 'Lue ', 'Xing ', 'Qian ', + 0xE0 => 'Shen ', 'Han ', 'Lue ', 'Xie ', 'Chu ', 'Zheng ', 'Ju ', 'Xian ', 'Tie ', 'Mang ', 'Pu ', 'Li ', 'Pan ', 'Rui ', 'Cheng ', 'Gao ', + 0xF0 => 'Li ', 'Te ', 'Pyeng ', 'Zhu ', null, 'Tu ', 'Liu ', 'Zui ', 'Ju ', 'Chang ', 'Yuan ', 'Jian ', 'Gang ', 'Diao ', 'Tao ', 'Chang ', +]; diff --git a/resources/transliteration-data/x93.php b/resources/transliteration-data/x93.php new file mode 100644 index 000000000..c506ad70d --- /dev/null +++ b/resources/transliteration-data/x93.php @@ -0,0 +1,20 @@ + 'Lun ', 'Kua ', 'Ling ', 'Bei ', 'Lu ', 'Li ', 'Qiang ', 'Pou ', 'Juan ', 'Min ', 'Zui ', 'Peng ', 'An ', 'Pi ', 'Xian ', 'Ya ', + 0x10 => 'Zhui ', 'Lei ', 'A ', 'Kong ', 'Ta ', 'Kun ', 'Du ', 'Wei ', 'Chui ', 'Zi ', 'Zheng ', 'Ben ', 'Nie ', 'Cong ', 'Qun ', 'Tan ', + 0x20 => 'Ding ', 'Qi ', 'Qian ', 'Zhuo ', 'Qi ', 'Yu ', 'Jin ', 'Guan ', 'Mao ', 'Chang ', 'Tian ', 'Xi ', 'Lian ', 'Tao ', 'Gu ', 'Cuo ', + 0x30 => 'Shu ', 'Zhen ', 'Lu ', 'Meng ', 'Lu ', 'Hua ', 'Biao ', 'Ga ', 'Lai ', 'Ken ', 'Kazari ', 'Bu ', 'Nai ', 'Wan ', 'Zan ', null, + 0x40 => 'De ', 'Xian ', null, 'Huo ', 'Liang ', null, 'Men ', 'Kai ', 'Ying ', 'Di ', 'Lian ', 'Guo ', 'Xian ', 'Du ', 'Tu ', 'Wei ', + 0x50 => 'Cong ', 'Fu ', 'Rou ', 'Ji ', 'E ', 'Rou ', 'Chen ', 'Ti ', 'Zha ', 'Hong ', 'Yang ', 'Duan ', 'Xia ', 'Yu ', 'Keng ', 'Xing ', + 0x60 => 'Huang ', 'Wei ', 'Fu ', 'Zhao ', 'Cha ', 'Qie ', 'She ', 'Hong ', 'Kui ', 'Tian ', 'Mou ', 'Qiao ', 'Qiao ', 'Hou ', 'Tou ', 'Cong ', + 0x70 => 'Huan ', 'Ye ', 'Min ', 'Jian ', 'Duan ', 'Jian ', 'Song ', 'Kui ', 'Hu ', 'Xuan ', 'Duo ', 'Jie ', 'Zhen ', 'Bian ', 'Zhong ', 'Zi ', + 0x80 => 'Xiu ', 'Ye ', 'Mei ', 'Pai ', 'Ai ', 'Jie ', null, 'Mei ', 'Chuo ', 'Ta ', 'Bang ', 'Xia ', 'Lian ', 'Suo ', 'Xi ', 'Liu ', + 0x90 => 'Zu ', 'Ye ', 'Nou ', 'Weng ', 'Rong ', 'Tang ', 'Suo ', 'Qiang ', 'Ge ', 'Shuo ', 'Chui ', 'Bo ', 'Pan ', 'Sa ', 'Bi ', 'Sang ', + 0xA0 => 'Gang ', 'Zi ', 'Wu ', 'Ying ', 'Huang ', 'Tiao ', 'Liu ', 'Kai ', 'Sun ', 'Sha ', 'Sou ', 'Wan ', 'Hao ', 'Zhen ', 'Zhen ', 'Luo ', + 0xB0 => 'Yi ', 'Yuan ', 'Tang ', 'Nie ', 'Xi ', 'Jia ', 'Ge ', 'Ma ', 'Juan ', 'Kasugai ', 'Habaki ', 'Suo ', null, null, null, 'Na ', + 0xC0 => 'Lu ', 'Suo ', 'Ou ', 'Zu ', 'Tuan ', 'Xiu ', 'Guan ', 'Xuan ', 'Lian ', 'Shou ', 'Ao ', 'Man ', 'Mo ', 'Luo ', 'Bi ', 'Wei ', + 0xD0 => 'Liu ', 'Di ', 'Qiao ', 'Cong ', 'Yi ', 'Lu ', 'Ao ', 'Keng ', 'Qiang ', 'Cui ', 'Qi ', 'Chang ', 'Tang ', 'Man ', 'Yong ', 'Chan ', + 0xE0 => 'Feng ', 'Jing ', 'Biao ', 'Shu ', 'Lou ', 'Xiu ', 'Cong ', 'Long ', 'Zan ', 'Jian ', 'Cao ', 'Li ', 'Xia ', 'Xi ', 'Kang ', null, + 0xF0 => 'Beng ', null, null, 'Zheng ', 'Lu ', 'Hua ', 'Ji ', 'Pu ', 'Hui ', 'Qiang ', 'Po ', 'Lin ', 'Suo ', 'Xiu ', 'San ', 'Cheng ', +]; diff --git a/resources/transliteration-data/x94.php b/resources/transliteration-data/x94.php new file mode 100644 index 000000000..9533c874c --- /dev/null +++ b/resources/transliteration-data/x94.php @@ -0,0 +1,20 @@ + 'Kui ', 'Si ', 'Liu ', 'Nao ', 'Heng ', 'Pie ', 'Sui ', 'Fan ', 'Qiao ', 'Quan ', 'Yang ', 'Tang ', 'Xiang ', 'Jue ', 'Jiao ', 'Zun ', + 0x10 => 'Liao ', 'Jie ', 'Lao ', 'Dui ', 'Tan ', 'Zan ', 'Ji ', 'Jian ', 'Zhong ', 'Deng ', 'Ya ', 'Ying ', 'Dui ', 'Jue ', 'Nou ', 'Ti ', + 0x20 => 'Pu ', 'Tie ', null, null, 'Ding ', 'Shan ', 'Kai ', 'Jian ', 'Fei ', 'Sui ', 'Lu ', 'Juan ', 'Hui ', 'Yu ', 'Lian ', 'Zhuo ', + 0x30 => 'Qiao ', 'Qian ', 'Zhuo ', 'Lei ', 'Bi ', 'Tie ', 'Huan ', 'Ye ', 'Duo ', 'Guo ', 'Dang ', 'Ju ', 'Fen ', 'Da ', 'Bei ', 'Yi ', + 0x40 => 'Ai ', 'Zong ', 'Xun ', 'Diao ', 'Zhu ', 'Heng ', 'Zhui ', 'Ji ', 'Nie ', 'Ta ', 'Huo ', 'Qing ', 'Bin ', 'Ying ', 'Kui ', 'Ning ', + 0x50 => 'Xu ', 'Jian ', 'Jian ', 'Yari ', 'Cha ', 'Zhi ', 'Mie ', 'Li ', 'Lei ', 'Ji ', 'Zuan ', 'Kuang ', 'Shang ', 'Peng ', 'La ', 'Du ', + 0x60 => 'Shuo ', 'Chuo ', 'Lu ', 'Biao ', 'Bao ', 'Lu ', null, null, 'Long ', 'E ', 'Lu ', 'Xin ', 'Jian ', 'Lan ', 'Bo ', 'Jian ', + 0x70 => 'Yao ', 'Chan ', 'Xiang ', 'Jian ', 'Xi ', 'Guan ', 'Cang ', 'Nie ', 'Lei ', 'Cuan ', 'Qu ', 'Pan ', 'Luo ', 'Zuan ', 'Luan ', 'Zao ', + 0x80 => 'Nie ', 'Jue ', 'Tang ', 'Shu ', 'Lan ', 'Jin ', 'Qiu ', 'Yi ', 'Zhen ', 'Ding ', 'Zhao ', 'Po ', 'Diao ', 'Tu ', 'Qian ', 'Chuan ', + 0x90 => 'Shan ', 'Ji ', 'Fan ', 'Diao ', 'Men ', 'Nu ', 'Xi ', 'Chai ', 'Xing ', 'Gai ', 'Bu ', 'Tai ', 'Ju ', 'Dun ', 'Chao ', 'Zhong ', + 0xA0 => 'Na ', 'Bei ', 'Gang ', 'Ban ', 'Qian ', 'Yao ', 'Qin ', 'Jun ', 'Wu ', 'Gou ', 'Kang ', 'Fang ', 'Huo ', 'Tou ', 'Niu ', 'Ba ', + 0xB0 => 'Yu ', 'Qian ', 'Zheng ', 'Qian ', 'Gu ', 'Bo ', 'E ', 'Po ', 'Bu ', 'Ba ', 'Yue ', 'Zuan ', 'Mu ', 'Dan ', 'Jia ', 'Dian ', + 0xC0 => 'You ', 'Tie ', 'Bo ', 'Ling ', 'Shuo ', 'Qian ', 'Liu ', 'Bao ', 'Shi ', 'Xuan ', 'She ', 'Bi ', 'Ni ', 'Pi ', 'Duo ', 'Xing ', + 0xD0 => 'Kao ', 'Lao ', 'Er ', 'Mang ', 'Ya ', 'You ', 'Cheng ', 'Jia ', 'Ye ', 'Nao ', 'Zhi ', 'Dang ', 'Tong ', 'Lu ', 'Diao ', 'Yin ', + 0xE0 => 'Kai ', 'Zha ', 'Zhu ', 'Xian ', 'Ting ', 'Diu ', 'Xian ', 'Hua ', 'Quan ', 'Sha ', 'Jia ', 'Yao ', 'Ge ', 'Ming ', 'Zheng ', 'Se ', + 0xF0 => 'Jiao ', 'Yi ', 'Chan ', 'Chong ', 'Tang ', 'An ', 'Yin ', 'Ru ', 'Zhu ', 'Lao ', 'Pu ', 'Wu ', 'Lai ', 'Te ', 'Lian ', 'Keng ', +]; diff --git a/resources/transliteration-data/x95.php b/resources/transliteration-data/x95.php new file mode 100644 index 000000000..18a4a592c --- /dev/null +++ b/resources/transliteration-data/x95.php @@ -0,0 +1,20 @@ + 'Xiao ', 'Suo ', 'Li ', 'Zheng ', 'Chu ', 'Guo ', 'Gao ', 'Tie ', 'Xiu ', 'Cuo ', 'Lue ', 'Feng ', 'Xin ', 'Liu ', 'Kai ', 'Jian ', + 0x10 => 'Rui ', 'Ti ', 'Lang ', 'Qian ', 'Ju ', 'A ', 'Qiang ', 'Duo ', 'Tian ', 'Cuo ', 'Mao ', 'Ben ', 'Qi ', 'De ', 'Kua ', 'Kun ', + 0x20 => 'Chang ', 'Xi ', 'Gu ', 'Luo ', 'Chui ', 'Zhui ', 'Jin ', 'Zhi ', 'Xian ', 'Juan ', 'Huo ', 'Pou ', 'Tan ', 'Ding ', 'Jian ', 'Ju ', + 0x30 => 'Meng ', 'Zi ', 'Qie ', 'Ying ', 'Kai ', 'Qiang ', 'Song ', 'E ', 'Cha ', 'Qiao ', 'Zhong ', 'Duan ', 'Sou ', 'Huang ', 'Huan ', 'Ai ', + 0x40 => 'Du ', 'Mei ', 'Lou ', 'Zi ', 'Fei ', 'Mei ', 'Mo ', 'Zhen ', 'Bo ', 'Ge ', 'Nie ', 'Tang ', 'Juan ', 'Nie ', 'Na ', 'Liu ', + 0x50 => 'Hao ', 'Bang ', 'Yi ', 'Jia ', 'Bin ', 'Rong ', 'Biao ', 'Tang ', 'Man ', 'Luo ', 'Beng ', 'Yong ', 'Jing ', 'Di ', 'Zu ', 'Xuan ', + 0x60 => 'Liu ', 'Tan ', 'Jue ', 'Liao ', 'Pu ', 'Lu ', 'Dui ', 'Lan ', 'Pu ', 'Cuan ', 'Qiang ', 'Deng ', 'Huo ', 'Lei ', 'Huan ', 'Zhuo ', + 0x70 => 'Lian ', 'Yi ', 'Cha ', 'Biao ', 'La ', 'Chan ', 'Xiang ', 'Chang ', 'Chang ', 'Jiu ', 'Ao ', 'Die ', 'Qu ', 'Liao ', 'Mi ', 'Chang ', + 0x80 => 'Men ', 'Ma ', 'Shuan ', 'Shan ', 'Huo ', 'Men ', 'Yan ', 'Bi ', 'Han ', 'Bi ', 'San ', 'Kai ', 'Kang ', 'Beng ', 'Hong ', 'Run ', + 0x90 => 'San ', 'Xian ', 'Xian ', 'Jian ', 'Min ', 'Xia ', 'Yuru ', 'Dou ', 'Zha ', 'Nao ', 'Jian ', 'Peng ', 'Xia ', 'Ling ', 'Bian ', 'Bi ', + 0xA0 => 'Run ', 'He ', 'Guan ', 'Ge ', 'Ge ', 'Fa ', 'Chu ', 'Hong ', 'Gui ', 'Min ', 'Se ', 'Kun ', 'Lang ', 'Lu ', 'Ting ', 'Sha ', + 0xB0 => 'Ju ', 'Yue ', 'Yue ', 'Chan ', 'Qu ', 'Lin ', 'Chang ', 'Shai ', 'Kun ', 'Yan ', 'Min ', 'Yan ', 'E ', 'Hun ', 'Yu ', 'Wen ', + 0xC0 => 'Xiang ', 'Bao ', 'Xiang ', 'Qu ', 'Yao ', 'Wen ', 'Ban ', 'An ', 'Wei ', 'Yin ', 'Kuo ', 'Que ', 'Lan ', 'Du ', null, 'Phwung ', + 0xD0 => 'Tian ', 'Nie ', 'Ta ', 'Kai ', 'He ', 'Que ', 'Chuang ', 'Guan ', 'Dou ', 'Qi ', 'Kui ', 'Tang ', 'Guan ', 'Piao ', 'Kan ', 'Xi ', + 0xE0 => 'Hui ', 'Chan ', 'Pi ', 'Dang ', 'Huan ', 'Ta ', 'Wen ', null, 'Men ', 'Shuan ', 'Shan ', 'Yan ', 'Han ', 'Bi ', 'Wen ', 'Chuang ', + 0xF0 => 'Run ', 'Wei ', 'Xian ', 'Hong ', 'Jian ', 'Min ', 'Kang ', 'Men ', 'Zha ', 'Nao ', 'Gui ', 'Wen ', 'Ta ', 'Min ', 'Lu ', 'Kai ', +]; diff --git a/resources/transliteration-data/x96.php b/resources/transliteration-data/x96.php new file mode 100644 index 000000000..c8ecf95e8 --- /dev/null +++ b/resources/transliteration-data/x96.php @@ -0,0 +1,20 @@ + 'Fa ', 'Ge ', 'He ', 'Kun ', 'Jiu ', 'Yue ', 'Lang ', 'Du ', 'Yu ', 'Yan ', 'Chang ', 'Xi ', 'Wen ', 'Hun ', 'Yan ', 'E ', + 0x10 => 'Chan ', 'Lan ', 'Qu ', 'Hui ', 'Kuo ', 'Que ', 'Ge ', 'Tian ', 'Ta ', 'Que ', 'Kan ', 'Huan ', 'Fu ', 'Fu ', 'Le ', 'Dui ', + 0x20 => 'Xin ', 'Qian ', 'Wu ', 'Yi ', 'Tuo ', 'Yin ', 'Yang ', 'Dou ', 'E ', 'Sheng ', 'Ban ', 'Pei ', 'Keng ', 'Yun ', 'Ruan ', 'Zhi ', + 0x30 => 'Pi ', 'Jing ', 'Fang ', 'Yang ', 'Yin ', 'Zhen ', 'Jie ', 'Cheng ', 'E ', 'Qu ', 'Di ', 'Zu ', 'Zuo ', 'Dian ', 'Ling ', 'A ', + 0x40 => 'Tuo ', 'Tuo ', 'Po ', 'Bing ', 'Fu ', 'Ji ', 'Lu ', 'Long ', 'Chen ', 'Xing ', 'Duo ', 'Lou ', 'Mo ', 'Jiang ', 'Shu ', 'Duo ', + 0x50 => 'Xian ', 'Er ', 'Gui ', 'Yu ', 'Gai ', 'Shan ', 'Xun ', 'Qiao ', 'Xing ', 'Chun ', 'Fu ', 'Bi ', 'Xia ', 'Shan ', 'Sheng ', 'Zhi ', + 0x60 => 'Pu ', 'Dou ', 'Yuan ', 'Zhen ', 'Chu ', 'Xian ', 'Tou ', 'Nie ', 'Yun ', 'Xian ', 'Pei ', 'Pei ', 'Zou ', 'Yi ', 'Dui ', 'Lun ', + 0x70 => 'Yin ', 'Ju ', 'Chui ', 'Chen ', 'Pi ', 'Ling ', 'Tao ', 'Xian ', 'Lu ', 'Sheng ', 'Xian ', 'Yin ', 'Zhu ', 'Yang ', 'Reng ', 'Shan ', + 0x80 => 'Chong ', 'Yan ', 'Yin ', 'Yu ', 'Ti ', 'Yu ', 'Long ', 'Wei ', 'Wei ', 'Nie ', 'Dui ', 'Sui ', 'An ', 'Huang ', 'Jie ', 'Sui ', + 0x90 => 'Yin ', 'Gai ', 'Yan ', 'Hui ', 'Ge ', 'Yun ', 'Wu ', 'Wei ', 'Ai ', 'Xi ', 'Tang ', 'Ji ', 'Zhang ', 'Dao ', 'Ao ', 'Xi ', + 0xA0 => 'Yin ', null, 'Rao ', 'Lin ', 'Tui ', 'Deng ', 'Pi ', 'Sui ', 'Sui ', 'Yu ', 'Xian ', 'Fen ', 'Ni ', 'Er ', 'Ji ', 'Dao ', + 0xB0 => 'Xi ', 'Yin ', 'E ', 'Hui ', 'Long ', 'Xi ', 'Li ', 'Li ', 'Li ', 'Zhui ', 'He ', 'Zhi ', 'Zhun ', 'Jun ', 'Nan ', 'Yi ', + 0xC0 => 'Que ', 'Yan ', 'Qian ', 'Ya ', 'Xiong ', 'Ya ', 'Ji ', 'Gu ', 'Huan ', 'Zhi ', 'Gou ', 'Jun ', 'Ci ', 'Yong ', 'Ju ', 'Chu ', + 0xD0 => 'Hu ', 'Za ', 'Luo ', 'Yu ', 'Chou ', 'Diao ', 'Sui ', 'Han ', 'Huo ', 'Shuang ', 'Guan ', 'Chu ', 'Za ', 'Yong ', 'Ji ', 'Xi ', + 0xE0 => 'Chou ', 'Liu ', 'Li ', 'Nan ', 'Xue ', 'Za ', 'Ji ', 'Ji ', 'Yu ', 'Yu ', 'Xue ', 'Na ', 'Fou ', 'Se ', 'Mu ', 'Wen ', + 0xF0 => 'Fen ', 'Pang ', 'Yun ', 'Li ', 'Li ', 'Ang ', 'Ling ', 'Lei ', 'An ', 'Bao ', 'Meng ', 'Dian ', 'Dang ', 'Xing ', 'Wu ', 'Zhao ', +]; diff --git a/resources/transliteration-data/x97.php b/resources/transliteration-data/x97.php new file mode 100644 index 000000000..7728cfeb1 --- /dev/null +++ b/resources/transliteration-data/x97.php @@ -0,0 +1,20 @@ + 'Xu ', 'Ji ', 'Mu ', 'Chen ', 'Xiao ', 'Zha ', 'Ting ', 'Zhen ', 'Pei ', 'Mei ', 'Ling ', 'Qi ', 'Chou ', 'Huo ', 'Sha ', 'Fei ', + 0x10 => 'Weng ', 'Zhan ', 'Yin ', 'Ni ', 'Chou ', 'Tun ', 'Lin ', null, 'Dong ', 'Ying ', 'Wu ', 'Ling ', 'Shuang ', 'Ling ', 'Xia ', 'Hong ', + 0x20 => 'Yin ', 'Mo ', 'Mai ', 'Yun ', 'Liu ', 'Meng ', 'Bin ', 'Wu ', 'Wei ', 'Huo ', 'Yin ', 'Xi ', 'Yi ', 'Ai ', 'Dan ', 'Deng ', + 0x30 => 'Xian ', 'Yu ', 'Lu ', 'Long ', 'Dai ', 'Ji ', 'Pang ', 'Yang ', 'Ba ', 'Pi ', 'Wei ', null, 'Xi ', 'Ji ', 'Mai ', 'Meng ', + 0x40 => 'Meng ', 'Lei ', 'Li ', 'Huo ', 'Ai ', 'Fei ', 'Dai ', 'Long ', 'Ling ', 'Ai ', 'Feng ', 'Li ', 'Bao ', null, 'He ', 'He ', + 0x50 => 'Bing ', 'Qing ', 'Qing ', 'Jing ', 'Tian ', 'Zhen ', 'Jing ', 'Cheng ', 'Qing ', 'Jing ', 'Jing ', 'Dian ', 'Jing ', 'Tian ', 'Fei ', 'Fei ', + 0x60 => 'Kao ', 'Mi ', 'Mian ', 'Mian ', 'Pao ', 'Ye ', 'Tian ', 'Hui ', 'Ye ', 'Ge ', 'Ding ', 'Cha ', 'Jian ', 'Ren ', 'Di ', 'Du ', + 0x70 => 'Wu ', 'Ren ', 'Qin ', 'Jin ', 'Xue ', 'Niu ', 'Ba ', 'Yin ', 'Sa ', 'Na ', 'Mo ', 'Zu ', 'Da ', 'Ban ', 'Yi ', 'Yao ', + 0x80 => 'Tao ', 'Tuo ', 'Jia ', 'Hong ', 'Pao ', 'Yang ', 'Tomo ', 'Yin ', 'Jia ', 'Tao ', 'Ji ', 'Xie ', 'An ', 'An ', 'Hen ', 'Gong ', + 0x90 => 'Kohaze ', 'Da ', 'Qiao ', 'Ting ', 'Wan ', 'Ying ', 'Sui ', 'Tiao ', 'Qiao ', 'Xuan ', 'Kong ', 'Beng ', 'Ta ', 'Zhang ', 'Bing ', 'Kuo ', + 0xA0 => 'Ju ', 'La ', 'Xie ', 'Rou ', 'Bang ', 'Yi ', 'Qiu ', 'Qiu ', 'He ', 'Xiao ', 'Mu ', 'Ju ', 'Jian ', 'Bian ', 'Di ', 'Jian ', + 0xB0 => 'On ', 'Tao ', 'Gou ', 'Ta ', 'Bei ', 'Xie ', 'Pan ', 'Ge ', 'Bi ', 'Kuo ', 'Tang ', 'Lou ', 'Gui ', 'Qiao ', 'Xue ', 'Ji ', + 0xC0 => 'Jian ', 'Jiang ', 'Chan ', 'Da ', 'Huo ', 'Xian ', 'Qian ', 'Du ', 'Wa ', 'Jian ', 'Lan ', 'Wei ', 'Ren ', 'Fu ', 'Mei ', 'Juan ', + 0xD0 => 'Ge ', 'Wei ', 'Qiao ', 'Han ', 'Chang ', null, 'Rou ', 'Xun ', 'She ', 'Wei ', 'Ge ', 'Bei ', 'Tao ', 'Gou ', 'Yun ', null, + 0xE0 => 'Bi ', 'Wei ', 'Hui ', 'Du ', 'Wa ', 'Du ', 'Wei ', 'Ren ', 'Fu ', 'Han ', 'Wei ', 'Yun ', 'Tao ', 'Jiu ', 'Jiu ', 'Xian ', + 0xF0 => 'Xie ', 'Xian ', 'Ji ', 'Yin ', 'Za ', 'Yun ', 'Shao ', 'Le ', 'Peng ', 'Heng ', 'Ying ', 'Yun ', 'Peng ', 'Yin ', 'Yin ', 'Xiang ', +]; diff --git a/resources/transliteration-data/x98.php b/resources/transliteration-data/x98.php new file mode 100644 index 000000000..0369ee877 --- /dev/null +++ b/resources/transliteration-data/x98.php @@ -0,0 +1,20 @@ + 'Hu ', 'Ye ', 'Ding ', 'Qing ', 'Pan ', 'Xiang ', 'Shun ', 'Han ', 'Xu ', 'Yi ', 'Xu ', 'Gu ', 'Song ', 'Kui ', 'Qi ', 'Hang ', + 0x10 => 'Yu ', 'Wan ', 'Ban ', 'Dun ', 'Di ', 'Dan ', 'Pan ', 'Po ', 'Ling ', 'Ce ', 'Jing ', 'Lei ', 'He ', 'Qiao ', 'E ', 'E ', + 0x20 => 'Wei ', 'Jie ', 'Gua ', 'Shen ', 'Yi ', 'Shen ', 'Hai ', 'Dui ', 'Pian ', 'Ping ', 'Lei ', 'Fu ', 'Jia ', 'Tou ', 'Hui ', 'Kui ', + 0x30 => 'Jia ', 'Le ', 'Tian ', 'Cheng ', 'Ying ', 'Jun ', 'Hu ', 'Han ', 'Jing ', 'Tui ', 'Tui ', 'Pin ', 'Lai ', 'Tui ', 'Zi ', 'Zi ', + 0x40 => 'Chui ', 'Ding ', 'Lai ', 'Yan ', 'Han ', 'Jian ', 'Ke ', 'Cui ', 'Jiong ', 'Qin ', 'Yi ', 'Sai ', 'Ti ', 'E ', 'E ', 'Yan ', + 0x50 => 'Hun ', 'Kan ', 'Yong ', 'Zhuan ', 'Yan ', 'Xian ', 'Xin ', 'Yi ', 'Yuan ', 'Sang ', 'Dian ', 'Dian ', 'Jiang ', 'Ku ', 'Lei ', 'Liao ', + 0x60 => 'Piao ', 'Yi ', 'Man ', 'Qi ', 'Rao ', 'Hao ', 'Qiao ', 'Gu ', 'Xun ', 'Qian ', 'Hui ', 'Zhan ', 'Ru ', 'Hong ', 'Bin ', 'Xian ', + 0x70 => 'Pin ', 'Lu ', 'Lan ', 'Nie ', 'Quan ', 'Ye ', 'Ding ', 'Qing ', 'Han ', 'Xiang ', 'Shun ', 'Xu ', 'Xu ', 'Wan ', 'Gu ', 'Dun ', + 0x80 => 'Qi ', 'Ban ', 'Song ', 'Hang ', 'Yu ', 'Lu ', 'Ling ', 'Po ', 'Jing ', 'Jie ', 'Jia ', 'Tian ', 'Han ', 'Ying ', 'Jiong ', 'Hai ', + 0x90 => 'Yi ', 'Pin ', 'Hui ', 'Tui ', 'Han ', 'Ying ', 'Ying ', 'Ke ', 'Ti ', 'Yong ', 'E ', 'Zhuan ', 'Yan ', 'E ', 'Nie ', 'Man ', + 0xA0 => 'Dian ', 'Sang ', 'Hao ', 'Lei ', 'Zhan ', 'Ru ', 'Pin ', 'Quan ', 'Feng ', 'Biao ', 'Oroshi ', 'Fu ', 'Xia ', 'Zhan ', 'Biao ', 'Sa ', + 0xB0 => 'Ba ', 'Tai ', 'Lie ', 'Gua ', 'Xuan ', 'Shao ', 'Ju ', 'Bi ', 'Si ', 'Wei ', 'Yang ', 'Yao ', 'Sou ', 'Kai ', 'Sao ', 'Fan ', + 0xC0 => 'Liu ', 'Xi ', 'Liao ', 'Piao ', 'Piao ', 'Liu ', 'Biao ', 'Biao ', 'Biao ', 'Liao ', null, 'Se ', 'Feng ', 'Biao ', 'Feng ', 'Yang ', + 0xD0 => 'Zhan ', 'Biao ', 'Sa ', 'Ju ', 'Si ', 'Sou ', 'Yao ', 'Liu ', 'Piao ', 'Biao ', 'Biao ', 'Fei ', 'Fan ', 'Fei ', 'Fei ', 'Shi ', + 0xE0 => 'Shi ', 'Can ', 'Ji ', 'Ding ', 'Si ', 'Tuo ', 'Zhan ', 'Sun ', 'Xiang ', 'Tun ', 'Ren ', 'Yu ', 'Juan ', 'Chi ', 'Yin ', 'Fan ', + 0xF0 => 'Fan ', 'Sun ', 'Yin ', 'Zhu ', 'Yi ', 'Zhai ', 'Bi ', 'Jie ', 'Tao ', 'Liu ', 'Ci ', 'Tie ', 'Si ', 'Bao ', 'Shi ', 'Duo ', +]; diff --git a/resources/transliteration-data/x99.php b/resources/transliteration-data/x99.php new file mode 100644 index 000000000..137dd07b8 --- /dev/null +++ b/resources/transliteration-data/x99.php @@ -0,0 +1,20 @@ + 'Hai ', 'Ren ', 'Tian ', 'Jiao ', 'Jia ', 'Bing ', 'Yao ', 'Tong ', 'Ci ', 'Xiang ', 'Yang ', 'Yang ', 'Er ', 'Yan ', 'Le ', 'Yi ', + 0x10 => 'Can ', 'Bo ', 'Nei ', 'E ', 'Bu ', 'Jun ', 'Dou ', 'Su ', 'Yu ', 'Shi ', 'Yao ', 'Hun ', 'Guo ', 'Shi ', 'Jian ', 'Zhui ', + 0x20 => 'Bing ', 'Xian ', 'Bu ', 'Ye ', 'Tan ', 'Fei ', 'Zhang ', 'Wei ', 'Guan ', 'E ', 'Nuan ', 'Hun ', 'Hu ', 'Huang ', 'Tie ', 'Hui ', + 0x30 => 'Jian ', 'Hou ', 'He ', 'Xing ', 'Fen ', 'Wei ', 'Gu ', 'Cha ', 'Song ', 'Tang ', 'Bo ', 'Gao ', 'Xi ', 'Kui ', 'Liu ', 'Sou ', + 0x40 => 'Tao ', 'Ye ', 'Yun ', 'Mo ', 'Tang ', 'Man ', 'Bi ', 'Yu ', 'Xiu ', 'Jin ', 'San ', 'Kui ', 'Zhuan ', 'Shan ', 'Chi ', 'Dan ', + 0x50 => 'Yi ', 'Ji ', 'Rao ', 'Cheng ', 'Yong ', 'Tao ', 'Hui ', 'Xiang ', 'Zhan ', 'Fen ', 'Hai ', 'Meng ', 'Yan ', 'Mo ', 'Chan ', 'Xiang ', + 0x60 => 'Luo ', 'Zuan ', 'Nang ', 'Shi ', 'Ding ', 'Ji ', 'Tuo ', 'Xing ', 'Tun ', 'Xi ', 'Ren ', 'Yu ', 'Chi ', 'Fan ', 'Yin ', 'Jian ', + 0x70 => 'Shi ', 'Bao ', 'Si ', 'Duo ', 'Yi ', 'Er ', 'Rao ', 'Xiang ', 'Jia ', 'Le ', 'Jiao ', 'Yi ', 'Bing ', 'Bo ', 'Dou ', 'E ', + 0x80 => 'Yu ', 'Nei ', 'Jun ', 'Guo ', 'Hun ', 'Xian ', 'Guan ', 'Cha ', 'Kui ', 'Gu ', 'Sou ', 'Chan ', 'Ye ', 'Mo ', 'Bo ', 'Liu ', + 0x90 => 'Xiu ', 'Jin ', 'Man ', 'San ', 'Zhuan ', 'Nang ', 'Shou ', 'Kui ', 'Guo ', 'Xiang ', 'Fen ', 'Ba ', 'Ni ', 'Bi ', 'Bo ', 'Tu ', + 0xA0 => 'Han ', 'Fei ', 'Jian ', 'An ', 'Ai ', 'Fu ', 'Xian ', 'Wen ', 'Xin ', 'Fen ', 'Bin ', 'Xing ', 'Ma ', 'Yu ', 'Feng ', 'Han ', + 0xB0 => 'Di ', 'Tuo ', 'Tuo ', 'Chi ', 'Xun ', 'Zhu ', 'Zhi ', 'Pei ', 'Xin ', 'Ri ', 'Sa ', 'Yin ', 'Wen ', 'Zhi ', 'Dan ', 'Lu ', + 0xC0 => 'You ', 'Bo ', 'Bao ', 'Kuai ', 'Tuo ', 'Yi ', 'Qu ', null, 'Qu ', 'Jiong ', 'Bo ', 'Zhao ', 'Yuan ', 'Peng ', 'Zhou ', 'Ju ', + 0xD0 => 'Zhu ', 'Nu ', 'Ju ', 'Pi ', 'Zang ', 'Jia ', 'Ling ', 'Zhen ', 'Tai ', 'Fu ', 'Yang ', 'Shi ', 'Bi ', 'Tuo ', 'Tuo ', 'Si ', + 0xE0 => 'Liu ', 'Ma ', 'Pian ', 'Tao ', 'Zhi ', 'Rong ', 'Teng ', 'Dong ', 'Xun ', 'Quan ', 'Shen ', 'Jiong ', 'Er ', 'Hai ', 'Bo ', 'Zhu ', + 0xF0 => 'Yin ', 'Luo ', 'Shuu ', 'Dan ', 'Xie ', 'Liu ', 'Ju ', 'Song ', 'Qin ', 'Mang ', 'Liang ', 'Han ', 'Tu ', 'Xuan ', 'Tui ', 'Jun ', +]; diff --git a/resources/transliteration-data/x9a.php b/resources/transliteration-data/x9a.php new file mode 100644 index 000000000..fd2374dc7 --- /dev/null +++ b/resources/transliteration-data/x9a.php @@ -0,0 +1,20 @@ + 'E ', 'Cheng ', 'Xin ', 'Ai ', 'Lu ', 'Zhui ', 'Zhou ', 'She ', 'Pian ', 'Kun ', 'Tao ', 'Lai ', 'Zong ', 'Ke ', 'Qi ', 'Qi ', + 0x10 => 'Yan ', 'Fei ', 'Sao ', 'Yan ', 'Jie ', 'Yao ', 'Wu ', 'Pian ', 'Cong ', 'Pian ', 'Qian ', 'Fei ', 'Huang ', 'Jian ', 'Huo ', 'Yu ', + 0x20 => 'Ti ', 'Quan ', 'Xia ', 'Zong ', 'Kui ', 'Rou ', 'Si ', 'Gua ', 'Tuo ', 'Kui ', 'Sou ', 'Qian ', 'Cheng ', 'Zhi ', 'Liu ', 'Pang ', + 0x30 => 'Teng ', 'Xi ', 'Cao ', 'Du ', 'Yan ', 'Yuan ', 'Zou ', 'Sao ', 'Shan ', 'Li ', 'Zhi ', 'Shuang ', 'Lu ', 'Xi ', 'Luo ', 'Zhang ', + 0x40 => 'Mo ', 'Ao ', 'Can ', 'Piao ', 'Cong ', 'Qu ', 'Bi ', 'Zhi ', 'Yu ', 'Xu ', 'Hua ', 'Bo ', 'Su ', 'Xiao ', 'Lin ', 'Chan ', + 0x50 => 'Dun ', 'Liu ', 'Tuo ', 'Zeng ', 'Tan ', 'Jiao ', 'Tie ', 'Yan ', 'Luo ', 'Zhan ', 'Jing ', 'Yi ', 'Ye ', 'Tuo ', 'Bin ', 'Zou ', + 0x60 => 'Yan ', 'Peng ', 'Lu ', 'Teng ', 'Xiang ', 'Ji ', 'Shuang ', 'Ju ', 'Xi ', 'Huan ', 'Li ', 'Biao ', 'Ma ', 'Yu ', 'Tuo ', 'Xun ', + 0x70 => 'Chi ', 'Qu ', 'Ri ', 'Bo ', 'Lu ', 'Zang ', 'Shi ', 'Si ', 'Fu ', 'Ju ', 'Zou ', 'Zhu ', 'Tuo ', 'Nu ', 'Jia ', 'Yi ', + 0x80 => 'Tai ', 'Xiao ', 'Ma ', 'Yin ', 'Jiao ', 'Hua ', 'Luo ', 'Hai ', 'Pian ', 'Biao ', 'Li ', 'Cheng ', 'Yan ', 'Xin ', 'Qin ', 'Jun ', + 0x90 => 'Qi ', 'Qi ', 'Ke ', 'Zhui ', 'Zong ', 'Su ', 'Can ', 'Pian ', 'Zhi ', 'Kui ', 'Sao ', 'Wu ', 'Ao ', 'Liu ', 'Qian ', 'Shan ', + 0xA0 => 'Piao ', 'Luo ', 'Cong ', 'Chan ', 'Zou ', 'Ji ', 'Shuang ', 'Xiang ', 'Gu ', 'Wei ', 'Wei ', 'Wei ', 'Yu ', 'Gan ', 'Yi ', 'Ang ', + 0xB0 => 'Tou ', 'Xie ', 'Bao ', 'Bi ', 'Chi ', 'Ti ', 'Di ', 'Ku ', 'Hai ', 'Qiao ', 'Gou ', 'Kua ', 'Ge ', 'Tui ', 'Geng ', 'Pian ', + 0xC0 => 'Bi ', 'Ke ', 'Ka ', 'Yu ', 'Sui ', 'Lou ', 'Bo ', 'Xiao ', 'Pang ', 'Bo ', 'Ci ', 'Kuan ', 'Bin ', 'Mo ', 'Liao ', 'Lou ', + 0xD0 => 'Nao ', 'Du ', 'Zang ', 'Sui ', 'Ti ', 'Bin ', 'Kuan ', 'Lu ', 'Gao ', 'Gao ', 'Qiao ', 'Kao ', 'Qiao ', 'Lao ', 'Zao ', 'Biao ', + 0xE0 => 'Kun ', 'Kun ', 'Ti ', 'Fang ', 'Xiu ', 'Ran ', 'Mao ', 'Dan ', 'Kun ', 'Bin ', 'Fa ', 'Tiao ', 'Peng ', 'Zi ', 'Fa ', 'Ran ', + 0xF0 => 'Ti ', 'Pao ', 'Pi ', 'Mao ', 'Fu ', 'Er ', 'Rong ', 'Qu ', 'Gong ', 'Xiu ', 'Gua ', 'Ji ', 'Peng ', 'Zhua ', 'Shao ', 'Sha ', +]; diff --git a/resources/transliteration-data/x9b.php b/resources/transliteration-data/x9b.php new file mode 100644 index 000000000..1f698afa8 --- /dev/null +++ b/resources/transliteration-data/x9b.php @@ -0,0 +1,20 @@ + 'Ti ', 'Li ', 'Bin ', 'Zong ', 'Ti ', 'Peng ', 'Song ', 'Zheng ', 'Quan ', 'Zong ', 'Shun ', 'Jian ', 'Duo ', 'Hu ', 'La ', 'Jiu ', + 0x10 => 'Qi ', 'Lian ', 'Zhen ', 'Bin ', 'Peng ', 'Mo ', 'San ', 'Man ', 'Man ', 'Seng ', 'Xu ', 'Lie ', 'Qian ', 'Qian ', 'Nong ', 'Huan ', + 0x20 => 'Kuai ', 'Ning ', 'Bin ', 'Lie ', 'Rang ', 'Dou ', 'Dou ', 'Nao ', 'Hong ', 'Xi ', 'Dou ', 'Han ', 'Dou ', 'Dou ', 'Jiu ', 'Chang ', + 0x30 => 'Yu ', 'Yu ', 'Li ', 'Juan ', 'Fu ', 'Qian ', 'Gui ', 'Zong ', 'Liu ', 'Gui ', 'Shang ', 'Yu ', 'Gui ', 'Mei ', 'Ji ', 'Qi ', + 0x40 => 'Jie ', 'Kui ', 'Hun ', 'Ba ', 'Po ', 'Mei ', 'Xu ', 'Yan ', 'Xiao ', 'Liang ', 'Yu ', 'Tui ', 'Qi ', 'Wang ', 'Liang ', 'Wei ', + 0x50 => 'Jian ', 'Chi ', 'Piao ', 'Bi ', 'Mo ', 'Ji ', 'Xu ', 'Chou ', 'Yan ', 'Zhan ', 'Yu ', 'Dao ', 'Ren ', 'Ji ', 'Eri ', 'Gong ', + 0x60 => 'Tuo ', 'Diao ', 'Ji ', 'Xu ', 'E ', 'E ', 'Sha ', 'Hang ', 'Tun ', 'Mo ', 'Jie ', 'Shen ', 'Fan ', 'Yuan ', 'Bi ', 'Lu ', + 0x70 => 'Wen ', 'Hu ', 'Lu ', 'Za ', 'Fang ', 'Fen ', 'Na ', 'You ', 'Namazu ', 'Todo ', 'He ', 'Xia ', 'Qu ', 'Han ', 'Pi ', 'Ling ', + 0x80 => 'Tuo ', 'Bo ', 'Qiu ', 'Ping ', 'Fu ', 'Bi ', 'Ji ', 'Wei ', 'Ju ', 'Diao ', 'Bo ', 'You ', 'Gun ', 'Pi ', 'Nian ', 'Xing ', + 0x90 => 'Tai ', 'Bao ', 'Fu ', 'Zha ', 'Ju ', 'Gu ', 'Kajika ', 'Tong ', null, 'Ta ', 'Jie ', 'Shu ', 'Hou ', 'Xiang ', 'Er ', 'An ', + 0xA0 => 'Wei ', 'Tiao ', 'Zhu ', 'Yin ', 'Lie ', 'Luo ', 'Tong ', 'Yi ', 'Qi ', 'Bing ', 'Wei ', 'Jiao ', 'Bu ', 'Gui ', 'Xian ', 'Ge ', + 0xB0 => 'Hui ', 'Bora ', 'Mate ', 'Kao ', 'Gori ', 'Duo ', 'Jun ', 'Ti ', 'Man ', 'Xiao ', 'Za ', 'Sha ', 'Qin ', 'Yu ', 'Nei ', 'Zhe ', + 0xC0 => 'Gun ', 'Geng ', 'Su ', 'Wu ', 'Qiu ', 'Ting ', 'Fu ', 'Wan ', 'You ', 'Li ', 'Sha ', 'Sha ', 'Gao ', 'Meng ', 'Ugui ', 'Asari ', + 0xD0 => 'Subashiri ', 'Kazunoko ', 'Yong ', 'Ni ', 'Zi ', 'Qi ', 'Qing ', 'Xiang ', 'Nei ', 'Chun ', 'Ji ', 'Diao ', 'Qie ', 'Gu ', 'Zhou ', 'Dong ', + 0xE0 => 'Lai ', 'Fei ', 'Ni ', 'Yi ', 'Kun ', 'Lu ', 'Jiu ', 'Chang ', 'Jing ', 'Lun ', 'Ling ', 'Zou ', 'Li ', 'Meng ', 'Zong ', 'Zhi ', + 0xF0 => 'Nian ', 'Shachi ', 'Dojou ', 'Sukesou ', 'Shi ', 'Shen ', 'Hun ', 'Shi ', 'Hou ', 'Xing ', 'Zhu ', 'La ', 'Zong ', 'Ji ', 'Bian ', 'Bian ', +]; diff --git a/resources/transliteration-data/x9c.php b/resources/transliteration-data/x9c.php new file mode 100644 index 000000000..2315fc3da --- /dev/null +++ b/resources/transliteration-data/x9c.php @@ -0,0 +1,20 @@ + 'Huan ', 'Quan ', 'Ze ', 'Wei ', 'Wei ', 'Yu ', 'Qun ', 'Rou ', 'Die ', 'Huang ', 'Lian ', 'Yan ', 'Qiu ', 'Qiu ', 'Jian ', 'Bi ', + 0x10 => 'E ', 'Yang ', 'Fu ', 'Sai ', 'Jian ', 'Xia ', 'Tuo ', 'Hu ', 'Muroaji ', 'Ruo ', 'Haraka ', 'Wen ', 'Jian ', 'Hao ', 'Wu ', 'Fang ', + 0x20 => 'Sao ', 'Liu ', 'Ma ', 'Shi ', 'Shi ', 'Yin ', 'Z ', 'Teng ', 'Ta ', 'Yao ', 'Ge ', 'Rong ', 'Qian ', 'Qi ', 'Wen ', 'Ruo ', + 0x30 => 'Hatahata ', 'Lian ', 'Ao ', 'Le ', 'Hui ', 'Min ', 'Ji ', 'Tiao ', 'Qu ', 'Jian ', 'Sao ', 'Man ', 'Xi ', 'Qiu ', 'Biao ', 'Ji ', + 0x40 => 'Ji ', 'Zhu ', 'Jiang ', 'Qiu ', 'Zhuan ', 'Yong ', 'Zhang ', 'Kang ', 'Xue ', 'Bie ', 'Jue ', 'Qu ', 'Xiang ', 'Bo ', 'Jiao ', 'Xun ', + 0x50 => 'Su ', 'Huang ', 'Zun ', 'Shan ', 'Shan ', 'Fan ', 'Jue ', 'Lin ', 'Xun ', 'Miao ', 'Xi ', 'Eso ', 'Kyou ', 'Fen ', 'Guan ', 'Hou ', + 0x60 => 'Kuai ', 'Zei ', 'Sao ', 'Zhan ', 'Gan ', 'Gui ', 'Sheng ', 'Li ', 'Chang ', 'Hatahata ', 'Shiira ', 'Mutsu ', 'Ru ', 'Ji ', 'Xu ', 'Huo ', + 0x70 => 'Shiira ', 'Li ', 'Lie ', 'Li ', 'Mie ', 'Zhen ', 'Xiang ', 'E ', 'Lu ', 'Guan ', 'Li ', 'Xian ', 'Yu ', 'Dao ', 'Ji ', 'You ', + 0x80 => 'Tun ', 'Lu ', 'Fang ', 'Ba ', 'He ', 'Bo ', 'Ping ', 'Nian ', 'Lu ', 'You ', 'Zha ', 'Fu ', 'Bo ', 'Bao ', 'Hou ', 'Pi ', + 0x90 => 'Tai ', 'Gui ', 'Jie ', 'Kao ', 'Wei ', 'Er ', 'Tong ', 'Ze ', 'Hou ', 'Kuai ', 'Ji ', 'Jiao ', 'Xian ', 'Za ', 'Xiang ', 'Xun ', + 0xA0 => 'Geng ', 'Li ', 'Lian ', 'Jian ', 'Li ', 'Shi ', 'Tiao ', 'Gun ', 'Sha ', 'Wan ', 'Jun ', 'Ji ', 'Yong ', 'Qing ', 'Ling ', 'Qi ', + 0xB0 => 'Zou ', 'Fei ', 'Kun ', 'Chang ', 'Gu ', 'Ni ', 'Nian ', 'Diao ', 'Jing ', 'Shen ', 'Shi ', 'Zi ', 'Fen ', 'Die ', 'Bi ', 'Chang ', + 0xC0 => 'Shi ', 'Wen ', 'Wei ', 'Sai ', 'E ', 'Qiu ', 'Fu ', 'Huang ', 'Quan ', 'Jiang ', 'Bian ', 'Sao ', 'Ao ', 'Qi ', 'Ta ', 'Yin ', + 0xD0 => 'Yao ', 'Fang ', 'Jian ', 'Le ', 'Biao ', 'Xue ', 'Bie ', 'Man ', 'Min ', 'Yong ', 'Wei ', 'Xi ', 'Jue ', 'Shan ', 'Lin ', 'Zun ', + 0xE0 => 'Huo ', 'Gan ', 'Li ', 'Zhan ', 'Guan ', 'Niao ', 'Yi ', 'Fu ', 'Li ', 'Jiu ', 'Bu ', 'Yan ', 'Fu ', 'Diao ', 'Ji ', 'Feng ', + 0xF0 => 'Nio ', 'Gan ', 'Shi ', 'Feng ', 'Ming ', 'Bao ', 'Yuan ', 'Zhi ', 'Hu ', 'Qin ', 'Fu ', 'Fen ', 'Wen ', 'Jian ', 'Shi ', 'Yu ', +]; diff --git a/resources/transliteration-data/x9d.php b/resources/transliteration-data/x9d.php new file mode 100644 index 000000000..bc55fd1a5 --- /dev/null +++ b/resources/transliteration-data/x9d.php @@ -0,0 +1,20 @@ + 'Fou ', 'Yiao ', 'Jue ', 'Jue ', 'Pi ', 'Huan ', 'Zhen ', 'Bao ', 'Yan ', 'Ya ', 'Zheng ', 'Fang ', 'Feng ', 'Wen ', 'Ou ', 'Te ', + 0x10 => 'Jia ', 'Nu ', 'Ling ', 'Mie ', 'Fu ', 'Tuo ', 'Wen ', 'Li ', 'Bian ', 'Zhi ', 'Ge ', 'Yuan ', 'Zi ', 'Qu ', 'Xiao ', 'Zhi ', + 0x20 => 'Dan ', 'Ju ', 'You ', 'Gu ', 'Zhong ', 'Yu ', 'Yang ', 'Rong ', 'Ya ', 'Tie ', 'Yu ', 'Shigi ', 'Ying ', 'Zhui ', 'Wu ', 'Er ', + 0x30 => 'Gua ', 'Ai ', 'Zhi ', 'Yan ', 'Heng ', 'Jiao ', 'Ji ', 'Lie ', 'Zhu ', 'Ren ', 'Yi ', 'Hong ', 'Luo ', 'Ru ', 'Mou ', 'Ge ', + 0x40 => 'Ren ', 'Jiao ', 'Xiu ', 'Zhou ', 'Zhi ', 'Luo ', 'Chidori ', 'Toki ', 'Ten ', 'Luan ', 'Jia ', 'Ji ', 'Yu ', 'Huan ', 'Tuo ', 'Bu ', + 0x50 => 'Wu ', 'Juan ', 'Yu ', 'Bo ', 'Xun ', 'Xun ', 'Bi ', 'Xi ', 'Jun ', 'Ju ', 'Tu ', 'Jing ', 'Ti ', 'E ', 'E ', 'Kuang ', + 0x60 => 'Hu ', 'Wu ', 'Shen ', 'Lai ', 'Ikaruga ', 'Kakesu ', 'Lu ', 'Ping ', 'Shu ', 'Fu ', 'An ', 'Zhao ', 'Peng ', 'Qin ', 'Qian ', 'Bei ', + 0x70 => 'Diao ', 'Lu ', 'Que ', 'Jian ', 'Ju ', 'Tu ', 'Ya ', 'Yuan ', 'Qi ', 'Li ', 'Ye ', 'Zhui ', 'Kong ', 'Zhui ', 'Kun ', 'Sheng ', + 0x80 => 'Qi ', 'Jing ', 'Yi ', 'Yi ', 'Jing ', 'Zi ', 'Lai ', 'Dong ', 'Qi ', 'Chun ', 'Geng ', 'Ju ', 'Qu ', 'Isuka ', 'Kikuitadaki ', 'Ji ', + 0x90 => 'Shu ', null, 'Chi ', 'Miao ', 'Rou ', 'An ', 'Qiu ', 'Ti ', 'Hu ', 'Ti ', 'E ', 'Jie ', 'Mao ', 'Fu ', 'Chun ', 'Tu ', + 0xA0 => 'Yan ', 'He ', 'Yuan ', 'Pian ', 'Yun ', 'Mei ', 'Hu ', 'Ying ', 'Dun ', 'Mu ', 'Ju ', 'Tsugumi ', 'Cang ', 'Fang ', 'Gu ', 'Ying ', + 0xB0 => 'Yuan ', 'Xuan ', 'Weng ', 'Shi ', 'He ', 'Chu ', 'Tang ', 'Xia ', 'Ruo ', 'Liu ', 'Ji ', 'Gu ', 'Jian ', 'Zhun ', 'Han ', 'Zi ', + 0xC0 => 'Zi ', 'Ni ', 'Yao ', 'Yan ', 'Ji ', 'Li ', 'Tian ', 'Kou ', 'Ti ', 'Ti ', 'Ni ', 'Tu ', 'Ma ', 'Jiao ', 'Gao ', 'Tian ', + 0xD0 => 'Chen ', 'Li ', 'Zhuan ', 'Zhe ', 'Ao ', 'Yao ', 'Yi ', 'Ou ', 'Chi ', 'Zhi ', 'Liao ', 'Rong ', 'Lou ', 'Bi ', 'Shuang ', 'Zhuo ', + 0xE0 => 'Yu ', 'Wu ', 'Jue ', 'Yin ', 'Quan ', 'Si ', 'Jiao ', 'Yi ', 'Hua ', 'Bi ', 'Ying ', 'Su ', 'Huang ', 'Fan ', 'Jiao ', 'Liao ', + 0xF0 => 'Yan ', 'Kao ', 'Jiu ', 'Xian ', 'Xian ', 'Tu ', 'Mai ', 'Zun ', 'Yu ', 'Ying ', 'Lu ', 'Tuan ', 'Xian ', 'Xue ', 'Yi ', 'Pi ', +]; diff --git a/resources/transliteration-data/x9e.php b/resources/transliteration-data/x9e.php new file mode 100644 index 000000000..da2667166 --- /dev/null +++ b/resources/transliteration-data/x9e.php @@ -0,0 +1,20 @@ + 'Shu ', 'Luo ', 'Qi ', 'Yi ', 'Ji ', 'Zhe ', 'Yu ', 'Zhan ', 'Ye ', 'Yang ', 'Pi ', 'Ning ', 'Huo ', 'Mi ', 'Ying ', 'Meng ', + 0x10 => 'Di ', 'Yue ', 'Yu ', 'Lei ', 'Bao ', 'Lu ', 'He ', 'Long ', 'Shuang ', 'Yue ', 'Ying ', 'Guan ', 'Qu ', 'Li ', 'Luan ', 'Niao ', + 0x20 => 'Jiu ', 'Ji ', 'Yuan ', 'Ming ', 'Shi ', 'Ou ', 'Ya ', 'Cang ', 'Bao ', 'Zhen ', 'Gu ', 'Dong ', 'Lu ', 'Ya ', 'Xiao ', 'Yang ', + 0x30 => 'Ling ', 'Zhi ', 'Qu ', 'Yuan ', 'Xue ', 'Tuo ', 'Si ', 'Zhi ', 'Er ', 'Gua ', 'Xiu ', 'Heng ', 'Zhou ', 'Ge ', 'Luan ', 'Hong ', + 0x40 => 'Wu ', 'Bo ', 'Li ', 'Juan ', 'Hu ', 'E ', 'Yu ', 'Xian ', 'Ti ', 'Wu ', 'Que ', 'Miao ', 'An ', 'Kun ', 'Bei ', 'Peng ', + 0x50 => 'Qian ', 'Chun ', 'Geng ', 'Yuan ', 'Su ', 'Hu ', 'He ', 'E ', 'Gu ', 'Qiu ', 'Zi ', 'Mei ', 'Mu ', 'Ni ', 'Yao ', 'Weng ', + 0x60 => 'Liu ', 'Ji ', 'Ni ', 'Jian ', 'He ', 'Yi ', 'Ying ', 'Zhe ', 'Liao ', 'Liao ', 'Jiao ', 'Jiu ', 'Yu ', 'Lu ', 'Xuan ', 'Zhan ', + 0x70 => 'Ying ', 'Huo ', 'Meng ', 'Guan ', 'Shuang ', 'Lu ', 'Jin ', 'Ling ', 'Jian ', 'Xian ', 'Cuo ', 'Jian ', 'Jian ', 'Yan ', 'Cuo ', 'Lu ', + 0x80 => 'You ', 'Cu ', 'Ji ', 'Biao ', 'Cu ', 'Biao ', 'Zhu ', 'Jun ', 'Zhu ', 'Jian ', 'Mi ', 'Mi ', 'Wu ', 'Liu ', 'Chen ', 'Jun ', + 0x90 => 'Lin ', 'Ni ', 'Qi ', 'Lu ', 'Jiu ', 'Jun ', 'Jing ', 'Li ', 'Xiang ', 'Yan ', 'Jia ', 'Mi ', 'Li ', 'She ', 'Zhang ', 'Lin ', + 0xA0 => 'Jing ', 'Ji ', 'Ling ', 'Yan ', 'Cu ', 'Mai ', 'Mai ', 'Ge ', 'Chao ', 'Fu ', 'Mian ', 'Mian ', 'Fu ', 'Pao ', 'Qu ', 'Qu ', + 0xB0 => 'Mou ', 'Fu ', 'Xian ', 'Lai ', 'Qu ', 'Mian ', null, 'Feng ', 'Fu ', 'Qu ', 'Mian ', 'Ma ', 'Mo ', 'Mo ', 'Hui ', 'Ma ', + 0xC0 => 'Zou ', 'Nen ', 'Fen ', 'Huang ', 'Huang ', 'Jin ', 'Guang ', 'Tian ', 'Tou ', 'Heng ', 'Xi ', 'Kuang ', 'Heng ', 'Shu ', 'Li ', 'Nian ', + 0xD0 => 'Chi ', 'Hei ', 'Hei ', 'Yi ', 'Qian ', 'Dan ', 'Xi ', 'Tuan ', 'Mo ', 'Mo ', 'Qian ', 'Dai ', 'Chu ', 'You ', 'Dian ', 'Yi ', + 0xE0 => 'Xia ', 'Yan ', 'Qu ', 'Mei ', 'Yan ', 'Jing ', 'Yu ', 'Li ', 'Dang ', 'Du ', 'Can ', 'Yin ', 'An ', 'Yan ', 'Tan ', 'An ', + 0xF0 => 'Zhen ', 'Dai ', 'Can ', 'Yi ', 'Mei ', 'Dan ', 'Yan ', 'Du ', 'Lu ', 'Zhi ', 'Fen ', 'Fu ', 'Fu ', 'Min ', 'Min ', 'Yuan ', +]; diff --git a/resources/transliteration-data/x9f.php b/resources/transliteration-data/x9f.php new file mode 100644 index 000000000..88a2c6043 --- /dev/null +++ b/resources/transliteration-data/x9f.php @@ -0,0 +1,20 @@ + 'Cu ', 'Qu ', 'Chao ', 'Wa ', 'Zhu ', 'Zhi ', 'Mang ', 'Ao ', 'Bie ', 'Tuo ', 'Bi ', 'Yuan ', 'Chao ', 'Tuo ', 'Ding ', 'Mi ', + 0x10 => 'Nai ', 'Ding ', 'Zi ', 'Gu ', 'Gu ', 'Dong ', 'Fen ', 'Tao ', 'Yuan ', 'Pi ', 'Chang ', 'Gao ', 'Qi ', 'Yuan ', 'Tang ', 'Teng ', + 0x20 => 'Shu ', 'Shu ', 'Fen ', 'Fei ', 'Wen ', 'Ba ', 'Diao ', 'Tuo ', 'Tong ', 'Qu ', 'Sheng ', 'Shi ', 'You ', 'Shi ', 'Ting ', 'Wu ', + 0x30 => 'Nian ', 'Jing ', 'Hun ', 'Ju ', 'Yan ', 'Tu ', 'Ti ', 'Xi ', 'Xian ', 'Yan ', 'Lei ', 'Bi ', 'Yao ', 'Qiu ', 'Han ', 'Wu ', + 0x40 => 'Wu ', 'Hou ', 'Xi ', 'Ge ', 'Zha ', 'Xiu ', 'Weng ', 'Zha ', 'Nong ', 'Nang ', 'Qi ', 'Zhai ', 'Ji ', 'Zi ', 'Ji ', 'Ji ', + 0x50 => 'Qi ', 'Ji ', 'Chi ', 'Chen ', 'Chen ', 'He ', 'Ya ', 'Ken ', 'Xie ', 'Pao ', 'Cuo ', 'Shi ', 'Zi ', 'Chi ', 'Nian ', 'Ju ', + 0x60 => 'Tiao ', 'Ling ', 'Ling ', 'Chu ', 'Quan ', 'Xie ', 'Ken ', 'Nie ', 'Jiu ', 'Yao ', 'Chuo ', 'Kun ', 'Yu ', 'Chu ', 'Yi ', 'Ni ', + 0x70 => 'Cuo ', 'Zou ', 'Qu ', 'Nen ', 'Xian ', 'Ou ', 'E ', 'Wo ', 'Yi ', 'Chuo ', 'Zou ', 'Dian ', 'Chu ', 'Jin ', 'Ya ', 'Chi ', + 0x80 => 'Chen ', 'He ', 'Ken ', 'Ju ', 'Ling ', 'Pao ', 'Tiao ', 'Zi ', 'Ken ', 'Yu ', 'Chuo ', 'Qu ', 'Wo ', 'Long ', 'Pang ', 'Gong ', + 0x90 => 'Pang ', 'Yan ', 'Long ', 'Long ', 'Gong ', 'Kan ', 'Ta ', 'Ling ', 'Ta ', 'Long ', 'Gong ', 'Kan ', 'Gui ', 'Qiu ', 'Bie ', 'Gui ', + 0xA0 => 'Yue ', 'Chui ', 'He ', 'Jue ', 'Xie ', 'Yu ', null, null, null, null, null, null, null, null, null, null, + 0xB0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0xC0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0xD0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0xE0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0xF0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, +]; diff --git a/resources/transliteration-data/xa0.php b/resources/transliteration-data/xa0.php new file mode 100644 index 000000000..75099ce67 --- /dev/null +++ b/resources/transliteration-data/xa0.php @@ -0,0 +1,20 @@ + 'it', 'ix', 'i', 'ip', 'iet', 'iex', 'ie', 'iep', 'at', 'ax', 'a', 'ap', 'uox', 'uo', 'uop', 'ot', + 0x10 => 'ox', 'o', 'op', 'ex', 'e', 'wu', 'bit', 'bix', 'bi', 'bip', 'biet', 'biex', 'bie', 'biep', 'bat', 'bax', + 0x20 => 'ba', 'bap', 'buox', 'buo', 'buop', 'bot', 'box', 'bo', 'bop', 'bex', 'be', 'bep', 'but', 'bux', 'bu', 'bup', + 0x30 => 'burx', 'bur', 'byt', 'byx', 'by', 'byp', 'byrx', 'byr', 'pit', 'pix', 'pi', 'pip', 'piex', 'pie', 'piep', 'pat', + 0x40 => 'pax', 'pa', 'pap', 'puox', 'puo', 'puop', 'pot', 'pox', 'po', 'pop', 'put', 'pux', 'pu', 'pup', 'purx', 'pur', + 0x50 => 'pyt', 'pyx', 'py', 'pyp', 'pyrx', 'pyr', 'bbit', 'bbix', 'bbi', 'bbip', 'bbiet', 'bbiex', 'bbie', 'bbiep', 'bbat', 'bbax', + 0x60 => 'bba', 'bbap', 'bbuox', 'bbuo', 'bbuop', 'bbot', 'bbox', 'bbo', 'bbop', 'bbex', 'bbe', 'bbep', 'bbut', 'bbux', 'bbu', 'bbup', + 0x70 => 'bburx', 'bbur', 'bbyt', 'bbyx', 'bby', 'bbyp', 'nbit', 'nbix', 'nbi', 'nbip', 'nbiex', 'nbie', 'nbiep', 'nbat', 'nbax', 'nba', + 0x80 => 'nbap', 'nbot', 'nbox', 'nbo', 'nbop', 'nbut', 'nbux', 'nbu', 'nbup', 'nburx', 'nbur', 'nbyt', 'nbyx', 'nby', 'nbyp', 'nbyrx', + 0x90 => 'nbyr', 'hmit', 'hmix', 'hmi', 'hmip', 'hmiex', 'hmie', 'hmiep', 'hmat', 'hmax', 'hma', 'hmap', 'hmuox', 'hmuo', 'hmuop', 'hmot', + 0xA0 => 'hmox', 'hmo', 'hmop', 'hmut', 'hmux', 'hmu', 'hmup', 'hmurx', 'hmur', 'hmyx', 'hmy', 'hmyp', 'hmyrx', 'hmyr', 'mit', 'mix', + 0xB0 => 'mi', 'mip', 'miex', 'mie', 'miep', 'mat', 'max', 'ma', 'map', 'muot', 'muox', 'muo', 'muop', 'mot', 'mox', 'mo', + 0xC0 => 'mop', 'mex', 'me', 'mut', 'mux', 'mu', 'mup', 'murx', 'mur', 'myt', 'myx', 'my', 'myp', 'fit', 'fix', 'fi', + 0xD0 => 'fip', 'fat', 'fax', 'fa', 'fap', 'fox', 'fo', 'fop', 'fut', 'fux', 'fu', 'fup', 'furx', 'fur', 'fyt', 'fyx', + 0xE0 => 'fy', 'fyp', 'vit', 'vix', 'vi', 'vip', 'viet', 'viex', 'vie', 'viep', 'vat', 'vax', 'va', 'vap', 'vot', 'vox', + 0xF0 => 'vo', 'vop', 'vex', 'vep', 'vut', 'vux', 'vu', 'vup', 'vurx', 'vur', 'vyt', 'vyx', 'vy', 'vyp', 'vyrx', 'vyr', +]; diff --git a/resources/transliteration-data/xa1.php b/resources/transliteration-data/xa1.php new file mode 100644 index 000000000..b769254fe --- /dev/null +++ b/resources/transliteration-data/xa1.php @@ -0,0 +1,20 @@ + 'dit', 'dix', 'di', 'dip', 'diex', 'die', 'diep', 'dat', 'dax', 'da', 'dap', 'duox', 'duo', 'dot', 'dox', 'do', + 0x10 => 'dop', 'dex', 'de', 'dep', 'dut', 'dux', 'du', 'dup', 'durx', 'dur', 'tit', 'tix', 'ti', 'tip', 'tiex', 'tie', + 0x20 => 'tiep', 'tat', 'tax', 'ta', 'tap', 'tuot', 'tuox', 'tuo', 'tuop', 'tot', 'tox', 'to', 'top', 'tex', 'te', 'tep', + 0x30 => 'tut', 'tux', 'tu', 'tup', 'turx', 'tur', 'ddit', 'ddix', 'ddi', 'ddip', 'ddiex', 'ddie', 'ddiep', 'ddat', 'ddax', 'dda', + 0x40 => 'ddap', 'dduox', 'dduo', 'dduop', 'ddot', 'ddox', 'ddo', 'ddop', 'ddex', 'dde', 'ddep', 'ddut', 'ddux', 'ddu', 'ddup', 'ddurx', + 0x50 => 'ddur', 'ndit', 'ndix', 'ndi', 'ndip', 'ndiex', 'ndie', 'ndat', 'ndax', 'nda', 'ndap', 'ndot', 'ndox', 'ndo', 'ndop', 'ndex', + 0x60 => 'nde', 'ndep', 'ndut', 'ndux', 'ndu', 'ndup', 'ndurx', 'ndur', 'hnit', 'hnix', 'hni', 'hnip', 'hniet', 'hniex', 'hnie', 'hniep', + 0x70 => 'hnat', 'hnax', 'hna', 'hnap', 'hnuox', 'hnuo', 'hnot', 'hnox', 'hnop', 'hnex', 'hne', 'hnep', 'hnut', 'nit', 'nix', 'ni', + 0x80 => 'nip', 'niex', 'nie', 'niep', 'nax', 'na', 'nap', 'nuox', 'nuo', 'nuop', 'not', 'nox', 'no', 'nop', 'nex', 'ne', + 0x90 => 'nep', 'nut', 'nux', 'nu', 'nup', 'nurx', 'nur', 'hlit', 'hlix', 'hli', 'hlip', 'hliex', 'hlie', 'hliep', 'hlat', 'hlax', + 0xA0 => 'hla', 'hlap', 'hluox', 'hluo', 'hluop', 'hlox', 'hlo', 'hlop', 'hlex', 'hle', 'hlep', 'hlut', 'hlux', 'hlu', 'hlup', 'hlurx', + 0xB0 => 'hlur', 'hlyt', 'hlyx', 'hly', 'hlyp', 'hlyrx', 'hlyr', 'lit', 'lix', 'li', 'lip', 'liet', 'liex', 'lie', 'liep', 'lat', + 0xC0 => 'lax', 'la', 'lap', 'luot', 'luox', 'luo', 'luop', 'lot', 'lox', 'lo', 'lop', 'lex', 'le', 'lep', 'lut', 'lux', + 0xD0 => 'lu', 'lup', 'lurx', 'lur', 'lyt', 'lyx', 'ly', 'lyp', 'lyrx', 'lyr', 'git', 'gix', 'gi', 'gip', 'giet', 'giex', + 0xE0 => 'gie', 'giep', 'gat', 'gax', 'ga', 'gap', 'guot', 'guox', 'guo', 'guop', 'got', 'gox', 'go', 'gop', 'get', 'gex', + 0xF0 => 'ge', 'gep', 'gut', 'gux', 'gu', 'gup', 'gurx', 'gur', 'kit', 'kix', 'ki', 'kip', 'kiex', 'kie', 'kiep', 'kat', +]; diff --git a/resources/transliteration-data/xa2.php b/resources/transliteration-data/xa2.php new file mode 100644 index 000000000..3b52c59a7 --- /dev/null +++ b/resources/transliteration-data/xa2.php @@ -0,0 +1,20 @@ + 'kax', 'ka', 'kap', 'kuox', 'kuo', 'kuop', 'kot', 'kox', 'ko', 'kop', 'ket', 'kex', 'ke', 'kep', 'kut', 'kux', + 0x10 => 'ku', 'kup', 'kurx', 'kur', 'ggit', 'ggix', 'ggi', 'ggiex', 'ggie', 'ggiep', 'ggat', 'ggax', 'gga', 'ggap', 'gguot', 'gguox', + 0x20 => 'gguo', 'gguop', 'ggot', 'ggox', 'ggo', 'ggop', 'gget', 'ggex', 'gge', 'ggep', 'ggut', 'ggux', 'ggu', 'ggup', 'ggurx', 'ggur', + 0x30 => 'mgiex', 'mgie', 'mgat', 'mgax', 'mga', 'mgap', 'mguox', 'mguo', 'mguop', 'mgot', 'mgox', 'mgo', 'mgop', 'mgex', 'mge', 'mgep', + 0x40 => 'mgut', 'mgux', 'mgu', 'mgup', 'mgurx', 'mgur', 'hxit', 'hxix', 'hxi', 'hxip', 'hxiet', 'hxiex', 'hxie', 'hxiep', 'hxat', 'hxax', + 0x50 => 'hxa', 'hxap', 'hxuot', 'hxuox', 'hxuo', 'hxuop', 'hxot', 'hxox', 'hxo', 'hxop', 'hxex', 'hxe', 'hxep', 'ngiex', 'ngie', 'ngiep', + 0x60 => 'ngat', 'ngax', 'nga', 'ngap', 'nguot', 'nguox', 'nguo', 'ngot', 'ngox', 'ngo', 'ngop', 'ngex', 'nge', 'ngep', 'hit', 'hiex', + 0x70 => 'hie', 'hat', 'hax', 'ha', 'hap', 'huot', 'huox', 'huo', 'huop', 'hot', 'hox', 'ho', 'hop', 'hex', 'he', 'hep', + 0x80 => 'wat', 'wax', 'wa', 'wap', 'wuox', 'wuo', 'wuop', 'wox', 'wo', 'wop', 'wex', 'we', 'wep', 'zit', 'zix', 'zi', + 0x90 => 'zip', 'ziex', 'zie', 'ziep', 'zat', 'zax', 'za', 'zap', 'zuox', 'zuo', 'zuop', 'zot', 'zox', 'zo', 'zop', 'zex', + 0xA0 => 'ze', 'zep', 'zut', 'zux', 'zu', 'zup', 'zurx', 'zur', 'zyt', 'zyx', 'zy', 'zyp', 'zyrx', 'zyr', 'cit', 'cix', + 0xB0 => 'ci', 'cip', 'ciet', 'ciex', 'cie', 'ciep', 'cat', 'cax', 'ca', 'cap', 'cuox', 'cuo', 'cuop', 'cot', 'cox', 'co', + 0xC0 => 'cop', 'cex', 'ce', 'cep', 'cut', 'cux', 'cu', 'cup', 'curx', 'cur', 'cyt', 'cyx', 'cy', 'cyp', 'cyrx', 'cyr', + 0xD0 => 'zzit', 'zzix', 'zzi', 'zzip', 'zziet', 'zziex', 'zzie', 'zziep', 'zzat', 'zzax', 'zza', 'zzap', 'zzox', 'zzo', 'zzop', 'zzex', + 0xE0 => 'zze', 'zzep', 'zzux', 'zzu', 'zzup', 'zzurx', 'zzur', 'zzyt', 'zzyx', 'zzy', 'zzyp', 'zzyrx', 'zzyr', 'nzit', 'nzix', 'nzi', + 0xF0 => 'nzip', 'nziex', 'nzie', 'nziep', 'nzat', 'nzax', 'nza', 'nzap', 'nzuox', 'nzuo', 'nzox', 'nzop', 'nzex', 'nze', 'nzux', 'nzu', +]; diff --git a/resources/transliteration-data/xa3.php b/resources/transliteration-data/xa3.php new file mode 100644 index 000000000..4e055f471 --- /dev/null +++ b/resources/transliteration-data/xa3.php @@ -0,0 +1,20 @@ + 'nzup', 'nzurx', 'nzur', 'nzyt', 'nzyx', 'nzy', 'nzyp', 'nzyrx', 'nzyr', 'sit', 'six', 'si', 'sip', 'siex', 'sie', 'siep', + 0x10 => 'sat', 'sax', 'sa', 'sap', 'suox', 'suo', 'suop', 'sot', 'sox', 'so', 'sop', 'sex', 'se', 'sep', 'sut', 'sux', + 0x20 => 'su', 'sup', 'surx', 'sur', 'syt', 'syx', 'sy', 'syp', 'syrx', 'syr', 'ssit', 'ssix', 'ssi', 'ssip', 'ssiex', 'ssie', + 0x30 => 'ssiep', 'ssat', 'ssax', 'ssa', 'ssap', 'ssot', 'ssox', 'sso', 'ssop', 'ssex', 'sse', 'ssep', 'ssut', 'ssux', 'ssu', 'ssup', + 0x40 => 'ssyt', 'ssyx', 'ssy', 'ssyp', 'ssyrx', 'ssyr', 'zhat', 'zhax', 'zha', 'zhap', 'zhuox', 'zhuo', 'zhuop', 'zhot', 'zhox', 'zho', + 0x50 => 'zhop', 'zhet', 'zhex', 'zhe', 'zhep', 'zhut', 'zhux', 'zhu', 'zhup', 'zhurx', 'zhur', 'zhyt', 'zhyx', 'zhy', 'zhyp', 'zhyrx', + 0x60 => 'zhyr', 'chat', 'chax', 'cha', 'chap', 'chuot', 'chuox', 'chuo', 'chuop', 'chot', 'chox', 'cho', 'chop', 'chet', 'chex', 'che', + 0x70 => 'chep', 'chux', 'chu', 'chup', 'churx', 'chur', 'chyt', 'chyx', 'chy', 'chyp', 'chyrx', 'chyr', 'rrax', 'rra', 'rruox', 'rruo', + 0x80 => 'rrot', 'rrox', 'rro', 'rrop', 'rret', 'rrex', 'rre', 'rrep', 'rrut', 'rrux', 'rru', 'rrup', 'rrurx', 'rrur', 'rryt', 'rryx', + 0x90 => 'rry', 'rryp', 'rryrx', 'rryr', 'nrat', 'nrax', 'nra', 'nrap', 'nrox', 'nro', 'nrop', 'nret', 'nrex', 'nre', 'nrep', 'nrut', + 0xA0 => 'nrux', 'nru', 'nrup', 'nrurx', 'nrur', 'nryt', 'nryx', 'nry', 'nryp', 'nryrx', 'nryr', 'shat', 'shax', 'sha', 'shap', 'shuox', + 0xB0 => 'shuo', 'shuop', 'shot', 'shox', 'sho', 'shop', 'shet', 'shex', 'she', 'shep', 'shut', 'shux', 'shu', 'shup', 'shurx', 'shur', + 0xC0 => 'shyt', 'shyx', 'shy', 'shyp', 'shyrx', 'shyr', 'rat', 'rax', 'ra', 'rap', 'ruox', 'ruo', 'ruop', 'rot', 'rox', 'ro', + 0xD0 => 'rop', 'rex', 're', 'rep', 'rut', 'rux', 'ru', 'rup', 'rurx', 'rur', 'ryt', 'ryx', 'ry', 'ryp', 'ryrx', 'ryr', + 0xE0 => 'jit', 'jix', 'ji', 'jip', 'jiet', 'jiex', 'jie', 'jiep', 'juot', 'juox', 'juo', 'juop', 'jot', 'jox', 'jo', 'jop', + 0xF0 => 'jut', 'jux', 'ju', 'jup', 'jurx', 'jur', 'jyt', 'jyx', 'jy', 'jyp', 'jyrx', 'jyr', 'qit', 'qix', 'qi', 'qip', +]; diff --git a/resources/transliteration-data/xa4.php b/resources/transliteration-data/xa4.php new file mode 100644 index 000000000..0cd66e7a8 --- /dev/null +++ b/resources/transliteration-data/xa4.php @@ -0,0 +1,20 @@ + 'qiet', 'qiex', 'qie', 'qiep', 'quot', 'quox', 'quo', 'quop', 'qot', 'qox', 'qo', 'qop', 'qut', 'qux', 'qu', 'qup', + 0x10 => 'qurx', 'qur', 'qyt', 'qyx', 'qy', 'qyp', 'qyrx', 'qyr', 'jjit', 'jjix', 'jji', 'jjip', 'jjiet', 'jjiex', 'jjie', 'jjiep', + 0x20 => 'jjuox', 'jjuo', 'jjuop', 'jjot', 'jjox', 'jjo', 'jjop', 'jjut', 'jjux', 'jju', 'jjup', 'jjurx', 'jjur', 'jjyt', 'jjyx', 'jjy', + 0x30 => 'jjyp', 'njit', 'njix', 'nji', 'njip', 'njiet', 'njiex', 'njie', 'njiep', 'njuox', 'njuo', 'njot', 'njox', 'njo', 'njop', 'njux', + 0x40 => 'nju', 'njup', 'njurx', 'njur', 'njyt', 'njyx', 'njy', 'njyp', 'njyrx', 'njyr', 'nyit', 'nyix', 'nyi', 'nyip', 'nyiet', 'nyiex', + 0x50 => 'nyie', 'nyiep', 'nyuox', 'nyuo', 'nyuop', 'nyot', 'nyox', 'nyo', 'nyop', 'nyut', 'nyux', 'nyu', 'nyup', 'xit', 'xix', 'xi', + 0x60 => 'xip', 'xiet', 'xiex', 'xie', 'xiep', 'xuox', 'xuo', 'xot', 'xox', 'xo', 'xop', 'xyt', 'xyx', 'xy', 'xyp', 'xyrx', + 0x70 => 'xyr', 'yit', 'yix', 'yi', 'yip', 'yiet', 'yiex', 'yie', 'yiep', 'yuot', 'yuox', 'yuo', 'yuop', 'yot', 'yox', 'yo', + 0x80 => 'yop', 'yut', 'yux', 'yu', 'yup', 'yurx', 'yur', 'yyt', 'yyx', 'yy', 'yyp', 'yyrx', 'yyr', null, null, null, + 0x90 => 'Qot', 'Li', 'Kit', 'Nyip', 'Cyp', 'Ssi', 'Ggop', 'Gep', 'Mi', 'Hxit', 'Lyr', 'Bbut', 'Mop', 'Yo', 'Put', 'Hxuo', + 0xA0 => 'Tat', 'Ga', null, null, 'Ddur', 'Bur', 'Gguo', 'Nyop', 'Tu', 'Op', 'Jjut', 'Zot', 'Pyt', 'Hmo', 'Yit', 'Vur', + 0xB0 => 'Shy', 'Vep', 'Za', 'Jo', null, 'Jjy', 'Got', 'Jjie', 'Wo', 'Du', 'Shur', 'Lie', 'Cy', 'Cuop', 'Cip', 'Hxop', + 0xC0 => 'Shat', null, 'Shop', 'Che', 'Zziet', null, 'Ke', null, null, null, null, null, null, null, null, null, + 0xD0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0xE0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0xF0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, +]; diff --git a/resources/transliteration-data/xac.php b/resources/transliteration-data/xac.php new file mode 100644 index 000000000..38b18e3e9 --- /dev/null +++ b/resources/transliteration-data/xac.php @@ -0,0 +1,20 @@ + 'ga', 'gag', 'gagg', 'gags', 'gan', 'ganj', 'ganh', 'gad', 'gal', 'galg', 'galm', 'galb', 'gals', 'galt', 'galp', 'galh', + 0x10 => 'gam', 'gab', 'gabs', 'gas', 'gass', 'gang', 'gaj', 'gac', 'gak', 'gat', 'gap', 'gah', 'gae', 'gaeg', 'gaegg', 'gaegs', + 0x20 => 'gaen', 'gaenj', 'gaenh', 'gaed', 'gael', 'gaelg', 'gaelm', 'gaelb', 'gaels', 'gaelt', 'gaelp', 'gaelh', 'gaem', 'gaeb', 'gaebs', 'gaes', + 0x30 => 'gaess', 'gaeng', 'gaej', 'gaec', 'gaek', 'gaet', 'gaep', 'gaeh', 'gya', 'gyag', 'gyagg', 'gyags', 'gyan', 'gyanj', 'gyanh', 'gyad', + 0x40 => 'gyal', 'gyalg', 'gyalm', 'gyalb', 'gyals', 'gyalt', 'gyalp', 'gyalh', 'gyam', 'gyab', 'gyabs', 'gyas', 'gyass', 'gyang', 'gyaj', 'gyac', + 0x50 => 'gyak', 'gyat', 'gyap', 'gyah', 'gyae', 'gyaeg', 'gyaegg', 'gyaegs', 'gyaen', 'gyaenj', 'gyaenh', 'gyaed', 'gyael', 'gyaelg', 'gyaelm', 'gyaelb', + 0x60 => 'gyaels', 'gyaelt', 'gyaelp', 'gyaelh', 'gyaem', 'gyaeb', 'gyaebs', 'gyaes', 'gyaess', 'gyaeng', 'gyaej', 'gyaec', 'gyaek', 'gyaet', 'gyaep', 'gyaeh', + 0x70 => 'geo', 'geog', 'geogg', 'geogs', 'geon', 'geonj', 'geonh', 'geod', 'geol', 'geolg', 'geolm', 'geolb', 'geols', 'geolt', 'geolp', 'geolh', + 0x80 => 'geom', 'geob', 'geobs', 'geos', 'geoss', 'geong', 'geoj', 'geoc', 'geok', 'geot', 'geop', 'geoh', 'ge', 'geg', 'gegg', 'gegs', + 0x90 => 'gen', 'genj', 'genh', 'ged', 'gel', 'gelg', 'gelm', 'gelb', 'gels', 'gelt', 'gelp', 'gelh', 'gem', 'geb', 'gebs', 'ges', + 0xA0 => 'gess', 'geng', 'gej', 'gec', 'gek', 'get', 'gep', 'geh', 'gyeo', 'gyeog', 'gyeogg', 'gyeogs', 'gyeon', 'gyeonj', 'gyeonh', 'gyeod', + 0xB0 => 'gyeol', 'gyeolg', 'gyeolm', 'gyeolb', 'gyeols', 'gyeolt', 'gyeolp', 'gyeolh', 'gyeom', 'gyeob', 'gyeobs', 'gyeos', 'gyeoss', 'gyeong', 'gyeoj', 'gyeoc', + 0xC0 => 'gyeok', 'gyeot', 'gyeop', 'gyeoh', 'gye', 'gyeg', 'gyegg', 'gyegs', 'gyen', 'gyenj', 'gyenh', 'gyed', 'gyel', 'gyelg', 'gyelm', 'gyelb', + 0xD0 => 'gyels', 'gyelt', 'gyelp', 'gyelh', 'gyem', 'gyeb', 'gyebs', 'gyes', 'gyess', 'gyeng', 'gyej', 'gyec', 'gyek', 'gyet', 'gyep', 'gyeh', + 0xE0 => 'go', 'gog', 'gogg', 'gogs', 'gon', 'gonj', 'gonh', 'god', 'gol', 'golg', 'golm', 'golb', 'gols', 'golt', 'golp', 'golh', + 0xF0 => 'gom', 'gob', 'gobs', 'gos', 'goss', 'gong', 'goj', 'goc', 'gok', 'got', 'gop', 'goh', 'gwa', 'gwag', 'gwagg', 'gwags', +]; diff --git a/resources/transliteration-data/xad.php b/resources/transliteration-data/xad.php new file mode 100644 index 000000000..3a186c4ac --- /dev/null +++ b/resources/transliteration-data/xad.php @@ -0,0 +1,20 @@ + 'gwan', 'gwanj', 'gwanh', 'gwad', 'gwal', 'gwalg', 'gwalm', 'gwalb', 'gwals', 'gwalt', 'gwalp', 'gwalh', 'gwam', 'gwab', 'gwabs', 'gwas', + 0x10 => 'gwass', 'gwang', 'gwaj', 'gwac', 'gwak', 'gwat', 'gwap', 'gwah', 'gwae', 'gwaeg', 'gwaegg', 'gwaegs', 'gwaen', 'gwaenj', 'gwaenh', 'gwaed', + 0x20 => 'gwael', 'gwaelg', 'gwaelm', 'gwaelb', 'gwaels', 'gwaelt', 'gwaelp', 'gwaelh', 'gwaem', 'gwaeb', 'gwaebs', 'gwaes', 'gwaess', 'gwaeng', 'gwaej', 'gwaec', + 0x30 => 'gwaek', 'gwaet', 'gwaep', 'gwaeh', 'goe', 'goeg', 'goegg', 'goegs', 'goen', 'goenj', 'goenh', 'goed', 'goel', 'goelg', 'goelm', 'goelb', + 0x40 => 'goels', 'goelt', 'goelp', 'goelh', 'goem', 'goeb', 'goebs', 'goes', 'goess', 'goeng', 'goej', 'goec', 'goek', 'goet', 'goep', 'goeh', + 0x50 => 'gyo', 'gyog', 'gyogg', 'gyogs', 'gyon', 'gyonj', 'gyonh', 'gyod', 'gyol', 'gyolg', 'gyolm', 'gyolb', 'gyols', 'gyolt', 'gyolp', 'gyolh', + 0x60 => 'gyom', 'gyob', 'gyobs', 'gyos', 'gyoss', 'gyong', 'gyoj', 'gyoc', 'gyok', 'gyot', 'gyop', 'gyoh', 'gu', 'gug', 'gugg', 'gugs', + 0x70 => 'gun', 'gunj', 'gunh', 'gud', 'gul', 'gulg', 'gulm', 'gulb', 'guls', 'gult', 'gulp', 'gulh', 'gum', 'gub', 'gubs', 'gus', + 0x80 => 'guss', 'gung', 'guj', 'guc', 'guk', 'gut', 'gup', 'guh', 'gweo', 'gweog', 'gweogg', 'gweogs', 'gweon', 'gweonj', 'gweonh', 'gweod', + 0x90 => 'gweol', 'gweolg', 'gweolm', 'gweolb', 'gweols', 'gweolt', 'gweolp', 'gweolh', 'gweom', 'gweob', 'gweobs', 'gweos', 'gweoss', 'gweong', 'gweoj', 'gweoc', + 0xA0 => 'gweok', 'gweot', 'gweop', 'gweoh', 'gwe', 'gweg', 'gwegg', 'gwegs', 'gwen', 'gwenj', 'gwenh', 'gwed', 'gwel', 'gwelg', 'gwelm', 'gwelb', + 0xB0 => 'gwels', 'gwelt', 'gwelp', 'gwelh', 'gwem', 'gweb', 'gwebs', 'gwes', 'gwess', 'gweng', 'gwej', 'gwec', 'gwek', 'gwet', 'gwep', 'gweh', + 0xC0 => 'gwi', 'gwig', 'gwigg', 'gwigs', 'gwin', 'gwinj', 'gwinh', 'gwid', 'gwil', 'gwilg', 'gwilm', 'gwilb', 'gwils', 'gwilt', 'gwilp', 'gwilh', + 0xD0 => 'gwim', 'gwib', 'gwibs', 'gwis', 'gwiss', 'gwing', 'gwij', 'gwic', 'gwik', 'gwit', 'gwip', 'gwih', 'gyu', 'gyug', 'gyugg', 'gyugs', + 0xE0 => 'gyun', 'gyunj', 'gyunh', 'gyud', 'gyul', 'gyulg', 'gyulm', 'gyulb', 'gyuls', 'gyult', 'gyulp', 'gyulh', 'gyum', 'gyub', 'gyubs', 'gyus', + 0xF0 => 'gyuss', 'gyung', 'gyuj', 'gyuc', 'gyuk', 'gyut', 'gyup', 'gyuh', 'geu', 'geug', 'geugg', 'geugs', 'geun', 'geunj', 'geunh', 'geud', +]; diff --git a/resources/transliteration-data/xae.php b/resources/transliteration-data/xae.php new file mode 100644 index 000000000..f4abb3f51 --- /dev/null +++ b/resources/transliteration-data/xae.php @@ -0,0 +1,20 @@ + 'geul', 'geulg', 'geulm', 'geulb', 'geuls', 'geult', 'geulp', 'geulh', 'geum', 'geub', 'geubs', 'geus', 'geuss', 'geung', 'geuj', 'geuc', + 0x10 => 'geuk', 'geut', 'geup', 'geuh', 'gyi', 'gyig', 'gyigg', 'gyigs', 'gyin', 'gyinj', 'gyinh', 'gyid', 'gyil', 'gyilg', 'gyilm', 'gyilb', + 0x20 => 'gyils', 'gyilt', 'gyilp', 'gyilh', 'gyim', 'gyib', 'gyibs', 'gyis', 'gyiss', 'gying', 'gyij', 'gyic', 'gyik', 'gyit', 'gyip', 'gyih', + 0x30 => 'gi', 'gig', 'gigg', 'gigs', 'gin', 'ginj', 'ginh', 'gid', 'gil', 'gilg', 'gilm', 'gilb', 'gils', 'gilt', 'gilp', 'gilh', + 0x40 => 'gim', 'gib', 'gibs', 'gis', 'giss', 'ging', 'gij', 'gic', 'gik', 'git', 'gip', 'gih', 'gga', 'ggag', 'ggagg', 'ggags', + 0x50 => 'ggan', 'gganj', 'gganh', 'ggad', 'ggal', 'ggalg', 'ggalm', 'ggalb', 'ggals', 'ggalt', 'ggalp', 'ggalh', 'ggam', 'ggab', 'ggabs', 'ggas', + 0x60 => 'ggass', 'ggang', 'ggaj', 'ggac', 'ggak', 'ggat', 'ggap', 'ggah', 'ggae', 'ggaeg', 'ggaegg', 'ggaegs', 'ggaen', 'ggaenj', 'ggaenh', 'ggaed', + 0x70 => 'ggael', 'ggaelg', 'ggaelm', 'ggaelb', 'ggaels', 'ggaelt', 'ggaelp', 'ggaelh', 'ggaem', 'ggaeb', 'ggaebs', 'ggaes', 'ggaess', 'ggaeng', 'ggaej', 'ggaec', + 0x80 => 'ggaek', 'ggaet', 'ggaep', 'ggaeh', 'ggya', 'ggyag', 'ggyagg', 'ggyags', 'ggyan', 'ggyanj', 'ggyanh', 'ggyad', 'ggyal', 'ggyalg', 'ggyalm', 'ggyalb', + 0x90 => 'ggyals', 'ggyalt', 'ggyalp', 'ggyalh', 'ggyam', 'ggyab', 'ggyabs', 'ggyas', 'ggyass', 'ggyang', 'ggyaj', 'ggyac', 'ggyak', 'ggyat', 'ggyap', 'ggyah', + 0xA0 => 'ggyae', 'ggyaeg', 'ggyaegg', 'ggyaegs', 'ggyaen', 'ggyaenj', 'ggyaenh', 'ggyaed', 'ggyael', 'ggyaelg', 'ggyaelm', 'ggyaelb', 'ggyaels', 'ggyaelt', 'ggyaelp', 'ggyaelh', + 0xB0 => 'ggyaem', 'ggyaeb', 'ggyaebs', 'ggyaes', 'ggyaess', 'ggyaeng', 'ggyaej', 'ggyaec', 'ggyaek', 'ggyaet', 'ggyaep', 'ggyaeh', 'ggeo', 'ggeog', 'ggeogg', 'ggeogs', + 0xC0 => 'ggeon', 'ggeonj', 'ggeonh', 'ggeod', 'ggeol', 'ggeolg', 'ggeolm', 'ggeolb', 'ggeols', 'ggeolt', 'ggeolp', 'ggeolh', 'ggeom', 'ggeob', 'ggeobs', 'ggeos', + 0xD0 => 'ggeoss', 'ggeong', 'ggeoj', 'ggeoc', 'ggeok', 'ggeot', 'ggeop', 'ggeoh', 'gge', 'ggeg', 'ggegg', 'ggegs', 'ggen', 'ggenj', 'ggenh', 'gged', + 0xE0 => 'ggel', 'ggelg', 'ggelm', 'ggelb', 'ggels', 'ggelt', 'ggelp', 'ggelh', 'ggem', 'ggeb', 'ggebs', 'gges', 'ggess', 'ggeng', 'ggej', 'ggec', + 0xF0 => 'ggek', 'gget', 'ggep', 'ggeh', 'ggyeo', 'ggyeog', 'ggyeogg', 'ggyeogs', 'ggyeon', 'ggyeonj', 'ggyeonh', 'ggyeod', 'ggyeol', 'ggyeolg', 'ggyeolm', 'ggyeolb', +]; diff --git a/resources/transliteration-data/xaf.php b/resources/transliteration-data/xaf.php new file mode 100644 index 000000000..fe0d9e4d2 --- /dev/null +++ b/resources/transliteration-data/xaf.php @@ -0,0 +1,20 @@ + 'ggyeols', 'ggyeolt', 'ggyeolp', 'ggyeolh', 'ggyeom', 'ggyeob', 'ggyeobs', 'ggyeos', 'ggyeoss', 'ggyeong', 'ggyeoj', 'ggyeoc', 'ggyeok', 'ggyeot', 'ggyeop', 'ggyeoh', + 0x10 => 'ggye', 'ggyeg', 'ggyegg', 'ggyegs', 'ggyen', 'ggyenj', 'ggyenh', 'ggyed', 'ggyel', 'ggyelg', 'ggyelm', 'ggyelb', 'ggyels', 'ggyelt', 'ggyelp', 'ggyelh', + 0x20 => 'ggyem', 'ggyeb', 'ggyebs', 'ggyes', 'ggyess', 'ggyeng', 'ggyej', 'ggyec', 'ggyek', 'ggyet', 'ggyep', 'ggyeh', 'ggo', 'ggog', 'ggogg', 'ggogs', + 0x30 => 'ggon', 'ggonj', 'ggonh', 'ggod', 'ggol', 'ggolg', 'ggolm', 'ggolb', 'ggols', 'ggolt', 'ggolp', 'ggolh', 'ggom', 'ggob', 'ggobs', 'ggos', + 0x40 => 'ggoss', 'ggong', 'ggoj', 'ggoc', 'ggok', 'ggot', 'ggop', 'ggoh', 'ggwa', 'ggwag', 'ggwagg', 'ggwags', 'ggwan', 'ggwanj', 'ggwanh', 'ggwad', + 0x50 => 'ggwal', 'ggwalg', 'ggwalm', 'ggwalb', 'ggwals', 'ggwalt', 'ggwalp', 'ggwalh', 'ggwam', 'ggwab', 'ggwabs', 'ggwas', 'ggwass', 'ggwang', 'ggwaj', 'ggwac', + 0x60 => 'ggwak', 'ggwat', 'ggwap', 'ggwah', 'ggwae', 'ggwaeg', 'ggwaegg', 'ggwaegs', 'ggwaen', 'ggwaenj', 'ggwaenh', 'ggwaed', 'ggwael', 'ggwaelg', 'ggwaelm', 'ggwaelb', + 0x70 => 'ggwaels', 'ggwaelt', 'ggwaelp', 'ggwaelh', 'ggwaem', 'ggwaeb', 'ggwaebs', 'ggwaes', 'ggwaess', 'ggwaeng', 'ggwaej', 'ggwaec', 'ggwaek', 'ggwaet', 'ggwaep', 'ggwaeh', + 0x80 => 'ggoe', 'ggoeg', 'ggoegg', 'ggoegs', 'ggoen', 'ggoenj', 'ggoenh', 'ggoed', 'ggoel', 'ggoelg', 'ggoelm', 'ggoelb', 'ggoels', 'ggoelt', 'ggoelp', 'ggoelh', + 0x90 => 'ggoem', 'ggoeb', 'ggoebs', 'ggoes', 'ggoess', 'ggoeng', 'ggoej', 'ggoec', 'ggoek', 'ggoet', 'ggoep', 'ggoeh', 'ggyo', 'ggyog', 'ggyogg', 'ggyogs', + 0xA0 => 'ggyon', 'ggyonj', 'ggyonh', 'ggyod', 'ggyol', 'ggyolg', 'ggyolm', 'ggyolb', 'ggyols', 'ggyolt', 'ggyolp', 'ggyolh', 'ggyom', 'ggyob', 'ggyobs', 'ggyos', + 0xB0 => 'ggyoss', 'ggyong', 'ggyoj', 'ggyoc', 'ggyok', 'ggyot', 'ggyop', 'ggyoh', 'ggu', 'ggug', 'ggugg', 'ggugs', 'ggun', 'ggunj', 'ggunh', 'ggud', + 0xC0 => 'ggul', 'ggulg', 'ggulm', 'ggulb', 'gguls', 'ggult', 'ggulp', 'ggulh', 'ggum', 'ggub', 'ggubs', 'ggus', 'gguss', 'ggung', 'gguj', 'gguc', + 0xD0 => 'gguk', 'ggut', 'ggup', 'gguh', 'ggweo', 'ggweog', 'ggweogg', 'ggweogs', 'ggweon', 'ggweonj', 'ggweonh', 'ggweod', 'ggweol', 'ggweolg', 'ggweolm', 'ggweolb', + 0xE0 => 'ggweols', 'ggweolt', 'ggweolp', 'ggweolh', 'ggweom', 'ggweob', 'ggweobs', 'ggweos', 'ggweoss', 'ggweong', 'ggweoj', 'ggweoc', 'ggweok', 'ggweot', 'ggweop', 'ggweoh', + 0xF0 => 'ggwe', 'ggweg', 'ggwegg', 'ggwegs', 'ggwen', 'ggwenj', 'ggwenh', 'ggwed', 'ggwel', 'ggwelg', 'ggwelm', 'ggwelb', 'ggwels', 'ggwelt', 'ggwelp', 'ggwelh', +]; diff --git a/resources/transliteration-data/xb0.php b/resources/transliteration-data/xb0.php new file mode 100644 index 000000000..5454fdb28 --- /dev/null +++ b/resources/transliteration-data/xb0.php @@ -0,0 +1,20 @@ + 'ggwem', 'ggweb', 'ggwebs', 'ggwes', 'ggwess', 'ggweng', 'ggwej', 'ggwec', 'ggwek', 'ggwet', 'ggwep', 'ggweh', 'ggwi', 'ggwig', 'ggwigg', 'ggwigs', + 0x10 => 'ggwin', 'ggwinj', 'ggwinh', 'ggwid', 'ggwil', 'ggwilg', 'ggwilm', 'ggwilb', 'ggwils', 'ggwilt', 'ggwilp', 'ggwilh', 'ggwim', 'ggwib', 'ggwibs', 'ggwis', + 0x20 => 'ggwiss', 'ggwing', 'ggwij', 'ggwic', 'ggwik', 'ggwit', 'ggwip', 'ggwih', 'ggyu', 'ggyug', 'ggyugg', 'ggyugs', 'ggyun', 'ggyunj', 'ggyunh', 'ggyud', + 0x30 => 'ggyul', 'ggyulg', 'ggyulm', 'ggyulb', 'ggyuls', 'ggyult', 'ggyulp', 'ggyulh', 'ggyum', 'ggyub', 'ggyubs', 'ggyus', 'ggyuss', 'ggyung', 'ggyuj', 'ggyuc', + 0x40 => 'ggyuk', 'ggyut', 'ggyup', 'ggyuh', 'ggeu', 'ggeug', 'ggeugg', 'ggeugs', 'ggeun', 'ggeunj', 'ggeunh', 'ggeud', 'ggeul', 'ggeulg', 'ggeulm', 'ggeulb', + 0x50 => 'ggeuls', 'ggeult', 'ggeulp', 'ggeulh', 'ggeum', 'ggeub', 'ggeubs', 'ggeus', 'ggeuss', 'ggeung', 'ggeuj', 'ggeuc', 'ggeuk', 'ggeut', 'ggeup', 'ggeuh', + 0x60 => 'ggyi', 'ggyig', 'ggyigg', 'ggyigs', 'ggyin', 'ggyinj', 'ggyinh', 'ggyid', 'ggyil', 'ggyilg', 'ggyilm', 'ggyilb', 'ggyils', 'ggyilt', 'ggyilp', 'ggyilh', + 0x70 => 'ggyim', 'ggyib', 'ggyibs', 'ggyis', 'ggyiss', 'ggying', 'ggyij', 'ggyic', 'ggyik', 'ggyit', 'ggyip', 'ggyih', 'ggi', 'ggig', 'ggigg', 'ggigs', + 0x80 => 'ggin', 'gginj', 'gginh', 'ggid', 'ggil', 'ggilg', 'ggilm', 'ggilb', 'ggils', 'ggilt', 'ggilp', 'ggilh', 'ggim', 'ggib', 'ggibs', 'ggis', + 0x90 => 'ggiss', 'gging', 'ggij', 'ggic', 'ggik', 'ggit', 'ggip', 'ggih', 'na', 'nag', 'nagg', 'nags', 'nan', 'nanj', 'nanh', 'nad', + 0xA0 => 'nal', 'nalg', 'nalm', 'nalb', 'nals', 'nalt', 'nalp', 'nalh', 'nam', 'nab', 'nabs', 'nas', 'nass', 'nang', 'naj', 'nac', + 0xB0 => 'nak', 'nat', 'nap', 'nah', 'nae', 'naeg', 'naegg', 'naegs', 'naen', 'naenj', 'naenh', 'naed', 'nael', 'naelg', 'naelm', 'naelb', + 0xC0 => 'naels', 'naelt', 'naelp', 'naelh', 'naem', 'naeb', 'naebs', 'naes', 'naess', 'naeng', 'naej', 'naec', 'naek', 'naet', 'naep', 'naeh', + 0xD0 => 'nya', 'nyag', 'nyagg', 'nyags', 'nyan', 'nyanj', 'nyanh', 'nyad', 'nyal', 'nyalg', 'nyalm', 'nyalb', 'nyals', 'nyalt', 'nyalp', 'nyalh', + 0xE0 => 'nyam', 'nyab', 'nyabs', 'nyas', 'nyass', 'nyang', 'nyaj', 'nyac', 'nyak', 'nyat', 'nyap', 'nyah', 'nyae', 'nyaeg', 'nyaegg', 'nyaegs', + 0xF0 => 'nyaen', 'nyaenj', 'nyaenh', 'nyaed', 'nyael', 'nyaelg', 'nyaelm', 'nyaelb', 'nyaels', 'nyaelt', 'nyaelp', 'nyaelh', 'nyaem', 'nyaeb', 'nyaebs', 'nyaes', +]; diff --git a/resources/transliteration-data/xb1.php b/resources/transliteration-data/xb1.php new file mode 100644 index 000000000..65205b473 --- /dev/null +++ b/resources/transliteration-data/xb1.php @@ -0,0 +1,20 @@ + 'nyaess', 'nyaeng', 'nyaej', 'nyaec', 'nyaek', 'nyaet', 'nyaep', 'nyaeh', 'neo', 'neog', 'neogg', 'neogs', 'neon', 'neonj', 'neonh', 'neod', + 0x10 => 'neol', 'neolg', 'neolm', 'neolb', 'neols', 'neolt', 'neolp', 'neolh', 'neom', 'neob', 'neobs', 'neos', 'neoss', 'neong', 'neoj', 'neoc', + 0x20 => 'neok', 'neot', 'neop', 'neoh', 'ne', 'neg', 'negg', 'negs', 'nen', 'nenj', 'nenh', 'ned', 'nel', 'nelg', 'nelm', 'nelb', + 0x30 => 'nels', 'nelt', 'nelp', 'nelh', 'nem', 'neb', 'nebs', 'nes', 'ness', 'neng', 'nej', 'nec', 'nek', 'net', 'nep', 'neh', + 0x40 => 'nyeo', 'nyeog', 'nyeogg', 'nyeogs', 'nyeon', 'nyeonj', 'nyeonh', 'nyeod', 'nyeol', 'nyeolg', 'nyeolm', 'nyeolb', 'nyeols', 'nyeolt', 'nyeolp', 'nyeolh', + 0x50 => 'nyeom', 'nyeob', 'nyeobs', 'nyeos', 'nyeoss', 'nyeong', 'nyeoj', 'nyeoc', 'nyeok', 'nyeot', 'nyeop', 'nyeoh', 'nye', 'nyeg', 'nyegg', 'nyegs', + 0x60 => 'nyen', 'nyenj', 'nyenh', 'nyed', 'nyel', 'nyelg', 'nyelm', 'nyelb', 'nyels', 'nyelt', 'nyelp', 'nyelh', 'nyem', 'nyeb', 'nyebs', 'nyes', + 0x70 => 'nyess', 'nyeng', 'nyej', 'nyec', 'nyek', 'nyet', 'nyep', 'nyeh', 'no', 'nog', 'nogg', 'nogs', 'non', 'nonj', 'nonh', 'nod', + 0x80 => 'nol', 'nolg', 'nolm', 'nolb', 'nols', 'nolt', 'nolp', 'nolh', 'nom', 'nob', 'nobs', 'nos', 'noss', 'nong', 'noj', 'noc', + 0x90 => 'nok', 'not', 'nop', 'noh', 'nwa', 'nwag', 'nwagg', 'nwags', 'nwan', 'nwanj', 'nwanh', 'nwad', 'nwal', 'nwalg', 'nwalm', 'nwalb', + 0xA0 => 'nwals', 'nwalt', 'nwalp', 'nwalh', 'nwam', 'nwab', 'nwabs', 'nwas', 'nwass', 'nwang', 'nwaj', 'nwac', 'nwak', 'nwat', 'nwap', 'nwah', + 0xB0 => 'nwae', 'nwaeg', 'nwaegg', 'nwaegs', 'nwaen', 'nwaenj', 'nwaenh', 'nwaed', 'nwael', 'nwaelg', 'nwaelm', 'nwaelb', 'nwaels', 'nwaelt', 'nwaelp', 'nwaelh', + 0xC0 => 'nwaem', 'nwaeb', 'nwaebs', 'nwaes', 'nwaess', 'nwaeng', 'nwaej', 'nwaec', 'nwaek', 'nwaet', 'nwaep', 'nwaeh', 'noe', 'noeg', 'noegg', 'noegs', + 0xD0 => 'noen', 'noenj', 'noenh', 'noed', 'noel', 'noelg', 'noelm', 'noelb', 'noels', 'noelt', 'noelp', 'noelh', 'noem', 'noeb', 'noebs', 'noes', + 0xE0 => 'noess', 'noeng', 'noej', 'noec', 'noek', 'noet', 'noep', 'noeh', 'nyo', 'nyog', 'nyogg', 'nyogs', 'nyon', 'nyonj', 'nyonh', 'nyod', + 0xF0 => 'nyol', 'nyolg', 'nyolm', 'nyolb', 'nyols', 'nyolt', 'nyolp', 'nyolh', 'nyom', 'nyob', 'nyobs', 'nyos', 'nyoss', 'nyong', 'nyoj', 'nyoc', +]; diff --git a/resources/transliteration-data/xb2.php b/resources/transliteration-data/xb2.php new file mode 100644 index 000000000..67266bc05 --- /dev/null +++ b/resources/transliteration-data/xb2.php @@ -0,0 +1,20 @@ + 'nyok', 'nyot', 'nyop', 'nyoh', 'nu', 'nug', 'nugg', 'nugs', 'nun', 'nunj', 'nunh', 'nud', 'nul', 'nulg', 'nulm', 'nulb', + 0x10 => 'nuls', 'nult', 'nulp', 'nulh', 'num', 'nub', 'nubs', 'nus', 'nuss', 'nung', 'nuj', 'nuc', 'nuk', 'nut', 'nup', 'nuh', + 0x20 => 'nweo', 'nweog', 'nweogg', 'nweogs', 'nweon', 'nweonj', 'nweonh', 'nweod', 'nweol', 'nweolg', 'nweolm', 'nweolb', 'nweols', 'nweolt', 'nweolp', 'nweolh', + 0x30 => 'nweom', 'nweob', 'nweobs', 'nweos', 'nweoss', 'nweong', 'nweoj', 'nweoc', 'nweok', 'nweot', 'nweop', 'nweoh', 'nwe', 'nweg', 'nwegg', 'nwegs', + 0x40 => 'nwen', 'nwenj', 'nwenh', 'nwed', 'nwel', 'nwelg', 'nwelm', 'nwelb', 'nwels', 'nwelt', 'nwelp', 'nwelh', 'nwem', 'nweb', 'nwebs', 'nwes', + 0x50 => 'nwess', 'nweng', 'nwej', 'nwec', 'nwek', 'nwet', 'nwep', 'nweh', 'nwi', 'nwig', 'nwigg', 'nwigs', 'nwin', 'nwinj', 'nwinh', 'nwid', + 0x60 => 'nwil', 'nwilg', 'nwilm', 'nwilb', 'nwils', 'nwilt', 'nwilp', 'nwilh', 'nwim', 'nwib', 'nwibs', 'nwis', 'nwiss', 'nwing', 'nwij', 'nwic', + 0x70 => 'nwik', 'nwit', 'nwip', 'nwih', 'nyu', 'nyug', 'nyugg', 'nyugs', 'nyun', 'nyunj', 'nyunh', 'nyud', 'nyul', 'nyulg', 'nyulm', 'nyulb', + 0x80 => 'nyuls', 'nyult', 'nyulp', 'nyulh', 'nyum', 'nyub', 'nyubs', 'nyus', 'nyuss', 'nyung', 'nyuj', 'nyuc', 'nyuk', 'nyut', 'nyup', 'nyuh', + 0x90 => 'neu', 'neug', 'neugg', 'neugs', 'neun', 'neunj', 'neunh', 'neud', 'neul', 'neulg', 'neulm', 'neulb', 'neuls', 'neult', 'neulp', 'neulh', + 0xA0 => 'neum', 'neub', 'neubs', 'neus', 'neuss', 'neung', 'neuj', 'neuc', 'neuk', 'neut', 'neup', 'neuh', 'nyi', 'nyig', 'nyigg', 'nyigs', + 0xB0 => 'nyin', 'nyinj', 'nyinh', 'nyid', 'nyil', 'nyilg', 'nyilm', 'nyilb', 'nyils', 'nyilt', 'nyilp', 'nyilh', 'nyim', 'nyib', 'nyibs', 'nyis', + 0xC0 => 'nyiss', 'nying', 'nyij', 'nyic', 'nyik', 'nyit', 'nyip', 'nyih', 'ni', 'nig', 'nigg', 'nigs', 'nin', 'ninj', 'ninh', 'nid', + 0xD0 => 'nil', 'nilg', 'nilm', 'nilb', 'nils', 'nilt', 'nilp', 'nilh', 'nim', 'nib', 'nibs', 'nis', 'niss', 'ning', 'nij', 'nic', + 0xE0 => 'nik', 'nit', 'nip', 'nih', 'da', 'dag', 'dagg', 'dags', 'dan', 'danj', 'danh', 'dad', 'dal', 'dalg', 'dalm', 'dalb', + 0xF0 => 'dals', 'dalt', 'dalp', 'dalh', 'dam', 'dab', 'dabs', 'das', 'dass', 'dang', 'daj', 'dac', 'dak', 'dat', 'dap', 'dah', +]; diff --git a/resources/transliteration-data/xb3.php b/resources/transliteration-data/xb3.php new file mode 100644 index 000000000..ef486796f --- /dev/null +++ b/resources/transliteration-data/xb3.php @@ -0,0 +1,20 @@ + 'dae', 'daeg', 'daegg', 'daegs', 'daen', 'daenj', 'daenh', 'daed', 'dael', 'daelg', 'daelm', 'daelb', 'daels', 'daelt', 'daelp', 'daelh', + 0x10 => 'daem', 'daeb', 'daebs', 'daes', 'daess', 'daeng', 'daej', 'daec', 'daek', 'daet', 'daep', 'daeh', 'dya', 'dyag', 'dyagg', 'dyags', + 0x20 => 'dyan', 'dyanj', 'dyanh', 'dyad', 'dyal', 'dyalg', 'dyalm', 'dyalb', 'dyals', 'dyalt', 'dyalp', 'dyalh', 'dyam', 'dyab', 'dyabs', 'dyas', + 0x30 => 'dyass', 'dyang', 'dyaj', 'dyac', 'dyak', 'dyat', 'dyap', 'dyah', 'dyae', 'dyaeg', 'dyaegg', 'dyaegs', 'dyaen', 'dyaenj', 'dyaenh', 'dyaed', + 0x40 => 'dyael', 'dyaelg', 'dyaelm', 'dyaelb', 'dyaels', 'dyaelt', 'dyaelp', 'dyaelh', 'dyaem', 'dyaeb', 'dyaebs', 'dyaes', 'dyaess', 'dyaeng', 'dyaej', 'dyaec', + 0x50 => 'dyaek', 'dyaet', 'dyaep', 'dyaeh', 'deo', 'deog', 'deogg', 'deogs', 'deon', 'deonj', 'deonh', 'deod', 'deol', 'deolg', 'deolm', 'deolb', + 0x60 => 'deols', 'deolt', 'deolp', 'deolh', 'deom', 'deob', 'deobs', 'deos', 'deoss', 'deong', 'deoj', 'deoc', 'deok', 'deot', 'deop', 'deoh', + 0x70 => 'de', 'deg', 'degg', 'degs', 'den', 'denj', 'denh', 'ded', 'del', 'delg', 'delm', 'delb', 'dels', 'delt', 'delp', 'delh', + 0x80 => 'dem', 'deb', 'debs', 'des', 'dess', 'deng', 'dej', 'dec', 'dek', 'det', 'dep', 'deh', 'dyeo', 'dyeog', 'dyeogg', 'dyeogs', + 0x90 => 'dyeon', 'dyeonj', 'dyeonh', 'dyeod', 'dyeol', 'dyeolg', 'dyeolm', 'dyeolb', 'dyeols', 'dyeolt', 'dyeolp', 'dyeolh', 'dyeom', 'dyeob', 'dyeobs', 'dyeos', + 0xA0 => 'dyeoss', 'dyeong', 'dyeoj', 'dyeoc', 'dyeok', 'dyeot', 'dyeop', 'dyeoh', 'dye', 'dyeg', 'dyegg', 'dyegs', 'dyen', 'dyenj', 'dyenh', 'dyed', + 0xB0 => 'dyel', 'dyelg', 'dyelm', 'dyelb', 'dyels', 'dyelt', 'dyelp', 'dyelh', 'dyem', 'dyeb', 'dyebs', 'dyes', 'dyess', 'dyeng', 'dyej', 'dyec', + 0xC0 => 'dyek', 'dyet', 'dyep', 'dyeh', 'do', 'dog', 'dogg', 'dogs', 'don', 'donj', 'donh', 'dod', 'dol', 'dolg', 'dolm', 'dolb', + 0xD0 => 'dols', 'dolt', 'dolp', 'dolh', 'dom', 'dob', 'dobs', 'dos', 'doss', 'dong', 'doj', 'doc', 'dok', 'dot', 'dop', 'doh', + 0xE0 => 'dwa', 'dwag', 'dwagg', 'dwags', 'dwan', 'dwanj', 'dwanh', 'dwad', 'dwal', 'dwalg', 'dwalm', 'dwalb', 'dwals', 'dwalt', 'dwalp', 'dwalh', + 0xF0 => 'dwam', 'dwab', 'dwabs', 'dwas', 'dwass', 'dwang', 'dwaj', 'dwac', 'dwak', 'dwat', 'dwap', 'dwah', 'dwae', 'dwaeg', 'dwaegg', 'dwaegs', +]; diff --git a/resources/transliteration-data/xb4.php b/resources/transliteration-data/xb4.php new file mode 100644 index 000000000..3616ad2b1 --- /dev/null +++ b/resources/transliteration-data/xb4.php @@ -0,0 +1,20 @@ + 'dwaen', 'dwaenj', 'dwaenh', 'dwaed', 'dwael', 'dwaelg', 'dwaelm', 'dwaelb', 'dwaels', 'dwaelt', 'dwaelp', 'dwaelh', 'dwaem', 'dwaeb', 'dwaebs', 'dwaes', + 0x10 => 'dwaess', 'dwaeng', 'dwaej', 'dwaec', 'dwaek', 'dwaet', 'dwaep', 'dwaeh', 'doe', 'doeg', 'doegg', 'doegs', 'doen', 'doenj', 'doenh', 'doed', + 0x20 => 'doel', 'doelg', 'doelm', 'doelb', 'doels', 'doelt', 'doelp', 'doelh', 'doem', 'doeb', 'doebs', 'does', 'doess', 'doeng', 'doej', 'doec', + 0x30 => 'doek', 'doet', 'doep', 'doeh', 'dyo', 'dyog', 'dyogg', 'dyogs', 'dyon', 'dyonj', 'dyonh', 'dyod', 'dyol', 'dyolg', 'dyolm', 'dyolb', + 0x40 => 'dyols', 'dyolt', 'dyolp', 'dyolh', 'dyom', 'dyob', 'dyobs', 'dyos', 'dyoss', 'dyong', 'dyoj', 'dyoc', 'dyok', 'dyot', 'dyop', 'dyoh', + 0x50 => 'du', 'dug', 'dugg', 'dugs', 'dun', 'dunj', 'dunh', 'dud', 'dul', 'dulg', 'dulm', 'dulb', 'duls', 'dult', 'dulp', 'dulh', + 0x60 => 'dum', 'dub', 'dubs', 'dus', 'duss', 'dung', 'duj', 'duc', 'duk', 'dut', 'dup', 'duh', 'dweo', 'dweog', 'dweogg', 'dweogs', + 0x70 => 'dweon', 'dweonj', 'dweonh', 'dweod', 'dweol', 'dweolg', 'dweolm', 'dweolb', 'dweols', 'dweolt', 'dweolp', 'dweolh', 'dweom', 'dweob', 'dweobs', 'dweos', + 0x80 => 'dweoss', 'dweong', 'dweoj', 'dweoc', 'dweok', 'dweot', 'dweop', 'dweoh', 'dwe', 'dweg', 'dwegg', 'dwegs', 'dwen', 'dwenj', 'dwenh', 'dwed', + 0x90 => 'dwel', 'dwelg', 'dwelm', 'dwelb', 'dwels', 'dwelt', 'dwelp', 'dwelh', 'dwem', 'dweb', 'dwebs', 'dwes', 'dwess', 'dweng', 'dwej', 'dwec', + 0xA0 => 'dwek', 'dwet', 'dwep', 'dweh', 'dwi', 'dwig', 'dwigg', 'dwigs', 'dwin', 'dwinj', 'dwinh', 'dwid', 'dwil', 'dwilg', 'dwilm', 'dwilb', + 0xB0 => 'dwils', 'dwilt', 'dwilp', 'dwilh', 'dwim', 'dwib', 'dwibs', 'dwis', 'dwiss', 'dwing', 'dwij', 'dwic', 'dwik', 'dwit', 'dwip', 'dwih', + 0xC0 => 'dyu', 'dyug', 'dyugg', 'dyugs', 'dyun', 'dyunj', 'dyunh', 'dyud', 'dyul', 'dyulg', 'dyulm', 'dyulb', 'dyuls', 'dyult', 'dyulp', 'dyulh', + 0xD0 => 'dyum', 'dyub', 'dyubs', 'dyus', 'dyuss', 'dyung', 'dyuj', 'dyuc', 'dyuk', 'dyut', 'dyup', 'dyuh', 'deu', 'deug', 'deugg', 'deugs', + 0xE0 => 'deun', 'deunj', 'deunh', 'deud', 'deul', 'deulg', 'deulm', 'deulb', 'deuls', 'deult', 'deulp', 'deulh', 'deum', 'deub', 'deubs', 'deus', + 0xF0 => 'deuss', 'deung', 'deuj', 'deuc', 'deuk', 'deut', 'deup', 'deuh', 'dyi', 'dyig', 'dyigg', 'dyigs', 'dyin', 'dyinj', 'dyinh', 'dyid', +]; diff --git a/resources/transliteration-data/xb5.php b/resources/transliteration-data/xb5.php new file mode 100644 index 000000000..9823a38e5 --- /dev/null +++ b/resources/transliteration-data/xb5.php @@ -0,0 +1,20 @@ + 'dyil', 'dyilg', 'dyilm', 'dyilb', 'dyils', 'dyilt', 'dyilp', 'dyilh', 'dyim', 'dyib', 'dyibs', 'dyis', 'dyiss', 'dying', 'dyij', 'dyic', + 0x10 => 'dyik', 'dyit', 'dyip', 'dyih', 'di', 'dig', 'digg', 'digs', 'din', 'dinj', 'dinh', 'did', 'dil', 'dilg', 'dilm', 'dilb', + 0x20 => 'dils', 'dilt', 'dilp', 'dilh', 'dim', 'dib', 'dibs', 'dis', 'diss', 'ding', 'dij', 'dic', 'dik', 'dit', 'dip', 'dih', + 0x30 => 'dda', 'ddag', 'ddagg', 'ddags', 'ddan', 'ddanj', 'ddanh', 'ddad', 'ddal', 'ddalg', 'ddalm', 'ddalb', 'ddals', 'ddalt', 'ddalp', 'ddalh', + 0x40 => 'ddam', 'ddab', 'ddabs', 'ddas', 'ddass', 'ddang', 'ddaj', 'ddac', 'ddak', 'ddat', 'ddap', 'ddah', 'ddae', 'ddaeg', 'ddaegg', 'ddaegs', + 0x50 => 'ddaen', 'ddaenj', 'ddaenh', 'ddaed', 'ddael', 'ddaelg', 'ddaelm', 'ddaelb', 'ddaels', 'ddaelt', 'ddaelp', 'ddaelh', 'ddaem', 'ddaeb', 'ddaebs', 'ddaes', + 0x60 => 'ddaess', 'ddaeng', 'ddaej', 'ddaec', 'ddaek', 'ddaet', 'ddaep', 'ddaeh', 'ddya', 'ddyag', 'ddyagg', 'ddyags', 'ddyan', 'ddyanj', 'ddyanh', 'ddyad', + 0x70 => 'ddyal', 'ddyalg', 'ddyalm', 'ddyalb', 'ddyals', 'ddyalt', 'ddyalp', 'ddyalh', 'ddyam', 'ddyab', 'ddyabs', 'ddyas', 'ddyass', 'ddyang', 'ddyaj', 'ddyac', + 0x80 => 'ddyak', 'ddyat', 'ddyap', 'ddyah', 'ddyae', 'ddyaeg', 'ddyaegg', 'ddyaegs', 'ddyaen', 'ddyaenj', 'ddyaenh', 'ddyaed', 'ddyael', 'ddyaelg', 'ddyaelm', 'ddyaelb', + 0x90 => 'ddyaels', 'ddyaelt', 'ddyaelp', 'ddyaelh', 'ddyaem', 'ddyaeb', 'ddyaebs', 'ddyaes', 'ddyaess', 'ddyaeng', 'ddyaej', 'ddyaec', 'ddyaek', 'ddyaet', 'ddyaep', 'ddyaeh', + 0xA0 => 'ddeo', 'ddeog', 'ddeogg', 'ddeogs', 'ddeon', 'ddeonj', 'ddeonh', 'ddeod', 'ddeol', 'ddeolg', 'ddeolm', 'ddeolb', 'ddeols', 'ddeolt', 'ddeolp', 'ddeolh', + 0xB0 => 'ddeom', 'ddeob', 'ddeobs', 'ddeos', 'ddeoss', 'ddeong', 'ddeoj', 'ddeoc', 'ddeok', 'ddeot', 'ddeop', 'ddeoh', 'dde', 'ddeg', 'ddegg', 'ddegs', + 0xC0 => 'dden', 'ddenj', 'ddenh', 'dded', 'ddel', 'ddelg', 'ddelm', 'ddelb', 'ddels', 'ddelt', 'ddelp', 'ddelh', 'ddem', 'ddeb', 'ddebs', 'ddes', + 0xD0 => 'ddess', 'ddeng', 'ddej', 'ddec', 'ddek', 'ddet', 'ddep', 'ddeh', 'ddyeo', 'ddyeog', 'ddyeogg', 'ddyeogs', 'ddyeon', 'ddyeonj', 'ddyeonh', 'ddyeod', + 0xE0 => 'ddyeol', 'ddyeolg', 'ddyeolm', 'ddyeolb', 'ddyeols', 'ddyeolt', 'ddyeolp', 'ddyeolh', 'ddyeom', 'ddyeob', 'ddyeobs', 'ddyeos', 'ddyeoss', 'ddyeong', 'ddyeoj', 'ddyeoc', + 0xF0 => 'ddyeok', 'ddyeot', 'ddyeop', 'ddyeoh', 'ddye', 'ddyeg', 'ddyegg', 'ddyegs', 'ddyen', 'ddyenj', 'ddyenh', 'ddyed', 'ddyel', 'ddyelg', 'ddyelm', 'ddyelb', +]; diff --git a/resources/transliteration-data/xb6.php b/resources/transliteration-data/xb6.php new file mode 100644 index 000000000..919de06ab --- /dev/null +++ b/resources/transliteration-data/xb6.php @@ -0,0 +1,20 @@ + 'ddyels', 'ddyelt', 'ddyelp', 'ddyelh', 'ddyem', 'ddyeb', 'ddyebs', 'ddyes', 'ddyess', 'ddyeng', 'ddyej', 'ddyec', 'ddyek', 'ddyet', 'ddyep', 'ddyeh', + 0x10 => 'ddo', 'ddog', 'ddogg', 'ddogs', 'ddon', 'ddonj', 'ddonh', 'ddod', 'ddol', 'ddolg', 'ddolm', 'ddolb', 'ddols', 'ddolt', 'ddolp', 'ddolh', + 0x20 => 'ddom', 'ddob', 'ddobs', 'ddos', 'ddoss', 'ddong', 'ddoj', 'ddoc', 'ddok', 'ddot', 'ddop', 'ddoh', 'ddwa', 'ddwag', 'ddwagg', 'ddwags', + 0x30 => 'ddwan', 'ddwanj', 'ddwanh', 'ddwad', 'ddwal', 'ddwalg', 'ddwalm', 'ddwalb', 'ddwals', 'ddwalt', 'ddwalp', 'ddwalh', 'ddwam', 'ddwab', 'ddwabs', 'ddwas', + 0x40 => 'ddwass', 'ddwang', 'ddwaj', 'ddwac', 'ddwak', 'ddwat', 'ddwap', 'ddwah', 'ddwae', 'ddwaeg', 'ddwaegg', 'ddwaegs', 'ddwaen', 'ddwaenj', 'ddwaenh', 'ddwaed', + 0x50 => 'ddwael', 'ddwaelg', 'ddwaelm', 'ddwaelb', 'ddwaels', 'ddwaelt', 'ddwaelp', 'ddwaelh', 'ddwaem', 'ddwaeb', 'ddwaebs', 'ddwaes', 'ddwaess', 'ddwaeng', 'ddwaej', 'ddwaec', + 0x60 => 'ddwaek', 'ddwaet', 'ddwaep', 'ddwaeh', 'ddoe', 'ddoeg', 'ddoegg', 'ddoegs', 'ddoen', 'ddoenj', 'ddoenh', 'ddoed', 'ddoel', 'ddoelg', 'ddoelm', 'ddoelb', + 0x70 => 'ddoels', 'ddoelt', 'ddoelp', 'ddoelh', 'ddoem', 'ddoeb', 'ddoebs', 'ddoes', 'ddoess', 'ddoeng', 'ddoej', 'ddoec', 'ddoek', 'ddoet', 'ddoep', 'ddoeh', + 0x80 => 'ddyo', 'ddyog', 'ddyogg', 'ddyogs', 'ddyon', 'ddyonj', 'ddyonh', 'ddyod', 'ddyol', 'ddyolg', 'ddyolm', 'ddyolb', 'ddyols', 'ddyolt', 'ddyolp', 'ddyolh', + 0x90 => 'ddyom', 'ddyob', 'ddyobs', 'ddyos', 'ddyoss', 'ddyong', 'ddyoj', 'ddyoc', 'ddyok', 'ddyot', 'ddyop', 'ddyoh', 'ddu', 'ddug', 'ddugg', 'ddugs', + 0xA0 => 'ddun', 'ddunj', 'ddunh', 'ddud', 'ddul', 'ddulg', 'ddulm', 'ddulb', 'dduls', 'ddult', 'ddulp', 'ddulh', 'ddum', 'ddub', 'ddubs', 'ddus', + 0xB0 => 'dduss', 'ddung', 'dduj', 'dduc', 'dduk', 'ddut', 'ddup', 'dduh', 'ddweo', 'ddweog', 'ddweogg', 'ddweogs', 'ddweon', 'ddweonj', 'ddweonh', 'ddweod', + 0xC0 => 'ddweol', 'ddweolg', 'ddweolm', 'ddweolb', 'ddweols', 'ddweolt', 'ddweolp', 'ddweolh', 'ddweom', 'ddweob', 'ddweobs', 'ddweos', 'ddweoss', 'ddweong', 'ddweoj', 'ddweoc', + 0xD0 => 'ddweok', 'ddweot', 'ddweop', 'ddweoh', 'ddwe', 'ddweg', 'ddwegg', 'ddwegs', 'ddwen', 'ddwenj', 'ddwenh', 'ddwed', 'ddwel', 'ddwelg', 'ddwelm', 'ddwelb', + 0xE0 => 'ddwels', 'ddwelt', 'ddwelp', 'ddwelh', 'ddwem', 'ddweb', 'ddwebs', 'ddwes', 'ddwess', 'ddweng', 'ddwej', 'ddwec', 'ddwek', 'ddwet', 'ddwep', 'ddweh', + 0xF0 => 'ddwi', 'ddwig', 'ddwigg', 'ddwigs', 'ddwin', 'ddwinj', 'ddwinh', 'ddwid', 'ddwil', 'ddwilg', 'ddwilm', 'ddwilb', 'ddwils', 'ddwilt', 'ddwilp', 'ddwilh', +]; diff --git a/resources/transliteration-data/xb7.php b/resources/transliteration-data/xb7.php new file mode 100644 index 000000000..2aae55651 --- /dev/null +++ b/resources/transliteration-data/xb7.php @@ -0,0 +1,20 @@ + 'ddwim', 'ddwib', 'ddwibs', 'ddwis', 'ddwiss', 'ddwing', 'ddwij', 'ddwic', 'ddwik', 'ddwit', 'ddwip', 'ddwih', 'ddyu', 'ddyug', 'ddyugg', 'ddyugs', + 0x10 => 'ddyun', 'ddyunj', 'ddyunh', 'ddyud', 'ddyul', 'ddyulg', 'ddyulm', 'ddyulb', 'ddyuls', 'ddyult', 'ddyulp', 'ddyulh', 'ddyum', 'ddyub', 'ddyubs', 'ddyus', + 0x20 => 'ddyuss', 'ddyung', 'ddyuj', 'ddyuc', 'ddyuk', 'ddyut', 'ddyup', 'ddyuh', 'ddeu', 'ddeug', 'ddeugg', 'ddeugs', 'ddeun', 'ddeunj', 'ddeunh', 'ddeud', + 0x30 => 'ddeul', 'ddeulg', 'ddeulm', 'ddeulb', 'ddeuls', 'ddeult', 'ddeulp', 'ddeulh', 'ddeum', 'ddeub', 'ddeubs', 'ddeus', 'ddeuss', 'ddeung', 'ddeuj', 'ddeuc', + 0x40 => 'ddeuk', 'ddeut', 'ddeup', 'ddeuh', 'ddyi', 'ddyig', 'ddyigg', 'ddyigs', 'ddyin', 'ddyinj', 'ddyinh', 'ddyid', 'ddyil', 'ddyilg', 'ddyilm', 'ddyilb', + 0x50 => 'ddyils', 'ddyilt', 'ddyilp', 'ddyilh', 'ddyim', 'ddyib', 'ddyibs', 'ddyis', 'ddyiss', 'ddying', 'ddyij', 'ddyic', 'ddyik', 'ddyit', 'ddyip', 'ddyih', + 0x60 => 'ddi', 'ddig', 'ddigg', 'ddigs', 'ddin', 'ddinj', 'ddinh', 'ddid', 'ddil', 'ddilg', 'ddilm', 'ddilb', 'ddils', 'ddilt', 'ddilp', 'ddilh', + 0x70 => 'ddim', 'ddib', 'ddibs', 'ddis', 'ddiss', 'dding', 'ddij', 'ddic', 'ddik', 'ddit', 'ddip', 'ddih', 'ra', 'rag', 'ragg', 'rags', + 0x80 => 'ran', 'ranj', 'ranh', 'rad', 'ral', 'ralg', 'ralm', 'ralb', 'rals', 'ralt', 'ralp', 'ralh', 'ram', 'rab', 'rabs', 'ras', + 0x90 => 'rass', 'rang', 'raj', 'rac', 'rak', 'rat', 'rap', 'rah', 'rae', 'raeg', 'raegg', 'raegs', 'raen', 'raenj', 'raenh', 'raed', + 0xA0 => 'rael', 'raelg', 'raelm', 'raelb', 'raels', 'raelt', 'raelp', 'raelh', 'raem', 'raeb', 'raebs', 'raes', 'raess', 'raeng', 'raej', 'raec', + 0xB0 => 'raek', 'raet', 'raep', 'raeh', 'rya', 'ryag', 'ryagg', 'ryags', 'ryan', 'ryanj', 'ryanh', 'ryad', 'ryal', 'ryalg', 'ryalm', 'ryalb', + 0xC0 => 'ryals', 'ryalt', 'ryalp', 'ryalh', 'ryam', 'ryab', 'ryabs', 'ryas', 'ryass', 'ryang', 'ryaj', 'ryac', 'ryak', 'ryat', 'ryap', 'ryah', + 0xD0 => 'ryae', 'ryaeg', 'ryaegg', 'ryaegs', 'ryaen', 'ryaenj', 'ryaenh', 'ryaed', 'ryael', 'ryaelg', 'ryaelm', 'ryaelb', 'ryaels', 'ryaelt', 'ryaelp', 'ryaelh', + 0xE0 => 'ryaem', 'ryaeb', 'ryaebs', 'ryaes', 'ryaess', 'ryaeng', 'ryaej', 'ryaec', 'ryaek', 'ryaet', 'ryaep', 'ryaeh', 'reo', 'reog', 'reogg', 'reogs', + 0xF0 => 'reon', 'reonj', 'reonh', 'reod', 'reol', 'reolg', 'reolm', 'reolb', 'reols', 'reolt', 'reolp', 'reolh', 'reom', 'reob', 'reobs', 'reos', +]; diff --git a/resources/transliteration-data/xb8.php b/resources/transliteration-data/xb8.php new file mode 100644 index 000000000..7353b3a56 --- /dev/null +++ b/resources/transliteration-data/xb8.php @@ -0,0 +1,20 @@ + 'reoss', 'reong', 'reoj', 'reoc', 'reok', 'reot', 'reop', 'reoh', 're', 'reg', 'regg', 'regs', 'ren', 'renj', 'renh', 'red', + 0x10 => 'rel', 'relg', 'relm', 'relb', 'rels', 'relt', 'relp', 'relh', 'rem', 'reb', 'rebs', 'res', 'ress', 'reng', 'rej', 'rec', + 0x20 => 'rek', 'ret', 'rep', 'reh', 'ryeo', 'ryeog', 'ryeogg', 'ryeogs', 'ryeon', 'ryeonj', 'ryeonh', 'ryeod', 'ryeol', 'ryeolg', 'ryeolm', 'ryeolb', + 0x30 => 'ryeols', 'ryeolt', 'ryeolp', 'ryeolh', 'ryeom', 'ryeob', 'ryeobs', 'ryeos', 'ryeoss', 'ryeong', 'ryeoj', 'ryeoc', 'ryeok', 'ryeot', 'ryeop', 'ryeoh', + 0x40 => 'rye', 'ryeg', 'ryegg', 'ryegs', 'ryen', 'ryenj', 'ryenh', 'ryed', 'ryel', 'ryelg', 'ryelm', 'ryelb', 'ryels', 'ryelt', 'ryelp', 'ryelh', + 0x50 => 'ryem', 'ryeb', 'ryebs', 'ryes', 'ryess', 'ryeng', 'ryej', 'ryec', 'ryek', 'ryet', 'ryep', 'ryeh', 'ro', 'rog', 'rogg', 'rogs', + 0x60 => 'ron', 'ronj', 'ronh', 'rod', 'rol', 'rolg', 'rolm', 'rolb', 'rols', 'rolt', 'rolp', 'rolh', 'rom', 'rob', 'robs', 'ros', + 0x70 => 'ross', 'rong', 'roj', 'roc', 'rok', 'rot', 'rop', 'roh', 'rwa', 'rwag', 'rwagg', 'rwags', 'rwan', 'rwanj', 'rwanh', 'rwad', + 0x80 => 'rwal', 'rwalg', 'rwalm', 'rwalb', 'rwals', 'rwalt', 'rwalp', 'rwalh', 'rwam', 'rwab', 'rwabs', 'rwas', 'rwass', 'rwang', 'rwaj', 'rwac', + 0x90 => 'rwak', 'rwat', 'rwap', 'rwah', 'rwae', 'rwaeg', 'rwaegg', 'rwaegs', 'rwaen', 'rwaenj', 'rwaenh', 'rwaed', 'rwael', 'rwaelg', 'rwaelm', 'rwaelb', + 0xA0 => 'rwaels', 'rwaelt', 'rwaelp', 'rwaelh', 'rwaem', 'rwaeb', 'rwaebs', 'rwaes', 'rwaess', 'rwaeng', 'rwaej', 'rwaec', 'rwaek', 'rwaet', 'rwaep', 'rwaeh', + 0xB0 => 'roe', 'roeg', 'roegg', 'roegs', 'roen', 'roenj', 'roenh', 'roed', 'roel', 'roelg', 'roelm', 'roelb', 'roels', 'roelt', 'roelp', 'roelh', + 0xC0 => 'roem', 'roeb', 'roebs', 'roes', 'roess', 'roeng', 'roej', 'roec', 'roek', 'roet', 'roep', 'roeh', 'ryo', 'ryog', 'ryogg', 'ryogs', + 0xD0 => 'ryon', 'ryonj', 'ryonh', 'ryod', 'ryol', 'ryolg', 'ryolm', 'ryolb', 'ryols', 'ryolt', 'ryolp', 'ryolh', 'ryom', 'ryob', 'ryobs', 'ryos', + 0xE0 => 'ryoss', 'ryong', 'ryoj', 'ryoc', 'ryok', 'ryot', 'ryop', 'ryoh', 'ru', 'rug', 'rugg', 'rugs', 'run', 'runj', 'runh', 'rud', + 0xF0 => 'rul', 'rulg', 'rulm', 'rulb', 'ruls', 'rult', 'rulp', 'rulh', 'rum', 'rub', 'rubs', 'rus', 'russ', 'rung', 'ruj', 'ruc', +]; diff --git a/resources/transliteration-data/xb9.php b/resources/transliteration-data/xb9.php new file mode 100644 index 000000000..2f934eacc --- /dev/null +++ b/resources/transliteration-data/xb9.php @@ -0,0 +1,20 @@ + 'ruk', 'rut', 'rup', 'ruh', 'rweo', 'rweog', 'rweogg', 'rweogs', 'rweon', 'rweonj', 'rweonh', 'rweod', 'rweol', 'rweolg', 'rweolm', 'rweolb', + 0x10 => 'rweols', 'rweolt', 'rweolp', 'rweolh', 'rweom', 'rweob', 'rweobs', 'rweos', 'rweoss', 'rweong', 'rweoj', 'rweoc', 'rweok', 'rweot', 'rweop', 'rweoh', + 0x20 => 'rwe', 'rweg', 'rwegg', 'rwegs', 'rwen', 'rwenj', 'rwenh', 'rwed', 'rwel', 'rwelg', 'rwelm', 'rwelb', 'rwels', 'rwelt', 'rwelp', 'rwelh', + 0x30 => 'rwem', 'rweb', 'rwebs', 'rwes', 'rwess', 'rweng', 'rwej', 'rwec', 'rwek', 'rwet', 'rwep', 'rweh', 'rwi', 'rwig', 'rwigg', 'rwigs', + 0x40 => 'rwin', 'rwinj', 'rwinh', 'rwid', 'rwil', 'rwilg', 'rwilm', 'rwilb', 'rwils', 'rwilt', 'rwilp', 'rwilh', 'rwim', 'rwib', 'rwibs', 'rwis', + 0x50 => 'rwiss', 'rwing', 'rwij', 'rwic', 'rwik', 'rwit', 'rwip', 'rwih', 'ryu', 'ryug', 'ryugg', 'ryugs', 'ryun', 'ryunj', 'ryunh', 'ryud', + 0x60 => 'ryul', 'ryulg', 'ryulm', 'ryulb', 'ryuls', 'ryult', 'ryulp', 'ryulh', 'ryum', 'ryub', 'ryubs', 'ryus', 'ryuss', 'ryung', 'ryuj', 'ryuc', + 0x70 => 'ryuk', 'ryut', 'ryup', 'ryuh', 'reu', 'reug', 'reugg', 'reugs', 'reun', 'reunj', 'reunh', 'reud', 'reul', 'reulg', 'reulm', 'reulb', + 0x80 => 'reuls', 'reult', 'reulp', 'reulh', 'reum', 'reub', 'reubs', 'reus', 'reuss', 'reung', 'reuj', 'reuc', 'reuk', 'reut', 'reup', 'reuh', + 0x90 => 'ryi', 'ryig', 'ryigg', 'ryigs', 'ryin', 'ryinj', 'ryinh', 'ryid', 'ryil', 'ryilg', 'ryilm', 'ryilb', 'ryils', 'ryilt', 'ryilp', 'ryilh', + 0xA0 => 'ryim', 'ryib', 'ryibs', 'ryis', 'ryiss', 'rying', 'ryij', 'ryic', 'ryik', 'ryit', 'ryip', 'ryih', 'ri', 'rig', 'rigg', 'rigs', + 0xB0 => 'rin', 'rinj', 'rinh', 'rid', 'ril', 'rilg', 'rilm', 'rilb', 'rils', 'rilt', 'rilp', 'rilh', 'rim', 'rib', 'ribs', 'ris', + 0xC0 => 'riss', 'ring', 'rij', 'ric', 'rik', 'rit', 'rip', 'rih', 'ma', 'mag', 'magg', 'mags', 'man', 'manj', 'manh', 'mad', + 0xD0 => 'mal', 'malg', 'malm', 'malb', 'mals', 'malt', 'malp', 'malh', 'mam', 'mab', 'mabs', 'mas', 'mass', 'mang', 'maj', 'mac', + 0xE0 => 'mak', 'mat', 'map', 'mah', 'mae', 'maeg', 'maegg', 'maegs', 'maen', 'maenj', 'maenh', 'maed', 'mael', 'maelg', 'maelm', 'maelb', + 0xF0 => 'maels', 'maelt', 'maelp', 'maelh', 'maem', 'maeb', 'maebs', 'maes', 'maess', 'maeng', 'maej', 'maec', 'maek', 'maet', 'maep', 'maeh', +]; diff --git a/resources/transliteration-data/xba.php b/resources/transliteration-data/xba.php new file mode 100644 index 000000000..464eced44 --- /dev/null +++ b/resources/transliteration-data/xba.php @@ -0,0 +1,20 @@ + 'mya', 'myag', 'myagg', 'myags', 'myan', 'myanj', 'myanh', 'myad', 'myal', 'myalg', 'myalm', 'myalb', 'myals', 'myalt', 'myalp', 'myalh', + 0x10 => 'myam', 'myab', 'myabs', 'myas', 'myass', 'myang', 'myaj', 'myac', 'myak', 'myat', 'myap', 'myah', 'myae', 'myaeg', 'myaegg', 'myaegs', + 0x20 => 'myaen', 'myaenj', 'myaenh', 'myaed', 'myael', 'myaelg', 'myaelm', 'myaelb', 'myaels', 'myaelt', 'myaelp', 'myaelh', 'myaem', 'myaeb', 'myaebs', 'myaes', + 0x30 => 'myaess', 'myaeng', 'myaej', 'myaec', 'myaek', 'myaet', 'myaep', 'myaeh', 'meo', 'meog', 'meogg', 'meogs', 'meon', 'meonj', 'meonh', 'meod', + 0x40 => 'meol', 'meolg', 'meolm', 'meolb', 'meols', 'meolt', 'meolp', 'meolh', 'meom', 'meob', 'meobs', 'meos', 'meoss', 'meong', 'meoj', 'meoc', + 0x50 => 'meok', 'meot', 'meop', 'meoh', 'me', 'meg', 'megg', 'megs', 'men', 'menj', 'menh', 'med', 'mel', 'melg', 'melm', 'melb', + 0x60 => 'mels', 'melt', 'melp', 'melh', 'mem', 'meb', 'mebs', 'mes', 'mess', 'meng', 'mej', 'mec', 'mek', 'met', 'mep', 'meh', + 0x70 => 'myeo', 'myeog', 'myeogg', 'myeogs', 'myeon', 'myeonj', 'myeonh', 'myeod', 'myeol', 'myeolg', 'myeolm', 'myeolb', 'myeols', 'myeolt', 'myeolp', 'myeolh', + 0x80 => 'myeom', 'myeob', 'myeobs', 'myeos', 'myeoss', 'myeong', 'myeoj', 'myeoc', 'myeok', 'myeot', 'myeop', 'myeoh', 'mye', 'myeg', 'myegg', 'myegs', + 0x90 => 'myen', 'myenj', 'myenh', 'myed', 'myel', 'myelg', 'myelm', 'myelb', 'myels', 'myelt', 'myelp', 'myelh', 'myem', 'myeb', 'myebs', 'myes', + 0xA0 => 'myess', 'myeng', 'myej', 'myec', 'myek', 'myet', 'myep', 'myeh', 'mo', 'mog', 'mogg', 'mogs', 'mon', 'monj', 'monh', 'mod', + 0xB0 => 'mol', 'molg', 'molm', 'molb', 'mols', 'molt', 'molp', 'molh', 'mom', 'mob', 'mobs', 'mos', 'moss', 'mong', 'moj', 'moc', + 0xC0 => 'mok', 'mot', 'mop', 'moh', 'mwa', 'mwag', 'mwagg', 'mwags', 'mwan', 'mwanj', 'mwanh', 'mwad', 'mwal', 'mwalg', 'mwalm', 'mwalb', + 0xD0 => 'mwals', 'mwalt', 'mwalp', 'mwalh', 'mwam', 'mwab', 'mwabs', 'mwas', 'mwass', 'mwang', 'mwaj', 'mwac', 'mwak', 'mwat', 'mwap', 'mwah', + 0xE0 => 'mwae', 'mwaeg', 'mwaegg', 'mwaegs', 'mwaen', 'mwaenj', 'mwaenh', 'mwaed', 'mwael', 'mwaelg', 'mwaelm', 'mwaelb', 'mwaels', 'mwaelt', 'mwaelp', 'mwaelh', + 0xF0 => 'mwaem', 'mwaeb', 'mwaebs', 'mwaes', 'mwaess', 'mwaeng', 'mwaej', 'mwaec', 'mwaek', 'mwaet', 'mwaep', 'mwaeh', 'moe', 'moeg', 'moegg', 'moegs', +]; diff --git a/resources/transliteration-data/xbb.php b/resources/transliteration-data/xbb.php new file mode 100644 index 000000000..7a6991ab3 --- /dev/null +++ b/resources/transliteration-data/xbb.php @@ -0,0 +1,20 @@ + 'moen', 'moenj', 'moenh', 'moed', 'moel', 'moelg', 'moelm', 'moelb', 'moels', 'moelt', 'moelp', 'moelh', 'moem', 'moeb', 'moebs', 'moes', + 0x10 => 'moess', 'moeng', 'moej', 'moec', 'moek', 'moet', 'moep', 'moeh', 'myo', 'myog', 'myogg', 'myogs', 'myon', 'myonj', 'myonh', 'myod', + 0x20 => 'myol', 'myolg', 'myolm', 'myolb', 'myols', 'myolt', 'myolp', 'myolh', 'myom', 'myob', 'myobs', 'myos', 'myoss', 'myong', 'myoj', 'myoc', + 0x30 => 'myok', 'myot', 'myop', 'myoh', 'mu', 'mug', 'mugg', 'mugs', 'mun', 'munj', 'munh', 'mud', 'mul', 'mulg', 'mulm', 'mulb', + 0x40 => 'muls', 'mult', 'mulp', 'mulh', 'mum', 'mub', 'mubs', 'mus', 'muss', 'mung', 'muj', 'muc', 'muk', 'mut', 'mup', 'muh', + 0x50 => 'mweo', 'mweog', 'mweogg', 'mweogs', 'mweon', 'mweonj', 'mweonh', 'mweod', 'mweol', 'mweolg', 'mweolm', 'mweolb', 'mweols', 'mweolt', 'mweolp', 'mweolh', + 0x60 => 'mweom', 'mweob', 'mweobs', 'mweos', 'mweoss', 'mweong', 'mweoj', 'mweoc', 'mweok', 'mweot', 'mweop', 'mweoh', 'mwe', 'mweg', 'mwegg', 'mwegs', + 0x70 => 'mwen', 'mwenj', 'mwenh', 'mwed', 'mwel', 'mwelg', 'mwelm', 'mwelb', 'mwels', 'mwelt', 'mwelp', 'mwelh', 'mwem', 'mweb', 'mwebs', 'mwes', + 0x80 => 'mwess', 'mweng', 'mwej', 'mwec', 'mwek', 'mwet', 'mwep', 'mweh', 'mwi', 'mwig', 'mwigg', 'mwigs', 'mwin', 'mwinj', 'mwinh', 'mwid', + 0x90 => 'mwil', 'mwilg', 'mwilm', 'mwilb', 'mwils', 'mwilt', 'mwilp', 'mwilh', 'mwim', 'mwib', 'mwibs', 'mwis', 'mwiss', 'mwing', 'mwij', 'mwic', + 0xA0 => 'mwik', 'mwit', 'mwip', 'mwih', 'myu', 'myug', 'myugg', 'myugs', 'myun', 'myunj', 'myunh', 'myud', 'myul', 'myulg', 'myulm', 'myulb', + 0xB0 => 'myuls', 'myult', 'myulp', 'myulh', 'myum', 'myub', 'myubs', 'myus', 'myuss', 'myung', 'myuj', 'myuc', 'myuk', 'myut', 'myup', 'myuh', + 0xC0 => 'meu', 'meug', 'meugg', 'meugs', 'meun', 'meunj', 'meunh', 'meud', 'meul', 'meulg', 'meulm', 'meulb', 'meuls', 'meult', 'meulp', 'meulh', + 0xD0 => 'meum', 'meub', 'meubs', 'meus', 'meuss', 'meung', 'meuj', 'meuc', 'meuk', 'meut', 'meup', 'meuh', 'myi', 'myig', 'myigg', 'myigs', + 0xE0 => 'myin', 'myinj', 'myinh', 'myid', 'myil', 'myilg', 'myilm', 'myilb', 'myils', 'myilt', 'myilp', 'myilh', 'myim', 'myib', 'myibs', 'myis', + 0xF0 => 'myiss', 'mying', 'myij', 'myic', 'myik', 'myit', 'myip', 'myih', 'mi', 'mig', 'migg', 'migs', 'min', 'minj', 'minh', 'mid', +]; diff --git a/resources/transliteration-data/xbc.php b/resources/transliteration-data/xbc.php new file mode 100644 index 000000000..19e6c5adf --- /dev/null +++ b/resources/transliteration-data/xbc.php @@ -0,0 +1,20 @@ + 'mil', 'milg', 'milm', 'milb', 'mils', 'milt', 'milp', 'milh', 'mim', 'mib', 'mibs', 'mis', 'miss', 'ming', 'mij', 'mic', + 0x10 => 'mik', 'mit', 'mip', 'mih', 'ba', 'bag', 'bagg', 'bags', 'ban', 'banj', 'banh', 'bad', 'bal', 'balg', 'balm', 'balb', + 0x20 => 'bals', 'balt', 'balp', 'balh', 'bam', 'bab', 'babs', 'bas', 'bass', 'bang', 'baj', 'bac', 'bak', 'bat', 'bap', 'bah', + 0x30 => 'bae', 'baeg', 'baegg', 'baegs', 'baen', 'baenj', 'baenh', 'baed', 'bael', 'baelg', 'baelm', 'baelb', 'baels', 'baelt', 'baelp', 'baelh', + 0x40 => 'baem', 'baeb', 'baebs', 'baes', 'baess', 'baeng', 'baej', 'baec', 'baek', 'baet', 'baep', 'baeh', 'bya', 'byag', 'byagg', 'byags', + 0x50 => 'byan', 'byanj', 'byanh', 'byad', 'byal', 'byalg', 'byalm', 'byalb', 'byals', 'byalt', 'byalp', 'byalh', 'byam', 'byab', 'byabs', 'byas', + 0x60 => 'byass', 'byang', 'byaj', 'byac', 'byak', 'byat', 'byap', 'byah', 'byae', 'byaeg', 'byaegg', 'byaegs', 'byaen', 'byaenj', 'byaenh', 'byaed', + 0x70 => 'byael', 'byaelg', 'byaelm', 'byaelb', 'byaels', 'byaelt', 'byaelp', 'byaelh', 'byaem', 'byaeb', 'byaebs', 'byaes', 'byaess', 'byaeng', 'byaej', 'byaec', + 0x80 => 'byaek', 'byaet', 'byaep', 'byaeh', 'beo', 'beog', 'beogg', 'beogs', 'beon', 'beonj', 'beonh', 'beod', 'beol', 'beolg', 'beolm', 'beolb', + 0x90 => 'beols', 'beolt', 'beolp', 'beolh', 'beom', 'beob', 'beobs', 'beos', 'beoss', 'beong', 'beoj', 'beoc', 'beok', 'beot', 'beop', 'beoh', + 0xA0 => 'be', 'beg', 'begg', 'begs', 'ben', 'benj', 'benh', 'bed', 'bel', 'belg', 'belm', 'belb', 'bels', 'belt', 'belp', 'belh', + 0xB0 => 'bem', 'beb', 'bebs', 'bes', 'bess', 'beng', 'bej', 'bec', 'bek', 'bet', 'bep', 'beh', 'byeo', 'byeog', 'byeogg', 'byeogs', + 0xC0 => 'byeon', 'byeonj', 'byeonh', 'byeod', 'byeol', 'byeolg', 'byeolm', 'byeolb', 'byeols', 'byeolt', 'byeolp', 'byeolh', 'byeom', 'byeob', 'byeobs', 'byeos', + 0xD0 => 'byeoss', 'byeong', 'byeoj', 'byeoc', 'byeok', 'byeot', 'byeop', 'byeoh', 'bye', 'byeg', 'byegg', 'byegs', 'byen', 'byenj', 'byenh', 'byed', + 0xE0 => 'byel', 'byelg', 'byelm', 'byelb', 'byels', 'byelt', 'byelp', 'byelh', 'byem', 'byeb', 'byebs', 'byes', 'byess', 'byeng', 'byej', 'byec', + 0xF0 => 'byek', 'byet', 'byep', 'byeh', 'bo', 'bog', 'bogg', 'bogs', 'bon', 'bonj', 'bonh', 'bod', 'bol', 'bolg', 'bolm', 'bolb', +]; diff --git a/resources/transliteration-data/xbd.php b/resources/transliteration-data/xbd.php new file mode 100644 index 000000000..a492a109b --- /dev/null +++ b/resources/transliteration-data/xbd.php @@ -0,0 +1,20 @@ + 'bols', 'bolt', 'bolp', 'bolh', 'bom', 'bob', 'bobs', 'bos', 'boss', 'bong', 'boj', 'boc', 'bok', 'bot', 'bop', 'boh', + 0x10 => 'bwa', 'bwag', 'bwagg', 'bwags', 'bwan', 'bwanj', 'bwanh', 'bwad', 'bwal', 'bwalg', 'bwalm', 'bwalb', 'bwals', 'bwalt', 'bwalp', 'bwalh', + 0x20 => 'bwam', 'bwab', 'bwabs', 'bwas', 'bwass', 'bwang', 'bwaj', 'bwac', 'bwak', 'bwat', 'bwap', 'bwah', 'bwae', 'bwaeg', 'bwaegg', 'bwaegs', + 0x30 => 'bwaen', 'bwaenj', 'bwaenh', 'bwaed', 'bwael', 'bwaelg', 'bwaelm', 'bwaelb', 'bwaels', 'bwaelt', 'bwaelp', 'bwaelh', 'bwaem', 'bwaeb', 'bwaebs', 'bwaes', + 0x40 => 'bwaess', 'bwaeng', 'bwaej', 'bwaec', 'bwaek', 'bwaet', 'bwaep', 'bwaeh', 'boe', 'boeg', 'boegg', 'boegs', 'boen', 'boenj', 'boenh', 'boed', + 0x50 => 'boel', 'boelg', 'boelm', 'boelb', 'boels', 'boelt', 'boelp', 'boelh', 'boem', 'boeb', 'boebs', 'boes', 'boess', 'boeng', 'boej', 'boec', + 0x60 => 'boek', 'boet', 'boep', 'boeh', 'byo', 'byog', 'byogg', 'byogs', 'byon', 'byonj', 'byonh', 'byod', 'byol', 'byolg', 'byolm', 'byolb', + 0x70 => 'byols', 'byolt', 'byolp', 'byolh', 'byom', 'byob', 'byobs', 'byos', 'byoss', 'byong', 'byoj', 'byoc', 'byok', 'byot', 'byop', 'byoh', + 0x80 => 'bu', 'bug', 'bugg', 'bugs', 'bun', 'bunj', 'bunh', 'bud', 'bul', 'bulg', 'bulm', 'bulb', 'buls', 'bult', 'bulp', 'bulh', + 0x90 => 'bum', 'bub', 'bubs', 'bus', 'buss', 'bung', 'buj', 'buc', 'buk', 'but', 'bup', 'buh', 'bweo', 'bweog', 'bweogg', 'bweogs', + 0xA0 => 'bweon', 'bweonj', 'bweonh', 'bweod', 'bweol', 'bweolg', 'bweolm', 'bweolb', 'bweols', 'bweolt', 'bweolp', 'bweolh', 'bweom', 'bweob', 'bweobs', 'bweos', + 0xB0 => 'bweoss', 'bweong', 'bweoj', 'bweoc', 'bweok', 'bweot', 'bweop', 'bweoh', 'bwe', 'bweg', 'bwegg', 'bwegs', 'bwen', 'bwenj', 'bwenh', 'bwed', + 0xC0 => 'bwel', 'bwelg', 'bwelm', 'bwelb', 'bwels', 'bwelt', 'bwelp', 'bwelh', 'bwem', 'bweb', 'bwebs', 'bwes', 'bwess', 'bweng', 'bwej', 'bwec', + 0xD0 => 'bwek', 'bwet', 'bwep', 'bweh', 'bwi', 'bwig', 'bwigg', 'bwigs', 'bwin', 'bwinj', 'bwinh', 'bwid', 'bwil', 'bwilg', 'bwilm', 'bwilb', + 0xE0 => 'bwils', 'bwilt', 'bwilp', 'bwilh', 'bwim', 'bwib', 'bwibs', 'bwis', 'bwiss', 'bwing', 'bwij', 'bwic', 'bwik', 'bwit', 'bwip', 'bwih', + 0xF0 => 'byu', 'byug', 'byugg', 'byugs', 'byun', 'byunj', 'byunh', 'byud', 'byul', 'byulg', 'byulm', 'byulb', 'byuls', 'byult', 'byulp', 'byulh', +]; diff --git a/resources/transliteration-data/xbe.php b/resources/transliteration-data/xbe.php new file mode 100644 index 000000000..e87a2e406 --- /dev/null +++ b/resources/transliteration-data/xbe.php @@ -0,0 +1,20 @@ + 'byum', 'byub', 'byubs', 'byus', 'byuss', 'byung', 'byuj', 'byuc', 'byuk', 'byut', 'byup', 'byuh', 'beu', 'beug', 'beugg', 'beugs', + 0x10 => 'beun', 'beunj', 'beunh', 'beud', 'beul', 'beulg', 'beulm', 'beulb', 'beuls', 'beult', 'beulp', 'beulh', 'beum', 'beub', 'beubs', 'beus', + 0x20 => 'beuss', 'beung', 'beuj', 'beuc', 'beuk', 'beut', 'beup', 'beuh', 'byi', 'byig', 'byigg', 'byigs', 'byin', 'byinj', 'byinh', 'byid', + 0x30 => 'byil', 'byilg', 'byilm', 'byilb', 'byils', 'byilt', 'byilp', 'byilh', 'byim', 'byib', 'byibs', 'byis', 'byiss', 'bying', 'byij', 'byic', + 0x40 => 'byik', 'byit', 'byip', 'byih', 'bi', 'big', 'bigg', 'bigs', 'bin', 'binj', 'binh', 'bid', 'bil', 'bilg', 'bilm', 'bilb', + 0x50 => 'bils', 'bilt', 'bilp', 'bilh', 'bim', 'bib', 'bibs', 'bis', 'biss', 'bing', 'bij', 'bic', 'bik', 'bit', 'bip', 'bih', + 0x60 => 'bba', 'bbag', 'bbagg', 'bbags', 'bban', 'bbanj', 'bbanh', 'bbad', 'bbal', 'bbalg', 'bbalm', 'bbalb', 'bbals', 'bbalt', 'bbalp', 'bbalh', + 0x70 => 'bbam', 'bbab', 'bbabs', 'bbas', 'bbass', 'bbang', 'bbaj', 'bbac', 'bbak', 'bbat', 'bbap', 'bbah', 'bbae', 'bbaeg', 'bbaegg', 'bbaegs', + 0x80 => 'bbaen', 'bbaenj', 'bbaenh', 'bbaed', 'bbael', 'bbaelg', 'bbaelm', 'bbaelb', 'bbaels', 'bbaelt', 'bbaelp', 'bbaelh', 'bbaem', 'bbaeb', 'bbaebs', 'bbaes', + 0x90 => 'bbaess', 'bbaeng', 'bbaej', 'bbaec', 'bbaek', 'bbaet', 'bbaep', 'bbaeh', 'bbya', 'bbyag', 'bbyagg', 'bbyags', 'bbyan', 'bbyanj', 'bbyanh', 'bbyad', + 0xA0 => 'bbyal', 'bbyalg', 'bbyalm', 'bbyalb', 'bbyals', 'bbyalt', 'bbyalp', 'bbyalh', 'bbyam', 'bbyab', 'bbyabs', 'bbyas', 'bbyass', 'bbyang', 'bbyaj', 'bbyac', + 0xB0 => 'bbyak', 'bbyat', 'bbyap', 'bbyah', 'bbyae', 'bbyaeg', 'bbyaegg', 'bbyaegs', 'bbyaen', 'bbyaenj', 'bbyaenh', 'bbyaed', 'bbyael', 'bbyaelg', 'bbyaelm', 'bbyaelb', + 0xC0 => 'bbyaels', 'bbyaelt', 'bbyaelp', 'bbyaelh', 'bbyaem', 'bbyaeb', 'bbyaebs', 'bbyaes', 'bbyaess', 'bbyaeng', 'bbyaej', 'bbyaec', 'bbyaek', 'bbyaet', 'bbyaep', 'bbyaeh', + 0xD0 => 'bbeo', 'bbeog', 'bbeogg', 'bbeogs', 'bbeon', 'bbeonj', 'bbeonh', 'bbeod', 'bbeol', 'bbeolg', 'bbeolm', 'bbeolb', 'bbeols', 'bbeolt', 'bbeolp', 'bbeolh', + 0xE0 => 'bbeom', 'bbeob', 'bbeobs', 'bbeos', 'bbeoss', 'bbeong', 'bbeoj', 'bbeoc', 'bbeok', 'bbeot', 'bbeop', 'bbeoh', 'bbe', 'bbeg', 'bbegg', 'bbegs', + 0xF0 => 'bben', 'bbenj', 'bbenh', 'bbed', 'bbel', 'bbelg', 'bbelm', 'bbelb', 'bbels', 'bbelt', 'bbelp', 'bbelh', 'bbem', 'bbeb', 'bbebs', 'bbes', +]; diff --git a/resources/transliteration-data/xbf.php b/resources/transliteration-data/xbf.php new file mode 100644 index 000000000..56bc3ad3b --- /dev/null +++ b/resources/transliteration-data/xbf.php @@ -0,0 +1,20 @@ + 'bbess', 'bbeng', 'bbej', 'bbec', 'bbek', 'bbet', 'bbep', 'bbeh', 'bbyeo', 'bbyeog', 'bbyeogg', 'bbyeogs', 'bbyeon', 'bbyeonj', 'bbyeonh', 'bbyeod', + 0x10 => 'bbyeol', 'bbyeolg', 'bbyeolm', 'bbyeolb', 'bbyeols', 'bbyeolt', 'bbyeolp', 'bbyeolh', 'bbyeom', 'bbyeob', 'bbyeobs', 'bbyeos', 'bbyeoss', 'bbyeong', 'bbyeoj', 'bbyeoc', + 0x20 => 'bbyeok', 'bbyeot', 'bbyeop', 'bbyeoh', 'bbye', 'bbyeg', 'bbyegg', 'bbyegs', 'bbyen', 'bbyenj', 'bbyenh', 'bbyed', 'bbyel', 'bbyelg', 'bbyelm', 'bbyelb', + 0x30 => 'bbyels', 'bbyelt', 'bbyelp', 'bbyelh', 'bbyem', 'bbyeb', 'bbyebs', 'bbyes', 'bbyess', 'bbyeng', 'bbyej', 'bbyec', 'bbyek', 'bbyet', 'bbyep', 'bbyeh', + 0x40 => 'bbo', 'bbog', 'bbogg', 'bbogs', 'bbon', 'bbonj', 'bbonh', 'bbod', 'bbol', 'bbolg', 'bbolm', 'bbolb', 'bbols', 'bbolt', 'bbolp', 'bbolh', + 0x50 => 'bbom', 'bbob', 'bbobs', 'bbos', 'bboss', 'bbong', 'bboj', 'bboc', 'bbok', 'bbot', 'bbop', 'bboh', 'bbwa', 'bbwag', 'bbwagg', 'bbwags', + 0x60 => 'bbwan', 'bbwanj', 'bbwanh', 'bbwad', 'bbwal', 'bbwalg', 'bbwalm', 'bbwalb', 'bbwals', 'bbwalt', 'bbwalp', 'bbwalh', 'bbwam', 'bbwab', 'bbwabs', 'bbwas', + 0x70 => 'bbwass', 'bbwang', 'bbwaj', 'bbwac', 'bbwak', 'bbwat', 'bbwap', 'bbwah', 'bbwae', 'bbwaeg', 'bbwaegg', 'bbwaegs', 'bbwaen', 'bbwaenj', 'bbwaenh', 'bbwaed', + 0x80 => 'bbwael', 'bbwaelg', 'bbwaelm', 'bbwaelb', 'bbwaels', 'bbwaelt', 'bbwaelp', 'bbwaelh', 'bbwaem', 'bbwaeb', 'bbwaebs', 'bbwaes', 'bbwaess', 'bbwaeng', 'bbwaej', 'bbwaec', + 0x90 => 'bbwaek', 'bbwaet', 'bbwaep', 'bbwaeh', 'bboe', 'bboeg', 'bboegg', 'bboegs', 'bboen', 'bboenj', 'bboenh', 'bboed', 'bboel', 'bboelg', 'bboelm', 'bboelb', + 0xA0 => 'bboels', 'bboelt', 'bboelp', 'bboelh', 'bboem', 'bboeb', 'bboebs', 'bboes', 'bboess', 'bboeng', 'bboej', 'bboec', 'bboek', 'bboet', 'bboep', 'bboeh', + 0xB0 => 'bbyo', 'bbyog', 'bbyogg', 'bbyogs', 'bbyon', 'bbyonj', 'bbyonh', 'bbyod', 'bbyol', 'bbyolg', 'bbyolm', 'bbyolb', 'bbyols', 'bbyolt', 'bbyolp', 'bbyolh', + 0xC0 => 'bbyom', 'bbyob', 'bbyobs', 'bbyos', 'bbyoss', 'bbyong', 'bbyoj', 'bbyoc', 'bbyok', 'bbyot', 'bbyop', 'bbyoh', 'bbu', 'bbug', 'bbugg', 'bbugs', + 0xD0 => 'bbun', 'bbunj', 'bbunh', 'bbud', 'bbul', 'bbulg', 'bbulm', 'bbulb', 'bbuls', 'bbult', 'bbulp', 'bbulh', 'bbum', 'bbub', 'bbubs', 'bbus', + 0xE0 => 'bbuss', 'bbung', 'bbuj', 'bbuc', 'bbuk', 'bbut', 'bbup', 'bbuh', 'bbweo', 'bbweog', 'bbweogg', 'bbweogs', 'bbweon', 'bbweonj', 'bbweonh', 'bbweod', + 0xF0 => 'bbweol', 'bbweolg', 'bbweolm', 'bbweolb', 'bbweols', 'bbweolt', 'bbweolp', 'bbweolh', 'bbweom', 'bbweob', 'bbweobs', 'bbweos', 'bbweoss', 'bbweong', 'bbweoj', 'bbweoc', +]; diff --git a/resources/transliteration-data/xc0.php b/resources/transliteration-data/xc0.php new file mode 100644 index 000000000..3cccd3c36 --- /dev/null +++ b/resources/transliteration-data/xc0.php @@ -0,0 +1,20 @@ + 'bbweok', 'bbweot', 'bbweop', 'bbweoh', 'bbwe', 'bbweg', 'bbwegg', 'bbwegs', 'bbwen', 'bbwenj', 'bbwenh', 'bbwed', 'bbwel', 'bbwelg', 'bbwelm', 'bbwelb', + 0x10 => 'bbwels', 'bbwelt', 'bbwelp', 'bbwelh', 'bbwem', 'bbweb', 'bbwebs', 'bbwes', 'bbwess', 'bbweng', 'bbwej', 'bbwec', 'bbwek', 'bbwet', 'bbwep', 'bbweh', + 0x20 => 'bbwi', 'bbwig', 'bbwigg', 'bbwigs', 'bbwin', 'bbwinj', 'bbwinh', 'bbwid', 'bbwil', 'bbwilg', 'bbwilm', 'bbwilb', 'bbwils', 'bbwilt', 'bbwilp', 'bbwilh', + 0x30 => 'bbwim', 'bbwib', 'bbwibs', 'bbwis', 'bbwiss', 'bbwing', 'bbwij', 'bbwic', 'bbwik', 'bbwit', 'bbwip', 'bbwih', 'bbyu', 'bbyug', 'bbyugg', 'bbyugs', + 0x40 => 'bbyun', 'bbyunj', 'bbyunh', 'bbyud', 'bbyul', 'bbyulg', 'bbyulm', 'bbyulb', 'bbyuls', 'bbyult', 'bbyulp', 'bbyulh', 'bbyum', 'bbyub', 'bbyubs', 'bbyus', + 0x50 => 'bbyuss', 'bbyung', 'bbyuj', 'bbyuc', 'bbyuk', 'bbyut', 'bbyup', 'bbyuh', 'bbeu', 'bbeug', 'bbeugg', 'bbeugs', 'bbeun', 'bbeunj', 'bbeunh', 'bbeud', + 0x60 => 'bbeul', 'bbeulg', 'bbeulm', 'bbeulb', 'bbeuls', 'bbeult', 'bbeulp', 'bbeulh', 'bbeum', 'bbeub', 'bbeubs', 'bbeus', 'bbeuss', 'bbeung', 'bbeuj', 'bbeuc', + 0x70 => 'bbeuk', 'bbeut', 'bbeup', 'bbeuh', 'bbyi', 'bbyig', 'bbyigg', 'bbyigs', 'bbyin', 'bbyinj', 'bbyinh', 'bbyid', 'bbyil', 'bbyilg', 'bbyilm', 'bbyilb', + 0x80 => 'bbyils', 'bbyilt', 'bbyilp', 'bbyilh', 'bbyim', 'bbyib', 'bbyibs', 'bbyis', 'bbyiss', 'bbying', 'bbyij', 'bbyic', 'bbyik', 'bbyit', 'bbyip', 'bbyih', + 0x90 => 'bbi', 'bbig', 'bbigg', 'bbigs', 'bbin', 'bbinj', 'bbinh', 'bbid', 'bbil', 'bbilg', 'bbilm', 'bbilb', 'bbils', 'bbilt', 'bbilp', 'bbilh', + 0xA0 => 'bbim', 'bbib', 'bbibs', 'bbis', 'bbiss', 'bbing', 'bbij', 'bbic', 'bbik', 'bbit', 'bbip', 'bbih', 'sa', 'sag', 'sagg', 'sags', + 0xB0 => 'san', 'sanj', 'sanh', 'sad', 'sal', 'salg', 'salm', 'salb', 'sals', 'salt', 'salp', 'salh', 'sam', 'sab', 'sabs', 'sas', + 0xC0 => 'sass', 'sang', 'saj', 'sac', 'sak', 'sat', 'sap', 'sah', 'sae', 'saeg', 'saegg', 'saegs', 'saen', 'saenj', 'saenh', 'saed', + 0xD0 => 'sael', 'saelg', 'saelm', 'saelb', 'saels', 'saelt', 'saelp', 'saelh', 'saem', 'saeb', 'saebs', 'saes', 'saess', 'saeng', 'saej', 'saec', + 0xE0 => 'saek', 'saet', 'saep', 'saeh', 'sya', 'syag', 'syagg', 'syags', 'syan', 'syanj', 'syanh', 'syad', 'syal', 'syalg', 'syalm', 'syalb', + 0xF0 => 'syals', 'syalt', 'syalp', 'syalh', 'syam', 'syab', 'syabs', 'syas', 'syass', 'syang', 'syaj', 'syac', 'syak', 'syat', 'syap', 'syah', +]; diff --git a/resources/transliteration-data/xc1.php b/resources/transliteration-data/xc1.php new file mode 100644 index 000000000..952d2afa2 --- /dev/null +++ b/resources/transliteration-data/xc1.php @@ -0,0 +1,20 @@ + 'syae', 'syaeg', 'syaegg', 'syaegs', 'syaen', 'syaenj', 'syaenh', 'syaed', 'syael', 'syaelg', 'syaelm', 'syaelb', 'syaels', 'syaelt', 'syaelp', 'syaelh', + 0x10 => 'syaem', 'syaeb', 'syaebs', 'syaes', 'syaess', 'syaeng', 'syaej', 'syaec', 'syaek', 'syaet', 'syaep', 'syaeh', 'seo', 'seog', 'seogg', 'seogs', + 0x20 => 'seon', 'seonj', 'seonh', 'seod', 'seol', 'seolg', 'seolm', 'seolb', 'seols', 'seolt', 'seolp', 'seolh', 'seom', 'seob', 'seobs', 'seos', + 0x30 => 'seoss', 'seong', 'seoj', 'seoc', 'seok', 'seot', 'seop', 'seoh', 'se', 'seg', 'segg', 'segs', 'sen', 'senj', 'senh', 'sed', + 0x40 => 'sel', 'selg', 'selm', 'selb', 'sels', 'selt', 'selp', 'selh', 'sem', 'seb', 'sebs', 'ses', 'sess', 'seng', 'sej', 'sec', + 0x50 => 'sek', 'set', 'sep', 'seh', 'syeo', 'syeog', 'syeogg', 'syeogs', 'syeon', 'syeonj', 'syeonh', 'syeod', 'syeol', 'syeolg', 'syeolm', 'syeolb', + 0x60 => 'syeols', 'syeolt', 'syeolp', 'syeolh', 'syeom', 'syeob', 'syeobs', 'syeos', 'syeoss', 'syeong', 'syeoj', 'syeoc', 'syeok', 'syeot', 'syeop', 'syeoh', + 0x70 => 'sye', 'syeg', 'syegg', 'syegs', 'syen', 'syenj', 'syenh', 'syed', 'syel', 'syelg', 'syelm', 'syelb', 'syels', 'syelt', 'syelp', 'syelh', + 0x80 => 'syem', 'syeb', 'syebs', 'syes', 'syess', 'syeng', 'syej', 'syec', 'syek', 'syet', 'syep', 'syeh', 'so', 'sog', 'sogg', 'sogs', + 0x90 => 'son', 'sonj', 'sonh', 'sod', 'sol', 'solg', 'solm', 'solb', 'sols', 'solt', 'solp', 'solh', 'som', 'sob', 'sobs', 'sos', + 0xA0 => 'soss', 'song', 'soj', 'soc', 'sok', 'sot', 'sop', 'soh', 'swa', 'swag', 'swagg', 'swags', 'swan', 'swanj', 'swanh', 'swad', + 0xB0 => 'swal', 'swalg', 'swalm', 'swalb', 'swals', 'swalt', 'swalp', 'swalh', 'swam', 'swab', 'swabs', 'swas', 'swass', 'swang', 'swaj', 'swac', + 0xC0 => 'swak', 'swat', 'swap', 'swah', 'swae', 'swaeg', 'swaegg', 'swaegs', 'swaen', 'swaenj', 'swaenh', 'swaed', 'swael', 'swaelg', 'swaelm', 'swaelb', + 0xD0 => 'swaels', 'swaelt', 'swaelp', 'swaelh', 'swaem', 'swaeb', 'swaebs', 'swaes', 'swaess', 'swaeng', 'swaej', 'swaec', 'swaek', 'swaet', 'swaep', 'swaeh', + 0xE0 => 'soe', 'soeg', 'soegg', 'soegs', 'soen', 'soenj', 'soenh', 'soed', 'soel', 'soelg', 'soelm', 'soelb', 'soels', 'soelt', 'soelp', 'soelh', + 0xF0 => 'soem', 'soeb', 'soebs', 'soes', 'soess', 'soeng', 'soej', 'soec', 'soek', 'soet', 'soep', 'soeh', 'syo', 'syog', 'syogg', 'syogs', +]; diff --git a/resources/transliteration-data/xc2.php b/resources/transliteration-data/xc2.php new file mode 100644 index 000000000..4a748916a --- /dev/null +++ b/resources/transliteration-data/xc2.php @@ -0,0 +1,20 @@ + 'syon', 'syonj', 'syonh', 'syod', 'syol', 'syolg', 'syolm', 'syolb', 'syols', 'syolt', 'syolp', 'syolh', 'syom', 'syob', 'syobs', 'syos', + 0x10 => 'syoss', 'syong', 'syoj', 'syoc', 'syok', 'syot', 'syop', 'syoh', 'su', 'sug', 'sugg', 'sugs', 'sun', 'sunj', 'sunh', 'sud', + 0x20 => 'sul', 'sulg', 'sulm', 'sulb', 'suls', 'sult', 'sulp', 'sulh', 'sum', 'sub', 'subs', 'sus', 'suss', 'sung', 'suj', 'suc', + 0x30 => 'suk', 'sut', 'sup', 'suh', 'sweo', 'sweog', 'sweogg', 'sweogs', 'sweon', 'sweonj', 'sweonh', 'sweod', 'sweol', 'sweolg', 'sweolm', 'sweolb', + 0x40 => 'sweols', 'sweolt', 'sweolp', 'sweolh', 'sweom', 'sweob', 'sweobs', 'sweos', 'sweoss', 'sweong', 'sweoj', 'sweoc', 'sweok', 'sweot', 'sweop', 'sweoh', + 0x50 => 'swe', 'sweg', 'swegg', 'swegs', 'swen', 'swenj', 'swenh', 'swed', 'swel', 'swelg', 'swelm', 'swelb', 'swels', 'swelt', 'swelp', 'swelh', + 0x60 => 'swem', 'sweb', 'swebs', 'swes', 'swess', 'sweng', 'swej', 'swec', 'swek', 'swet', 'swep', 'sweh', 'swi', 'swig', 'swigg', 'swigs', + 0x70 => 'swin', 'swinj', 'swinh', 'swid', 'swil', 'swilg', 'swilm', 'swilb', 'swils', 'swilt', 'swilp', 'swilh', 'swim', 'swib', 'swibs', 'swis', + 0x80 => 'swiss', 'swing', 'swij', 'swic', 'swik', 'swit', 'swip', 'swih', 'syu', 'syug', 'syugg', 'syugs', 'syun', 'syunj', 'syunh', 'syud', + 0x90 => 'syul', 'syulg', 'syulm', 'syulb', 'syuls', 'syult', 'syulp', 'syulh', 'syum', 'syub', 'syubs', 'syus', 'syuss', 'syung', 'syuj', 'syuc', + 0xA0 => 'syuk', 'syut', 'syup', 'syuh', 'seu', 'seug', 'seugg', 'seugs', 'seun', 'seunj', 'seunh', 'seud', 'seul', 'seulg', 'seulm', 'seulb', + 0xB0 => 'seuls', 'seult', 'seulp', 'seulh', 'seum', 'seub', 'seubs', 'seus', 'seuss', 'seung', 'seuj', 'seuc', 'seuk', 'seut', 'seup', 'seuh', + 0xC0 => 'syi', 'syig', 'syigg', 'syigs', 'syin', 'syinj', 'syinh', 'syid', 'syil', 'syilg', 'syilm', 'syilb', 'syils', 'syilt', 'syilp', 'syilh', + 0xD0 => 'syim', 'syib', 'syibs', 'syis', 'syiss', 'sying', 'syij', 'syic', 'syik', 'syit', 'syip', 'syih', 'si', 'sig', 'sigg', 'sigs', + 0xE0 => 'sin', 'sinj', 'sinh', 'sid', 'sil', 'silg', 'silm', 'silb', 'sils', 'silt', 'silp', 'silh', 'sim', 'sib', 'sibs', 'sis', + 0xF0 => 'siss', 'sing', 'sij', 'sic', 'sik', 'sit', 'sip', 'sih', 'ssa', 'ssag', 'ssagg', 'ssags', 'ssan', 'ssanj', 'ssanh', 'ssad', +]; diff --git a/resources/transliteration-data/xc3.php b/resources/transliteration-data/xc3.php new file mode 100644 index 000000000..f1a495428 --- /dev/null +++ b/resources/transliteration-data/xc3.php @@ -0,0 +1,20 @@ + 'ssal', 'ssalg', 'ssalm', 'ssalb', 'ssals', 'ssalt', 'ssalp', 'ssalh', 'ssam', 'ssab', 'ssabs', 'ssas', 'ssass', 'ssang', 'ssaj', 'ssac', + 0x10 => 'ssak', 'ssat', 'ssap', 'ssah', 'ssae', 'ssaeg', 'ssaegg', 'ssaegs', 'ssaen', 'ssaenj', 'ssaenh', 'ssaed', 'ssael', 'ssaelg', 'ssaelm', 'ssaelb', + 0x20 => 'ssaels', 'ssaelt', 'ssaelp', 'ssaelh', 'ssaem', 'ssaeb', 'ssaebs', 'ssaes', 'ssaess', 'ssaeng', 'ssaej', 'ssaec', 'ssaek', 'ssaet', 'ssaep', 'ssaeh', + 0x30 => 'ssya', 'ssyag', 'ssyagg', 'ssyags', 'ssyan', 'ssyanj', 'ssyanh', 'ssyad', 'ssyal', 'ssyalg', 'ssyalm', 'ssyalb', 'ssyals', 'ssyalt', 'ssyalp', 'ssyalh', + 0x40 => 'ssyam', 'ssyab', 'ssyabs', 'ssyas', 'ssyass', 'ssyang', 'ssyaj', 'ssyac', 'ssyak', 'ssyat', 'ssyap', 'ssyah', 'ssyae', 'ssyaeg', 'ssyaegg', 'ssyaegs', + 0x50 => 'ssyaen', 'ssyaenj', 'ssyaenh', 'ssyaed', 'ssyael', 'ssyaelg', 'ssyaelm', 'ssyaelb', 'ssyaels', 'ssyaelt', 'ssyaelp', 'ssyaelh', 'ssyaem', 'ssyaeb', 'ssyaebs', 'ssyaes', + 0x60 => 'ssyaess', 'ssyaeng', 'ssyaej', 'ssyaec', 'ssyaek', 'ssyaet', 'ssyaep', 'ssyaeh', 'sseo', 'sseog', 'sseogg', 'sseogs', 'sseon', 'sseonj', 'sseonh', 'sseod', + 0x70 => 'sseol', 'sseolg', 'sseolm', 'sseolb', 'sseols', 'sseolt', 'sseolp', 'sseolh', 'sseom', 'sseob', 'sseobs', 'sseos', 'sseoss', 'sseong', 'sseoj', 'sseoc', + 0x80 => 'sseok', 'sseot', 'sseop', 'sseoh', 'sse', 'sseg', 'ssegg', 'ssegs', 'ssen', 'ssenj', 'ssenh', 'ssed', 'ssel', 'sselg', 'sselm', 'sselb', + 0x90 => 'ssels', 'sselt', 'sselp', 'sselh', 'ssem', 'sseb', 'ssebs', 'sses', 'ssess', 'sseng', 'ssej', 'ssec', 'ssek', 'sset', 'ssep', 'sseh', + 0xA0 => 'ssyeo', 'ssyeog', 'ssyeogg', 'ssyeogs', 'ssyeon', 'ssyeonj', 'ssyeonh', 'ssyeod', 'ssyeol', 'ssyeolg', 'ssyeolm', 'ssyeolb', 'ssyeols', 'ssyeolt', 'ssyeolp', 'ssyeolh', + 0xB0 => 'ssyeom', 'ssyeob', 'ssyeobs', 'ssyeos', 'ssyeoss', 'ssyeong', 'ssyeoj', 'ssyeoc', 'ssyeok', 'ssyeot', 'ssyeop', 'ssyeoh', 'ssye', 'ssyeg', 'ssyegg', 'ssyegs', + 0xC0 => 'ssyen', 'ssyenj', 'ssyenh', 'ssyed', 'ssyel', 'ssyelg', 'ssyelm', 'ssyelb', 'ssyels', 'ssyelt', 'ssyelp', 'ssyelh', 'ssyem', 'ssyeb', 'ssyebs', 'ssyes', + 0xD0 => 'ssyess', 'ssyeng', 'ssyej', 'ssyec', 'ssyek', 'ssyet', 'ssyep', 'ssyeh', 'sso', 'ssog', 'ssogg', 'ssogs', 'sson', 'ssonj', 'ssonh', 'ssod', + 0xE0 => 'ssol', 'ssolg', 'ssolm', 'ssolb', 'ssols', 'ssolt', 'ssolp', 'ssolh', 'ssom', 'ssob', 'ssobs', 'ssos', 'ssoss', 'ssong', 'ssoj', 'ssoc', + 0xF0 => 'ssok', 'ssot', 'ssop', 'ssoh', 'sswa', 'sswag', 'sswagg', 'sswags', 'sswan', 'sswanj', 'sswanh', 'sswad', 'sswal', 'sswalg', 'sswalm', 'sswalb', +]; diff --git a/resources/transliteration-data/xc4.php b/resources/transliteration-data/xc4.php new file mode 100644 index 000000000..c06bf2e67 --- /dev/null +++ b/resources/transliteration-data/xc4.php @@ -0,0 +1,20 @@ + 'sswals', 'sswalt', 'sswalp', 'sswalh', 'sswam', 'sswab', 'sswabs', 'sswas', 'sswass', 'sswang', 'sswaj', 'sswac', 'sswak', 'sswat', 'sswap', 'sswah', + 0x10 => 'sswae', 'sswaeg', 'sswaegg', 'sswaegs', 'sswaen', 'sswaenj', 'sswaenh', 'sswaed', 'sswael', 'sswaelg', 'sswaelm', 'sswaelb', 'sswaels', 'sswaelt', 'sswaelp', 'sswaelh', + 0x20 => 'sswaem', 'sswaeb', 'sswaebs', 'sswaes', 'sswaess', 'sswaeng', 'sswaej', 'sswaec', 'sswaek', 'sswaet', 'sswaep', 'sswaeh', 'ssoe', 'ssoeg', 'ssoegg', 'ssoegs', + 0x30 => 'ssoen', 'ssoenj', 'ssoenh', 'ssoed', 'ssoel', 'ssoelg', 'ssoelm', 'ssoelb', 'ssoels', 'ssoelt', 'ssoelp', 'ssoelh', 'ssoem', 'ssoeb', 'ssoebs', 'ssoes', + 0x40 => 'ssoess', 'ssoeng', 'ssoej', 'ssoec', 'ssoek', 'ssoet', 'ssoep', 'ssoeh', 'ssyo', 'ssyog', 'ssyogg', 'ssyogs', 'ssyon', 'ssyonj', 'ssyonh', 'ssyod', + 0x50 => 'ssyol', 'ssyolg', 'ssyolm', 'ssyolb', 'ssyols', 'ssyolt', 'ssyolp', 'ssyolh', 'ssyom', 'ssyob', 'ssyobs', 'ssyos', 'ssyoss', 'ssyong', 'ssyoj', 'ssyoc', + 0x60 => 'ssyok', 'ssyot', 'ssyop', 'ssyoh', 'ssu', 'ssug', 'ssugg', 'ssugs', 'ssun', 'ssunj', 'ssunh', 'ssud', 'ssul', 'ssulg', 'ssulm', 'ssulb', + 0x70 => 'ssuls', 'ssult', 'ssulp', 'ssulh', 'ssum', 'ssub', 'ssubs', 'ssus', 'ssuss', 'ssung', 'ssuj', 'ssuc', 'ssuk', 'ssut', 'ssup', 'ssuh', + 0x80 => 'ssweo', 'ssweog', 'ssweogg', 'ssweogs', 'ssweon', 'ssweonj', 'ssweonh', 'ssweod', 'ssweol', 'ssweolg', 'ssweolm', 'ssweolb', 'ssweols', 'ssweolt', 'ssweolp', 'ssweolh', + 0x90 => 'ssweom', 'ssweob', 'ssweobs', 'ssweos', 'ssweoss', 'ssweong', 'ssweoj', 'ssweoc', 'ssweok', 'ssweot', 'ssweop', 'ssweoh', 'sswe', 'ssweg', 'sswegg', 'sswegs', + 0xA0 => 'sswen', 'sswenj', 'sswenh', 'sswed', 'sswel', 'sswelg', 'sswelm', 'sswelb', 'sswels', 'sswelt', 'sswelp', 'sswelh', 'sswem', 'ssweb', 'sswebs', 'sswes', + 0xB0 => 'sswess', 'ssweng', 'sswej', 'sswec', 'sswek', 'sswet', 'sswep', 'ssweh', 'sswi', 'sswig', 'sswigg', 'sswigs', 'sswin', 'sswinj', 'sswinh', 'sswid', + 0xC0 => 'sswil', 'sswilg', 'sswilm', 'sswilb', 'sswils', 'sswilt', 'sswilp', 'sswilh', 'sswim', 'sswib', 'sswibs', 'sswis', 'sswiss', 'sswing', 'sswij', 'sswic', + 0xD0 => 'sswik', 'sswit', 'sswip', 'sswih', 'ssyu', 'ssyug', 'ssyugg', 'ssyugs', 'ssyun', 'ssyunj', 'ssyunh', 'ssyud', 'ssyul', 'ssyulg', 'ssyulm', 'ssyulb', + 0xE0 => 'ssyuls', 'ssyult', 'ssyulp', 'ssyulh', 'ssyum', 'ssyub', 'ssyubs', 'ssyus', 'ssyuss', 'ssyung', 'ssyuj', 'ssyuc', 'ssyuk', 'ssyut', 'ssyup', 'ssyuh', + 0xF0 => 'sseu', 'sseug', 'sseugg', 'sseugs', 'sseun', 'sseunj', 'sseunh', 'sseud', 'sseul', 'sseulg', 'sseulm', 'sseulb', 'sseuls', 'sseult', 'sseulp', 'sseulh', +]; diff --git a/resources/transliteration-data/xc5.php b/resources/transliteration-data/xc5.php new file mode 100644 index 000000000..7ae03ca96 --- /dev/null +++ b/resources/transliteration-data/xc5.php @@ -0,0 +1,20 @@ + 'sseum', 'sseub', 'sseubs', 'sseus', 'sseuss', 'sseung', 'sseuj', 'sseuc', 'sseuk', 'sseut', 'sseup', 'sseuh', 'ssyi', 'ssyig', 'ssyigg', 'ssyigs', + 0x10 => 'ssyin', 'ssyinj', 'ssyinh', 'ssyid', 'ssyil', 'ssyilg', 'ssyilm', 'ssyilb', 'ssyils', 'ssyilt', 'ssyilp', 'ssyilh', 'ssyim', 'ssyib', 'ssyibs', 'ssyis', + 0x20 => 'ssyiss', 'ssying', 'ssyij', 'ssyic', 'ssyik', 'ssyit', 'ssyip', 'ssyih', 'ssi', 'ssig', 'ssigg', 'ssigs', 'ssin', 'ssinj', 'ssinh', 'ssid', + 0x30 => 'ssil', 'ssilg', 'ssilm', 'ssilb', 'ssils', 'ssilt', 'ssilp', 'ssilh', 'ssim', 'ssib', 'ssibs', 'ssis', 'ssiss', 'ssing', 'ssij', 'ssic', + 0x40 => 'ssik', 'ssit', 'ssip', 'ssih', 'a', 'ag', 'agg', 'ags', 'an', 'anj', 'anh', 'ad', 'al', 'alg', 'alm', 'alb', + 0x50 => 'als', 'alt', 'alp', 'alh', 'am', 'ab', 'abs', 'as', 'ass', 'ang', 'aj', 'ac', 'ak', 'at', 'ap', 'ah', + 0x60 => 'ae', 'aeg', 'aegg', 'aegs', 'aen', 'aenj', 'aenh', 'aed', 'ael', 'aelg', 'aelm', 'aelb', 'aels', 'aelt', 'aelp', 'aelh', + 0x70 => 'aem', 'aeb', 'aebs', 'aes', 'aess', 'aeng', 'aej', 'aec', 'aek', 'aet', 'aep', 'aeh', 'ya', 'yag', 'yagg', 'yags', + 0x80 => 'yan', 'yanj', 'yanh', 'yad', 'yal', 'yalg', 'yalm', 'yalb', 'yals', 'yalt', 'yalp', 'yalh', 'yam', 'yab', 'yabs', 'yas', + 0x90 => 'yass', 'yang', 'yaj', 'yac', 'yak', 'yat', 'yap', 'yah', 'yae', 'yaeg', 'yaegg', 'yaegs', 'yaen', 'yaenj', 'yaenh', 'yaed', + 0xA0 => 'yael', 'yaelg', 'yaelm', 'yaelb', 'yaels', 'yaelt', 'yaelp', 'yaelh', 'yaem', 'yaeb', 'yaebs', 'yaes', 'yaess', 'yaeng', 'yaej', 'yaec', + 0xB0 => 'yaek', 'yaet', 'yaep', 'yaeh', 'eo', 'eog', 'eogg', 'eogs', 'eon', 'eonj', 'eonh', 'eod', 'eol', 'eolg', 'eolm', 'eolb', + 0xC0 => 'eols', 'eolt', 'eolp', 'eolh', 'eom', 'eob', 'eobs', 'eos', 'eoss', 'eong', 'eoj', 'eoc', 'eok', 'eot', 'eop', 'eoh', + 0xD0 => 'e', 'eg', 'egg', 'egs', 'en', 'enj', 'enh', 'ed', 'el', 'elg', 'elm', 'elb', 'els', 'elt', 'elp', 'elh', + 0xE0 => 'em', 'eb', 'ebs', 'es', 'ess', 'eng', 'ej', 'ec', 'ek', 'et', 'ep', 'eh', 'yeo', 'yeog', 'yeogg', 'yeogs', + 0xF0 => 'yeon', 'yeonj', 'yeonh', 'yeod', 'yeol', 'yeolg', 'yeolm', 'yeolb', 'yeols', 'yeolt', 'yeolp', 'yeolh', 'yeom', 'yeob', 'yeobs', 'yeos', +]; diff --git a/resources/transliteration-data/xc6.php b/resources/transliteration-data/xc6.php new file mode 100644 index 000000000..799fb9075 --- /dev/null +++ b/resources/transliteration-data/xc6.php @@ -0,0 +1,20 @@ + 'yeoss', 'yeong', 'yeoj', 'yeoc', 'yeok', 'yeot', 'yeop', 'yeoh', 'ye', 'yeg', 'yegg', 'yegs', 'yen', 'yenj', 'yenh', 'yed', + 0x10 => 'yel', 'yelg', 'yelm', 'yelb', 'yels', 'yelt', 'yelp', 'yelh', 'yem', 'yeb', 'yebs', 'yes', 'yess', 'yeng', 'yej', 'yec', + 0x20 => 'yek', 'yet', 'yep', 'yeh', 'o', 'og', 'ogg', 'ogs', 'on', 'onj', 'onh', 'od', 'ol', 'olg', 'olm', 'olb', + 0x30 => 'ols', 'olt', 'olp', 'olh', 'om', 'ob', 'obs', 'os', 'oss', 'ong', 'oj', 'oc', 'ok', 'ot', 'op', 'oh', + 0x40 => 'wa', 'wag', 'wagg', 'wags', 'wan', 'wanj', 'wanh', 'wad', 'wal', 'walg', 'walm', 'walb', 'wals', 'walt', 'walp', 'walh', + 0x50 => 'wam', 'wab', 'wabs', 'was', 'wass', 'wang', 'waj', 'wac', 'wak', 'wat', 'wap', 'wah', 'wae', 'waeg', 'waegg', 'waegs', + 0x60 => 'waen', 'waenj', 'waenh', 'waed', 'wael', 'waelg', 'waelm', 'waelb', 'waels', 'waelt', 'waelp', 'waelh', 'waem', 'waeb', 'waebs', 'waes', + 0x70 => 'waess', 'waeng', 'waej', 'waec', 'waek', 'waet', 'waep', 'waeh', 'oe', 'oeg', 'oegg', 'oegs', 'oen', 'oenj', 'oenh', 'oed', + 0x80 => 'oel', 'oelg', 'oelm', 'oelb', 'oels', 'oelt', 'oelp', 'oelh', 'oem', 'oeb', 'oebs', 'oes', 'oess', 'oeng', 'oej', 'oec', + 0x90 => 'oek', 'oet', 'oep', 'oeh', 'yo', 'yog', 'yogg', 'yogs', 'yon', 'yonj', 'yonh', 'yod', 'yol', 'yolg', 'yolm', 'yolb', + 0xA0 => 'yols', 'yolt', 'yolp', 'yolh', 'yom', 'yob', 'yobs', 'yos', 'yoss', 'yong', 'yoj', 'yoc', 'yok', 'yot', 'yop', 'yoh', + 0xB0 => 'u', 'ug', 'ugg', 'ugs', 'un', 'unj', 'unh', 'ud', 'ul', 'ulg', 'ulm', 'ulb', 'uls', 'ult', 'ulp', 'ulh', + 0xC0 => 'um', 'ub', 'ubs', 'us', 'uss', 'ung', 'uj', 'uc', 'uk', 'ut', 'up', 'uh', 'weo', 'weog', 'weogg', 'weogs', + 0xD0 => 'weon', 'weonj', 'weonh', 'weod', 'weol', 'weolg', 'weolm', 'weolb', 'weols', 'weolt', 'weolp', 'weolh', 'weom', 'weob', 'weobs', 'weos', + 0xE0 => 'weoss', 'weong', 'weoj', 'weoc', 'weok', 'weot', 'weop', 'weoh', 'we', 'weg', 'wegg', 'wegs', 'wen', 'wenj', 'wenh', 'wed', + 0xF0 => 'wel', 'welg', 'welm', 'welb', 'wels', 'welt', 'welp', 'welh', 'wem', 'web', 'webs', 'wes', 'wess', 'weng', 'wej', 'wec', +]; diff --git a/resources/transliteration-data/xc7.php b/resources/transliteration-data/xc7.php new file mode 100644 index 000000000..260cc8082 --- /dev/null +++ b/resources/transliteration-data/xc7.php @@ -0,0 +1,20 @@ + 'wek', 'wet', 'wep', 'weh', 'wi', 'wig', 'wigg', 'wigs', 'win', 'winj', 'winh', 'wid', 'wil', 'wilg', 'wilm', 'wilb', + 0x10 => 'wils', 'wilt', 'wilp', 'wilh', 'wim', 'wib', 'wibs', 'wis', 'wiss', 'wing', 'wij', 'wic', 'wik', 'wit', 'wip', 'wih', + 0x20 => 'yu', 'yug', 'yugg', 'yugs', 'yun', 'yunj', 'yunh', 'yud', 'yul', 'yulg', 'yulm', 'yulb', 'yuls', 'yult', 'yulp', 'yulh', + 0x30 => 'yum', 'yub', 'yubs', 'yus', 'yuss', 'yung', 'yuj', 'yuc', 'yuk', 'yut', 'yup', 'yuh', 'eu', 'eug', 'eugg', 'eugs', + 0x40 => 'eun', 'eunj', 'eunh', 'eud', 'eul', 'eulg', 'eulm', 'eulb', 'euls', 'eult', 'eulp', 'eulh', 'eum', 'eub', 'eubs', 'eus', + 0x50 => 'euss', 'eung', 'euj', 'euc', 'euk', 'eut', 'eup', 'euh', 'yi', 'yig', 'yigg', 'yigs', 'yin', 'yinj', 'yinh', 'yid', + 0x60 => 'yil', 'yilg', 'yilm', 'yilb', 'yils', 'yilt', 'yilp', 'yilh', 'yim', 'yib', 'yibs', 'yis', 'yiss', 'ying', 'yij', 'yic', + 0x70 => 'yik', 'yit', 'yip', 'yih', 'i', 'ig', 'igg', 'igs', 'in', 'inj', 'inh', 'id', 'il', 'ilg', 'ilm', 'ilb', + 0x80 => 'ils', 'ilt', 'ilp', 'ilh', 'im', 'ib', 'ibs', 'is', 'iss', 'ing', 'ij', 'ic', 'ik', 'it', 'ip', 'ih', + 0x90 => 'ja', 'jag', 'jagg', 'jags', 'jan', 'janj', 'janh', 'jad', 'jal', 'jalg', 'jalm', 'jalb', 'jals', 'jalt', 'jalp', 'jalh', + 0xA0 => 'jam', 'jab', 'jabs', 'jas', 'jass', 'jang', 'jaj', 'jac', 'jak', 'jat', 'jap', 'jah', 'jae', 'jaeg', 'jaegg', 'jaegs', + 0xB0 => 'jaen', 'jaenj', 'jaenh', 'jaed', 'jael', 'jaelg', 'jaelm', 'jaelb', 'jaels', 'jaelt', 'jaelp', 'jaelh', 'jaem', 'jaeb', 'jaebs', 'jaes', + 0xC0 => 'jaess', 'jaeng', 'jaej', 'jaec', 'jaek', 'jaet', 'jaep', 'jaeh', 'jya', 'jyag', 'jyagg', 'jyags', 'jyan', 'jyanj', 'jyanh', 'jyad', + 0xD0 => 'jyal', 'jyalg', 'jyalm', 'jyalb', 'jyals', 'jyalt', 'jyalp', 'jyalh', 'jyam', 'jyab', 'jyabs', 'jyas', 'jyass', 'jyang', 'jyaj', 'jyac', + 0xE0 => 'jyak', 'jyat', 'jyap', 'jyah', 'jyae', 'jyaeg', 'jyaegg', 'jyaegs', 'jyaen', 'jyaenj', 'jyaenh', 'jyaed', 'jyael', 'jyaelg', 'jyaelm', 'jyaelb', + 0xF0 => 'jyaels', 'jyaelt', 'jyaelp', 'jyaelh', 'jyaem', 'jyaeb', 'jyaebs', 'jyaes', 'jyaess', 'jyaeng', 'jyaej', 'jyaec', 'jyaek', 'jyaet', 'jyaep', 'jyaeh', +]; diff --git a/resources/transliteration-data/xc8.php b/resources/transliteration-data/xc8.php new file mode 100644 index 000000000..262c61e77 --- /dev/null +++ b/resources/transliteration-data/xc8.php @@ -0,0 +1,20 @@ + 'jeo', 'jeog', 'jeogg', 'jeogs', 'jeon', 'jeonj', 'jeonh', 'jeod', 'jeol', 'jeolg', 'jeolm', 'jeolb', 'jeols', 'jeolt', 'jeolp', 'jeolh', + 0x10 => 'jeom', 'jeob', 'jeobs', 'jeos', 'jeoss', 'jeong', 'jeoj', 'jeoc', 'jeok', 'jeot', 'jeop', 'jeoh', 'je', 'jeg', 'jegg', 'jegs', + 0x20 => 'jen', 'jenj', 'jenh', 'jed', 'jel', 'jelg', 'jelm', 'jelb', 'jels', 'jelt', 'jelp', 'jelh', 'jem', 'jeb', 'jebs', 'jes', + 0x30 => 'jess', 'jeng', 'jej', 'jec', 'jek', 'jet', 'jep', 'jeh', 'jyeo', 'jyeog', 'jyeogg', 'jyeogs', 'jyeon', 'jyeonj', 'jyeonh', 'jyeod', + 0x40 => 'jyeol', 'jyeolg', 'jyeolm', 'jyeolb', 'jyeols', 'jyeolt', 'jyeolp', 'jyeolh', 'jyeom', 'jyeob', 'jyeobs', 'jyeos', 'jyeoss', 'jyeong', 'jyeoj', 'jyeoc', + 0x50 => 'jyeok', 'jyeot', 'jyeop', 'jyeoh', 'jye', 'jyeg', 'jyegg', 'jyegs', 'jyen', 'jyenj', 'jyenh', 'jyed', 'jyel', 'jyelg', 'jyelm', 'jyelb', + 0x60 => 'jyels', 'jyelt', 'jyelp', 'jyelh', 'jyem', 'jyeb', 'jyebs', 'jyes', 'jyess', 'jyeng', 'jyej', 'jyec', 'jyek', 'jyet', 'jyep', 'jyeh', + 0x70 => 'jo', 'jog', 'jogg', 'jogs', 'jon', 'jonj', 'jonh', 'jod', 'jol', 'jolg', 'jolm', 'jolb', 'jols', 'jolt', 'jolp', 'jolh', + 0x80 => 'jom', 'job', 'jobs', 'jos', 'joss', 'jong', 'joj', 'joc', 'jok', 'jot', 'jop', 'joh', 'jwa', 'jwag', 'jwagg', 'jwags', + 0x90 => 'jwan', 'jwanj', 'jwanh', 'jwad', 'jwal', 'jwalg', 'jwalm', 'jwalb', 'jwals', 'jwalt', 'jwalp', 'jwalh', 'jwam', 'jwab', 'jwabs', 'jwas', + 0xA0 => 'jwass', 'jwang', 'jwaj', 'jwac', 'jwak', 'jwat', 'jwap', 'jwah', 'jwae', 'jwaeg', 'jwaegg', 'jwaegs', 'jwaen', 'jwaenj', 'jwaenh', 'jwaed', + 0xB0 => 'jwael', 'jwaelg', 'jwaelm', 'jwaelb', 'jwaels', 'jwaelt', 'jwaelp', 'jwaelh', 'jwaem', 'jwaeb', 'jwaebs', 'jwaes', 'jwaess', 'jwaeng', 'jwaej', 'jwaec', + 0xC0 => 'jwaek', 'jwaet', 'jwaep', 'jwaeh', 'joe', 'joeg', 'joegg', 'joegs', 'joen', 'joenj', 'joenh', 'joed', 'joel', 'joelg', 'joelm', 'joelb', + 0xD0 => 'joels', 'joelt', 'joelp', 'joelh', 'joem', 'joeb', 'joebs', 'joes', 'joess', 'joeng', 'joej', 'joec', 'joek', 'joet', 'joep', 'joeh', + 0xE0 => 'jyo', 'jyog', 'jyogg', 'jyogs', 'jyon', 'jyonj', 'jyonh', 'jyod', 'jyol', 'jyolg', 'jyolm', 'jyolb', 'jyols', 'jyolt', 'jyolp', 'jyolh', + 0xF0 => 'jyom', 'jyob', 'jyobs', 'jyos', 'jyoss', 'jyong', 'jyoj', 'jyoc', 'jyok', 'jyot', 'jyop', 'jyoh', 'ju', 'jug', 'jugg', 'jugs', +]; diff --git a/resources/transliteration-data/xc9.php b/resources/transliteration-data/xc9.php new file mode 100644 index 000000000..a6bb937fb --- /dev/null +++ b/resources/transliteration-data/xc9.php @@ -0,0 +1,20 @@ + 'jun', 'junj', 'junh', 'jud', 'jul', 'julg', 'julm', 'julb', 'juls', 'jult', 'julp', 'julh', 'jum', 'jub', 'jubs', 'jus', + 0x10 => 'juss', 'jung', 'juj', 'juc', 'juk', 'jut', 'jup', 'juh', 'jweo', 'jweog', 'jweogg', 'jweogs', 'jweon', 'jweonj', 'jweonh', 'jweod', + 0x20 => 'jweol', 'jweolg', 'jweolm', 'jweolb', 'jweols', 'jweolt', 'jweolp', 'jweolh', 'jweom', 'jweob', 'jweobs', 'jweos', 'jweoss', 'jweong', 'jweoj', 'jweoc', + 0x30 => 'jweok', 'jweot', 'jweop', 'jweoh', 'jwe', 'jweg', 'jwegg', 'jwegs', 'jwen', 'jwenj', 'jwenh', 'jwed', 'jwel', 'jwelg', 'jwelm', 'jwelb', + 0x40 => 'jwels', 'jwelt', 'jwelp', 'jwelh', 'jwem', 'jweb', 'jwebs', 'jwes', 'jwess', 'jweng', 'jwej', 'jwec', 'jwek', 'jwet', 'jwep', 'jweh', + 0x50 => 'jwi', 'jwig', 'jwigg', 'jwigs', 'jwin', 'jwinj', 'jwinh', 'jwid', 'jwil', 'jwilg', 'jwilm', 'jwilb', 'jwils', 'jwilt', 'jwilp', 'jwilh', + 0x60 => 'jwim', 'jwib', 'jwibs', 'jwis', 'jwiss', 'jwing', 'jwij', 'jwic', 'jwik', 'jwit', 'jwip', 'jwih', 'jyu', 'jyug', 'jyugg', 'jyugs', + 0x70 => 'jyun', 'jyunj', 'jyunh', 'jyud', 'jyul', 'jyulg', 'jyulm', 'jyulb', 'jyuls', 'jyult', 'jyulp', 'jyulh', 'jyum', 'jyub', 'jyubs', 'jyus', + 0x80 => 'jyuss', 'jyung', 'jyuj', 'jyuc', 'jyuk', 'jyut', 'jyup', 'jyuh', 'jeu', 'jeug', 'jeugg', 'jeugs', 'jeun', 'jeunj', 'jeunh', 'jeud', + 0x90 => 'jeul', 'jeulg', 'jeulm', 'jeulb', 'jeuls', 'jeult', 'jeulp', 'jeulh', 'jeum', 'jeub', 'jeubs', 'jeus', 'jeuss', 'jeung', 'jeuj', 'jeuc', + 0xA0 => 'jeuk', 'jeut', 'jeup', 'jeuh', 'jyi', 'jyig', 'jyigg', 'jyigs', 'jyin', 'jyinj', 'jyinh', 'jyid', 'jyil', 'jyilg', 'jyilm', 'jyilb', + 0xB0 => 'jyils', 'jyilt', 'jyilp', 'jyilh', 'jyim', 'jyib', 'jyibs', 'jyis', 'jyiss', 'jying', 'jyij', 'jyic', 'jyik', 'jyit', 'jyip', 'jyih', + 0xC0 => 'ji', 'jig', 'jigg', 'jigs', 'jin', 'jinj', 'jinh', 'jid', 'jil', 'jilg', 'jilm', 'jilb', 'jils', 'jilt', 'jilp', 'jilh', + 0xD0 => 'jim', 'jib', 'jibs', 'jis', 'jiss', 'jing', 'jij', 'jic', 'jik', 'jit', 'jip', 'jih', 'jja', 'jjag', 'jjagg', 'jjags', + 0xE0 => 'jjan', 'jjanj', 'jjanh', 'jjad', 'jjal', 'jjalg', 'jjalm', 'jjalb', 'jjals', 'jjalt', 'jjalp', 'jjalh', 'jjam', 'jjab', 'jjabs', 'jjas', + 0xF0 => 'jjass', 'jjang', 'jjaj', 'jjac', 'jjak', 'jjat', 'jjap', 'jjah', 'jjae', 'jjaeg', 'jjaegg', 'jjaegs', 'jjaen', 'jjaenj', 'jjaenh', 'jjaed', +]; diff --git a/resources/transliteration-data/xca.php b/resources/transliteration-data/xca.php new file mode 100644 index 000000000..b0e14e469 --- /dev/null +++ b/resources/transliteration-data/xca.php @@ -0,0 +1,20 @@ + 'jjael', 'jjaelg', 'jjaelm', 'jjaelb', 'jjaels', 'jjaelt', 'jjaelp', 'jjaelh', 'jjaem', 'jjaeb', 'jjaebs', 'jjaes', 'jjaess', 'jjaeng', 'jjaej', 'jjaec', + 0x10 => 'jjaek', 'jjaet', 'jjaep', 'jjaeh', 'jjya', 'jjyag', 'jjyagg', 'jjyags', 'jjyan', 'jjyanj', 'jjyanh', 'jjyad', 'jjyal', 'jjyalg', 'jjyalm', 'jjyalb', + 0x20 => 'jjyals', 'jjyalt', 'jjyalp', 'jjyalh', 'jjyam', 'jjyab', 'jjyabs', 'jjyas', 'jjyass', 'jjyang', 'jjyaj', 'jjyac', 'jjyak', 'jjyat', 'jjyap', 'jjyah', + 0x30 => 'jjyae', 'jjyaeg', 'jjyaegg', 'jjyaegs', 'jjyaen', 'jjyaenj', 'jjyaenh', 'jjyaed', 'jjyael', 'jjyaelg', 'jjyaelm', 'jjyaelb', 'jjyaels', 'jjyaelt', 'jjyaelp', 'jjyaelh', + 0x40 => 'jjyaem', 'jjyaeb', 'jjyaebs', 'jjyaes', 'jjyaess', 'jjyaeng', 'jjyaej', 'jjyaec', 'jjyaek', 'jjyaet', 'jjyaep', 'jjyaeh', 'jjeo', 'jjeog', 'jjeogg', 'jjeogs', + 0x50 => 'jjeon', 'jjeonj', 'jjeonh', 'jjeod', 'jjeol', 'jjeolg', 'jjeolm', 'jjeolb', 'jjeols', 'jjeolt', 'jjeolp', 'jjeolh', 'jjeom', 'jjeob', 'jjeobs', 'jjeos', + 0x60 => 'jjeoss', 'jjeong', 'jjeoj', 'jjeoc', 'jjeok', 'jjeot', 'jjeop', 'jjeoh', 'jje', 'jjeg', 'jjegg', 'jjegs', 'jjen', 'jjenj', 'jjenh', 'jjed', + 0x70 => 'jjel', 'jjelg', 'jjelm', 'jjelb', 'jjels', 'jjelt', 'jjelp', 'jjelh', 'jjem', 'jjeb', 'jjebs', 'jjes', 'jjess', 'jjeng', 'jjej', 'jjec', + 0x80 => 'jjek', 'jjet', 'jjep', 'jjeh', 'jjyeo', 'jjyeog', 'jjyeogg', 'jjyeogs', 'jjyeon', 'jjyeonj', 'jjyeonh', 'jjyeod', 'jjyeol', 'jjyeolg', 'jjyeolm', 'jjyeolb', + 0x90 => 'jjyeols', 'jjyeolt', 'jjyeolp', 'jjyeolh', 'jjyeom', 'jjyeob', 'jjyeobs', 'jjyeos', 'jjyeoss', 'jjyeong', 'jjyeoj', 'jjyeoc', 'jjyeok', 'jjyeot', 'jjyeop', 'jjyeoh', + 0xA0 => 'jjye', 'jjyeg', 'jjyegg', 'jjyegs', 'jjyen', 'jjyenj', 'jjyenh', 'jjyed', 'jjyel', 'jjyelg', 'jjyelm', 'jjyelb', 'jjyels', 'jjyelt', 'jjyelp', 'jjyelh', + 0xB0 => 'jjyem', 'jjyeb', 'jjyebs', 'jjyes', 'jjyess', 'jjyeng', 'jjyej', 'jjyec', 'jjyek', 'jjyet', 'jjyep', 'jjyeh', 'jjo', 'jjog', 'jjogg', 'jjogs', + 0xC0 => 'jjon', 'jjonj', 'jjonh', 'jjod', 'jjol', 'jjolg', 'jjolm', 'jjolb', 'jjols', 'jjolt', 'jjolp', 'jjolh', 'jjom', 'jjob', 'jjobs', 'jjos', + 0xD0 => 'jjoss', 'jjong', 'jjoj', 'jjoc', 'jjok', 'jjot', 'jjop', 'jjoh', 'jjwa', 'jjwag', 'jjwagg', 'jjwags', 'jjwan', 'jjwanj', 'jjwanh', 'jjwad', + 0xE0 => 'jjwal', 'jjwalg', 'jjwalm', 'jjwalb', 'jjwals', 'jjwalt', 'jjwalp', 'jjwalh', 'jjwam', 'jjwab', 'jjwabs', 'jjwas', 'jjwass', 'jjwang', 'jjwaj', 'jjwac', + 0xF0 => 'jjwak', 'jjwat', 'jjwap', 'jjwah', 'jjwae', 'jjwaeg', 'jjwaegg', 'jjwaegs', 'jjwaen', 'jjwaenj', 'jjwaenh', 'jjwaed', 'jjwael', 'jjwaelg', 'jjwaelm', 'jjwaelb', +]; diff --git a/resources/transliteration-data/xcb.php b/resources/transliteration-data/xcb.php new file mode 100644 index 000000000..cbd04e85b --- /dev/null +++ b/resources/transliteration-data/xcb.php @@ -0,0 +1,20 @@ + 'jjwaels', 'jjwaelt', 'jjwaelp', 'jjwaelh', 'jjwaem', 'jjwaeb', 'jjwaebs', 'jjwaes', 'jjwaess', 'jjwaeng', 'jjwaej', 'jjwaec', 'jjwaek', 'jjwaet', 'jjwaep', 'jjwaeh', + 0x10 => 'jjoe', 'jjoeg', 'jjoegg', 'jjoegs', 'jjoen', 'jjoenj', 'jjoenh', 'jjoed', 'jjoel', 'jjoelg', 'jjoelm', 'jjoelb', 'jjoels', 'jjoelt', 'jjoelp', 'jjoelh', + 0x20 => 'jjoem', 'jjoeb', 'jjoebs', 'jjoes', 'jjoess', 'jjoeng', 'jjoej', 'jjoec', 'jjoek', 'jjoet', 'jjoep', 'jjoeh', 'jjyo', 'jjyog', 'jjyogg', 'jjyogs', + 0x30 => 'jjyon', 'jjyonj', 'jjyonh', 'jjyod', 'jjyol', 'jjyolg', 'jjyolm', 'jjyolb', 'jjyols', 'jjyolt', 'jjyolp', 'jjyolh', 'jjyom', 'jjyob', 'jjyobs', 'jjyos', + 0x40 => 'jjyoss', 'jjyong', 'jjyoj', 'jjyoc', 'jjyok', 'jjyot', 'jjyop', 'jjyoh', 'jju', 'jjug', 'jjugg', 'jjugs', 'jjun', 'jjunj', 'jjunh', 'jjud', + 0x50 => 'jjul', 'jjulg', 'jjulm', 'jjulb', 'jjuls', 'jjult', 'jjulp', 'jjulh', 'jjum', 'jjub', 'jjubs', 'jjus', 'jjuss', 'jjung', 'jjuj', 'jjuc', + 0x60 => 'jjuk', 'jjut', 'jjup', 'jjuh', 'jjweo', 'jjweog', 'jjweogg', 'jjweogs', 'jjweon', 'jjweonj', 'jjweonh', 'jjweod', 'jjweol', 'jjweolg', 'jjweolm', 'jjweolb', + 0x70 => 'jjweols', 'jjweolt', 'jjweolp', 'jjweolh', 'jjweom', 'jjweob', 'jjweobs', 'jjweos', 'jjweoss', 'jjweong', 'jjweoj', 'jjweoc', 'jjweok', 'jjweot', 'jjweop', 'jjweoh', + 0x80 => 'jjwe', 'jjweg', 'jjwegg', 'jjwegs', 'jjwen', 'jjwenj', 'jjwenh', 'jjwed', 'jjwel', 'jjwelg', 'jjwelm', 'jjwelb', 'jjwels', 'jjwelt', 'jjwelp', 'jjwelh', + 0x90 => 'jjwem', 'jjweb', 'jjwebs', 'jjwes', 'jjwess', 'jjweng', 'jjwej', 'jjwec', 'jjwek', 'jjwet', 'jjwep', 'jjweh', 'jjwi', 'jjwig', 'jjwigg', 'jjwigs', + 0xA0 => 'jjwin', 'jjwinj', 'jjwinh', 'jjwid', 'jjwil', 'jjwilg', 'jjwilm', 'jjwilb', 'jjwils', 'jjwilt', 'jjwilp', 'jjwilh', 'jjwim', 'jjwib', 'jjwibs', 'jjwis', + 0xB0 => 'jjwiss', 'jjwing', 'jjwij', 'jjwic', 'jjwik', 'jjwit', 'jjwip', 'jjwih', 'jjyu', 'jjyug', 'jjyugg', 'jjyugs', 'jjyun', 'jjyunj', 'jjyunh', 'jjyud', + 0xC0 => 'jjyul', 'jjyulg', 'jjyulm', 'jjyulb', 'jjyuls', 'jjyult', 'jjyulp', 'jjyulh', 'jjyum', 'jjyub', 'jjyubs', 'jjyus', 'jjyuss', 'jjyung', 'jjyuj', 'jjyuc', + 0xD0 => 'jjyuk', 'jjyut', 'jjyup', 'jjyuh', 'jjeu', 'jjeug', 'jjeugg', 'jjeugs', 'jjeun', 'jjeunj', 'jjeunh', 'jjeud', 'jjeul', 'jjeulg', 'jjeulm', 'jjeulb', + 0xE0 => 'jjeuls', 'jjeult', 'jjeulp', 'jjeulh', 'jjeum', 'jjeub', 'jjeubs', 'jjeus', 'jjeuss', 'jjeung', 'jjeuj', 'jjeuc', 'jjeuk', 'jjeut', 'jjeup', 'jjeuh', + 0xF0 => 'jjyi', 'jjyig', 'jjyigg', 'jjyigs', 'jjyin', 'jjyinj', 'jjyinh', 'jjyid', 'jjyil', 'jjyilg', 'jjyilm', 'jjyilb', 'jjyils', 'jjyilt', 'jjyilp', 'jjyilh', +]; diff --git a/resources/transliteration-data/xcc.php b/resources/transliteration-data/xcc.php new file mode 100644 index 000000000..d9d25ed64 --- /dev/null +++ b/resources/transliteration-data/xcc.php @@ -0,0 +1,20 @@ + 'jjyim', 'jjyib', 'jjyibs', 'jjyis', 'jjyiss', 'jjying', 'jjyij', 'jjyic', 'jjyik', 'jjyit', 'jjyip', 'jjyih', 'jji', 'jjig', 'jjigg', 'jjigs', + 0x10 => 'jjin', 'jjinj', 'jjinh', 'jjid', 'jjil', 'jjilg', 'jjilm', 'jjilb', 'jjils', 'jjilt', 'jjilp', 'jjilh', 'jjim', 'jjib', 'jjibs', 'jjis', + 0x20 => 'jjiss', 'jjing', 'jjij', 'jjic', 'jjik', 'jjit', 'jjip', 'jjih', 'ca', 'cag', 'cagg', 'cags', 'can', 'canj', 'canh', 'cad', + 0x30 => 'cal', 'calg', 'calm', 'calb', 'cals', 'calt', 'calp', 'calh', 'cam', 'cab', 'cabs', 'cas', 'cass', 'cang', 'caj', 'cac', + 0x40 => 'cak', 'cat', 'cap', 'cah', 'cae', 'caeg', 'caegg', 'caegs', 'caen', 'caenj', 'caenh', 'caed', 'cael', 'caelg', 'caelm', 'caelb', + 0x50 => 'caels', 'caelt', 'caelp', 'caelh', 'caem', 'caeb', 'caebs', 'caes', 'caess', 'caeng', 'caej', 'caec', 'caek', 'caet', 'caep', 'caeh', + 0x60 => 'cya', 'cyag', 'cyagg', 'cyags', 'cyan', 'cyanj', 'cyanh', 'cyad', 'cyal', 'cyalg', 'cyalm', 'cyalb', 'cyals', 'cyalt', 'cyalp', 'cyalh', + 0x70 => 'cyam', 'cyab', 'cyabs', 'cyas', 'cyass', 'cyang', 'cyaj', 'cyac', 'cyak', 'cyat', 'cyap', 'cyah', 'cyae', 'cyaeg', 'cyaegg', 'cyaegs', + 0x80 => 'cyaen', 'cyaenj', 'cyaenh', 'cyaed', 'cyael', 'cyaelg', 'cyaelm', 'cyaelb', 'cyaels', 'cyaelt', 'cyaelp', 'cyaelh', 'cyaem', 'cyaeb', 'cyaebs', 'cyaes', + 0x90 => 'cyaess', 'cyaeng', 'cyaej', 'cyaec', 'cyaek', 'cyaet', 'cyaep', 'cyaeh', 'ceo', 'ceog', 'ceogg', 'ceogs', 'ceon', 'ceonj', 'ceonh', 'ceod', + 0xA0 => 'ceol', 'ceolg', 'ceolm', 'ceolb', 'ceols', 'ceolt', 'ceolp', 'ceolh', 'ceom', 'ceob', 'ceobs', 'ceos', 'ceoss', 'ceong', 'ceoj', 'ceoc', + 0xB0 => 'ceok', 'ceot', 'ceop', 'ceoh', 'ce', 'ceg', 'cegg', 'cegs', 'cen', 'cenj', 'cenh', 'ced', 'cel', 'celg', 'celm', 'celb', + 0xC0 => 'cels', 'celt', 'celp', 'celh', 'cem', 'ceb', 'cebs', 'ces', 'cess', 'ceng', 'cej', 'cec', 'cek', 'cet', 'cep', 'ceh', + 0xD0 => 'cyeo', 'cyeog', 'cyeogg', 'cyeogs', 'cyeon', 'cyeonj', 'cyeonh', 'cyeod', 'cyeol', 'cyeolg', 'cyeolm', 'cyeolb', 'cyeols', 'cyeolt', 'cyeolp', 'cyeolh', + 0xE0 => 'cyeom', 'cyeob', 'cyeobs', 'cyeos', 'cyeoss', 'cyeong', 'cyeoj', 'cyeoc', 'cyeok', 'cyeot', 'cyeop', 'cyeoh', 'cye', 'cyeg', 'cyegg', 'cyegs', + 0xF0 => 'cyen', 'cyenj', 'cyenh', 'cyed', 'cyel', 'cyelg', 'cyelm', 'cyelb', 'cyels', 'cyelt', 'cyelp', 'cyelh', 'cyem', 'cyeb', 'cyebs', 'cyes', +]; diff --git a/resources/transliteration-data/xcd.php b/resources/transliteration-data/xcd.php new file mode 100644 index 000000000..2a83fa7f4 --- /dev/null +++ b/resources/transliteration-data/xcd.php @@ -0,0 +1,20 @@ + 'cyess', 'cyeng', 'cyej', 'cyec', 'cyek', 'cyet', 'cyep', 'cyeh', 'co', 'cog', 'cogg', 'cogs', 'con', 'conj', 'conh', 'cod', + 0x10 => 'col', 'colg', 'colm', 'colb', 'cols', 'colt', 'colp', 'colh', 'com', 'cob', 'cobs', 'cos', 'coss', 'cong', 'coj', 'coc', + 0x20 => 'cok', 'cot', 'cop', 'coh', 'cwa', 'cwag', 'cwagg', 'cwags', 'cwan', 'cwanj', 'cwanh', 'cwad', 'cwal', 'cwalg', 'cwalm', 'cwalb', + 0x30 => 'cwals', 'cwalt', 'cwalp', 'cwalh', 'cwam', 'cwab', 'cwabs', 'cwas', 'cwass', 'cwang', 'cwaj', 'cwac', 'cwak', 'cwat', 'cwap', 'cwah', + 0x40 => 'cwae', 'cwaeg', 'cwaegg', 'cwaegs', 'cwaen', 'cwaenj', 'cwaenh', 'cwaed', 'cwael', 'cwaelg', 'cwaelm', 'cwaelb', 'cwaels', 'cwaelt', 'cwaelp', 'cwaelh', + 0x50 => 'cwaem', 'cwaeb', 'cwaebs', 'cwaes', 'cwaess', 'cwaeng', 'cwaej', 'cwaec', 'cwaek', 'cwaet', 'cwaep', 'cwaeh', 'coe', 'coeg', 'coegg', 'coegs', + 0x60 => 'coen', 'coenj', 'coenh', 'coed', 'coel', 'coelg', 'coelm', 'coelb', 'coels', 'coelt', 'coelp', 'coelh', 'coem', 'coeb', 'coebs', 'coes', + 0x70 => 'coess', 'coeng', 'coej', 'coec', 'coek', 'coet', 'coep', 'coeh', 'cyo', 'cyog', 'cyogg', 'cyogs', 'cyon', 'cyonj', 'cyonh', 'cyod', + 0x80 => 'cyol', 'cyolg', 'cyolm', 'cyolb', 'cyols', 'cyolt', 'cyolp', 'cyolh', 'cyom', 'cyob', 'cyobs', 'cyos', 'cyoss', 'cyong', 'cyoj', 'cyoc', + 0x90 => 'cyok', 'cyot', 'cyop', 'cyoh', 'cu', 'cug', 'cugg', 'cugs', 'cun', 'cunj', 'cunh', 'cud', 'cul', 'culg', 'culm', 'culb', + 0xA0 => 'culs', 'cult', 'culp', 'culh', 'cum', 'cub', 'cubs', 'cus', 'cuss', 'cung', 'cuj', 'cuc', 'cuk', 'cut', 'cup', 'cuh', + 0xB0 => 'cweo', 'cweog', 'cweogg', 'cweogs', 'cweon', 'cweonj', 'cweonh', 'cweod', 'cweol', 'cweolg', 'cweolm', 'cweolb', 'cweols', 'cweolt', 'cweolp', 'cweolh', + 0xC0 => 'cweom', 'cweob', 'cweobs', 'cweos', 'cweoss', 'cweong', 'cweoj', 'cweoc', 'cweok', 'cweot', 'cweop', 'cweoh', 'cwe', 'cweg', 'cwegg', 'cwegs', + 0xD0 => 'cwen', 'cwenj', 'cwenh', 'cwed', 'cwel', 'cwelg', 'cwelm', 'cwelb', 'cwels', 'cwelt', 'cwelp', 'cwelh', 'cwem', 'cweb', 'cwebs', 'cwes', + 0xE0 => 'cwess', 'cweng', 'cwej', 'cwec', 'cwek', 'cwet', 'cwep', 'cweh', 'cwi', 'cwig', 'cwigg', 'cwigs', 'cwin', 'cwinj', 'cwinh', 'cwid', + 0xF0 => 'cwil', 'cwilg', 'cwilm', 'cwilb', 'cwils', 'cwilt', 'cwilp', 'cwilh', 'cwim', 'cwib', 'cwibs', 'cwis', 'cwiss', 'cwing', 'cwij', 'cwic', +]; diff --git a/resources/transliteration-data/xce.php b/resources/transliteration-data/xce.php new file mode 100644 index 000000000..713aa4931 --- /dev/null +++ b/resources/transliteration-data/xce.php @@ -0,0 +1,20 @@ + 'cwik', 'cwit', 'cwip', 'cwih', 'cyu', 'cyug', 'cyugg', 'cyugs', 'cyun', 'cyunj', 'cyunh', 'cyud', 'cyul', 'cyulg', 'cyulm', 'cyulb', + 0x10 => 'cyuls', 'cyult', 'cyulp', 'cyulh', 'cyum', 'cyub', 'cyubs', 'cyus', 'cyuss', 'cyung', 'cyuj', 'cyuc', 'cyuk', 'cyut', 'cyup', 'cyuh', + 0x20 => 'ceu', 'ceug', 'ceugg', 'ceugs', 'ceun', 'ceunj', 'ceunh', 'ceud', 'ceul', 'ceulg', 'ceulm', 'ceulb', 'ceuls', 'ceult', 'ceulp', 'ceulh', + 0x30 => 'ceum', 'ceub', 'ceubs', 'ceus', 'ceuss', 'ceung', 'ceuj', 'ceuc', 'ceuk', 'ceut', 'ceup', 'ceuh', 'cyi', 'cyig', 'cyigg', 'cyigs', + 0x40 => 'cyin', 'cyinj', 'cyinh', 'cyid', 'cyil', 'cyilg', 'cyilm', 'cyilb', 'cyils', 'cyilt', 'cyilp', 'cyilh', 'cyim', 'cyib', 'cyibs', 'cyis', + 0x50 => 'cyiss', 'cying', 'cyij', 'cyic', 'cyik', 'cyit', 'cyip', 'cyih', 'ci', 'cig', 'cigg', 'cigs', 'cin', 'cinj', 'cinh', 'cid', + 0x60 => 'cil', 'cilg', 'cilm', 'cilb', 'cils', 'cilt', 'cilp', 'cilh', 'cim', 'cib', 'cibs', 'cis', 'ciss', 'cing', 'cij', 'cic', + 0x70 => 'cik', 'cit', 'cip', 'cih', 'ka', 'kag', 'kagg', 'kags', 'kan', 'kanj', 'kanh', 'kad', 'kal', 'kalg', 'kalm', 'kalb', + 0x80 => 'kals', 'kalt', 'kalp', 'kalh', 'kam', 'kab', 'kabs', 'kas', 'kass', 'kang', 'kaj', 'kac', 'kak', 'kat', 'kap', 'kah', + 0x90 => 'kae', 'kaeg', 'kaegg', 'kaegs', 'kaen', 'kaenj', 'kaenh', 'kaed', 'kael', 'kaelg', 'kaelm', 'kaelb', 'kaels', 'kaelt', 'kaelp', 'kaelh', + 0xA0 => 'kaem', 'kaeb', 'kaebs', 'kaes', 'kaess', 'kaeng', 'kaej', 'kaec', 'kaek', 'kaet', 'kaep', 'kaeh', 'kya', 'kyag', 'kyagg', 'kyags', + 0xB0 => 'kyan', 'kyanj', 'kyanh', 'kyad', 'kyal', 'kyalg', 'kyalm', 'kyalb', 'kyals', 'kyalt', 'kyalp', 'kyalh', 'kyam', 'kyab', 'kyabs', 'kyas', + 0xC0 => 'kyass', 'kyang', 'kyaj', 'kyac', 'kyak', 'kyat', 'kyap', 'kyah', 'kyae', 'kyaeg', 'kyaegg', 'kyaegs', 'kyaen', 'kyaenj', 'kyaenh', 'kyaed', + 0xD0 => 'kyael', 'kyaelg', 'kyaelm', 'kyaelb', 'kyaels', 'kyaelt', 'kyaelp', 'kyaelh', 'kyaem', 'kyaeb', 'kyaebs', 'kyaes', 'kyaess', 'kyaeng', 'kyaej', 'kyaec', + 0xE0 => 'kyaek', 'kyaet', 'kyaep', 'kyaeh', 'keo', 'keog', 'keogg', 'keogs', 'keon', 'keonj', 'keonh', 'keod', 'keol', 'keolg', 'keolm', 'keolb', + 0xF0 => 'keols', 'keolt', 'keolp', 'keolh', 'keom', 'keob', 'keobs', 'keos', 'keoss', 'keong', 'keoj', 'keoc', 'keok', 'keot', 'keop', 'keoh', +]; diff --git a/resources/transliteration-data/xcf.php b/resources/transliteration-data/xcf.php new file mode 100644 index 000000000..20ed8e962 --- /dev/null +++ b/resources/transliteration-data/xcf.php @@ -0,0 +1,20 @@ + 'ke', 'keg', 'kegg', 'kegs', 'ken', 'kenj', 'kenh', 'ked', 'kel', 'kelg', 'kelm', 'kelb', 'kels', 'kelt', 'kelp', 'kelh', + 0x10 => 'kem', 'keb', 'kebs', 'kes', 'kess', 'keng', 'kej', 'kec', 'kek', 'ket', 'kep', 'keh', 'kyeo', 'kyeog', 'kyeogg', 'kyeogs', + 0x20 => 'kyeon', 'kyeonj', 'kyeonh', 'kyeod', 'kyeol', 'kyeolg', 'kyeolm', 'kyeolb', 'kyeols', 'kyeolt', 'kyeolp', 'kyeolh', 'kyeom', 'kyeob', 'kyeobs', 'kyeos', + 0x30 => 'kyeoss', 'kyeong', 'kyeoj', 'kyeoc', 'kyeok', 'kyeot', 'kyeop', 'kyeoh', 'kye', 'kyeg', 'kyegg', 'kyegs', 'kyen', 'kyenj', 'kyenh', 'kyed', + 0x40 => 'kyel', 'kyelg', 'kyelm', 'kyelb', 'kyels', 'kyelt', 'kyelp', 'kyelh', 'kyem', 'kyeb', 'kyebs', 'kyes', 'kyess', 'kyeng', 'kyej', 'kyec', + 0x50 => 'kyek', 'kyet', 'kyep', 'kyeh', 'ko', 'kog', 'kogg', 'kogs', 'kon', 'konj', 'konh', 'kod', 'kol', 'kolg', 'kolm', 'kolb', + 0x60 => 'kols', 'kolt', 'kolp', 'kolh', 'kom', 'kob', 'kobs', 'kos', 'koss', 'kong', 'koj', 'koc', 'kok', 'kot', 'kop', 'koh', + 0x70 => 'kwa', 'kwag', 'kwagg', 'kwags', 'kwan', 'kwanj', 'kwanh', 'kwad', 'kwal', 'kwalg', 'kwalm', 'kwalb', 'kwals', 'kwalt', 'kwalp', 'kwalh', + 0x80 => 'kwam', 'kwab', 'kwabs', 'kwas', 'kwass', 'kwang', 'kwaj', 'kwac', 'kwak', 'kwat', 'kwap', 'kwah', 'kwae', 'kwaeg', 'kwaegg', 'kwaegs', + 0x90 => 'kwaen', 'kwaenj', 'kwaenh', 'kwaed', 'kwael', 'kwaelg', 'kwaelm', 'kwaelb', 'kwaels', 'kwaelt', 'kwaelp', 'kwaelh', 'kwaem', 'kwaeb', 'kwaebs', 'kwaes', + 0xA0 => 'kwaess', 'kwaeng', 'kwaej', 'kwaec', 'kwaek', 'kwaet', 'kwaep', 'kwaeh', 'koe', 'koeg', 'koegg', 'koegs', 'koen', 'koenj', 'koenh', 'koed', + 0xB0 => 'koel', 'koelg', 'koelm', 'koelb', 'koels', 'koelt', 'koelp', 'koelh', 'koem', 'koeb', 'koebs', 'koes', 'koess', 'koeng', 'koej', 'koec', + 0xC0 => 'koek', 'koet', 'koep', 'koeh', 'kyo', 'kyog', 'kyogg', 'kyogs', 'kyon', 'kyonj', 'kyonh', 'kyod', 'kyol', 'kyolg', 'kyolm', 'kyolb', + 0xD0 => 'kyols', 'kyolt', 'kyolp', 'kyolh', 'kyom', 'kyob', 'kyobs', 'kyos', 'kyoss', 'kyong', 'kyoj', 'kyoc', 'kyok', 'kyot', 'kyop', 'kyoh', + 0xE0 => 'ku', 'kug', 'kugg', 'kugs', 'kun', 'kunj', 'kunh', 'kud', 'kul', 'kulg', 'kulm', 'kulb', 'kuls', 'kult', 'kulp', 'kulh', + 0xF0 => 'kum', 'kub', 'kubs', 'kus', 'kuss', 'kung', 'kuj', 'kuc', 'kuk', 'kut', 'kup', 'kuh', 'kweo', 'kweog', 'kweogg', 'kweogs', +]; diff --git a/resources/transliteration-data/xd0.php b/resources/transliteration-data/xd0.php new file mode 100644 index 000000000..9c2a940e2 --- /dev/null +++ b/resources/transliteration-data/xd0.php @@ -0,0 +1,20 @@ + 'kweon', 'kweonj', 'kweonh', 'kweod', 'kweol', 'kweolg', 'kweolm', 'kweolb', 'kweols', 'kweolt', 'kweolp', 'kweolh', 'kweom', 'kweob', 'kweobs', 'kweos', + 0x10 => 'kweoss', 'kweong', 'kweoj', 'kweoc', 'kweok', 'kweot', 'kweop', 'kweoh', 'kwe', 'kweg', 'kwegg', 'kwegs', 'kwen', 'kwenj', 'kwenh', 'kwed', + 0x20 => 'kwel', 'kwelg', 'kwelm', 'kwelb', 'kwels', 'kwelt', 'kwelp', 'kwelh', 'kwem', 'kweb', 'kwebs', 'kwes', 'kwess', 'kweng', 'kwej', 'kwec', + 0x30 => 'kwek', 'kwet', 'kwep', 'kweh', 'kwi', 'kwig', 'kwigg', 'kwigs', 'kwin', 'kwinj', 'kwinh', 'kwid', 'kwil', 'kwilg', 'kwilm', 'kwilb', + 0x40 => 'kwils', 'kwilt', 'kwilp', 'kwilh', 'kwim', 'kwib', 'kwibs', 'kwis', 'kwiss', 'kwing', 'kwij', 'kwic', 'kwik', 'kwit', 'kwip', 'kwih', + 0x50 => 'kyu', 'kyug', 'kyugg', 'kyugs', 'kyun', 'kyunj', 'kyunh', 'kyud', 'kyul', 'kyulg', 'kyulm', 'kyulb', 'kyuls', 'kyult', 'kyulp', 'kyulh', + 0x60 => 'kyum', 'kyub', 'kyubs', 'kyus', 'kyuss', 'kyung', 'kyuj', 'kyuc', 'kyuk', 'kyut', 'kyup', 'kyuh', 'keu', 'keug', 'keugg', 'keugs', + 0x70 => 'keun', 'keunj', 'keunh', 'keud', 'keul', 'keulg', 'keulm', 'keulb', 'keuls', 'keult', 'keulp', 'keulh', 'keum', 'keub', 'keubs', 'keus', + 0x80 => 'keuss', 'keung', 'keuj', 'keuc', 'keuk', 'keut', 'keup', 'keuh', 'kyi', 'kyig', 'kyigg', 'kyigs', 'kyin', 'kyinj', 'kyinh', 'kyid', + 0x90 => 'kyil', 'kyilg', 'kyilm', 'kyilb', 'kyils', 'kyilt', 'kyilp', 'kyilh', 'kyim', 'kyib', 'kyibs', 'kyis', 'kyiss', 'kying', 'kyij', 'kyic', + 0xA0 => 'kyik', 'kyit', 'kyip', 'kyih', 'ki', 'kig', 'kigg', 'kigs', 'kin', 'kinj', 'kinh', 'kid', 'kil', 'kilg', 'kilm', 'kilb', + 0xB0 => 'kils', 'kilt', 'kilp', 'kilh', 'kim', 'kib', 'kibs', 'kis', 'kiss', 'king', 'kij', 'kic', 'kik', 'kit', 'kip', 'kih', + 0xC0 => 'ta', 'tag', 'tagg', 'tags', 'tan', 'tanj', 'tanh', 'tad', 'tal', 'talg', 'talm', 'talb', 'tals', 'talt', 'talp', 'talh', + 0xD0 => 'tam', 'tab', 'tabs', 'tas', 'tass', 'tang', 'taj', 'tac', 'tak', 'tat', 'tap', 'tah', 'tae', 'taeg', 'taegg', 'taegs', + 0xE0 => 'taen', 'taenj', 'taenh', 'taed', 'tael', 'taelg', 'taelm', 'taelb', 'taels', 'taelt', 'taelp', 'taelh', 'taem', 'taeb', 'taebs', 'taes', + 0xF0 => 'taess', 'taeng', 'taej', 'taec', 'taek', 'taet', 'taep', 'taeh', 'tya', 'tyag', 'tyagg', 'tyags', 'tyan', 'tyanj', 'tyanh', 'tyad', +]; diff --git a/resources/transliteration-data/xd1.php b/resources/transliteration-data/xd1.php new file mode 100644 index 000000000..3ad11e317 --- /dev/null +++ b/resources/transliteration-data/xd1.php @@ -0,0 +1,20 @@ + 'tyal', 'tyalg', 'tyalm', 'tyalb', 'tyals', 'tyalt', 'tyalp', 'tyalh', 'tyam', 'tyab', 'tyabs', 'tyas', 'tyass', 'tyang', 'tyaj', 'tyac', + 0x10 => 'tyak', 'tyat', 'tyap', 'tyah', 'tyae', 'tyaeg', 'tyaegg', 'tyaegs', 'tyaen', 'tyaenj', 'tyaenh', 'tyaed', 'tyael', 'tyaelg', 'tyaelm', 'tyaelb', + 0x20 => 'tyaels', 'tyaelt', 'tyaelp', 'tyaelh', 'tyaem', 'tyaeb', 'tyaebs', 'tyaes', 'tyaess', 'tyaeng', 'tyaej', 'tyaec', 'tyaek', 'tyaet', 'tyaep', 'tyaeh', + 0x30 => 'teo', 'teog', 'teogg', 'teogs', 'teon', 'teonj', 'teonh', 'teod', 'teol', 'teolg', 'teolm', 'teolb', 'teols', 'teolt', 'teolp', 'teolh', + 0x40 => 'teom', 'teob', 'teobs', 'teos', 'teoss', 'teong', 'teoj', 'teoc', 'teok', 'teot', 'teop', 'teoh', 'te', 'teg', 'tegg', 'tegs', + 0x50 => 'ten', 'tenj', 'tenh', 'ted', 'tel', 'telg', 'telm', 'telb', 'tels', 'telt', 'telp', 'telh', 'tem', 'teb', 'tebs', 'tes', + 0x60 => 'tess', 'teng', 'tej', 'tec', 'tek', 'tet', 'tep', 'teh', 'tyeo', 'tyeog', 'tyeogg', 'tyeogs', 'tyeon', 'tyeonj', 'tyeonh', 'tyeod', + 0x70 => 'tyeol', 'tyeolg', 'tyeolm', 'tyeolb', 'tyeols', 'tyeolt', 'tyeolp', 'tyeolh', 'tyeom', 'tyeob', 'tyeobs', 'tyeos', 'tyeoss', 'tyeong', 'tyeoj', 'tyeoc', + 0x80 => 'tyeok', 'tyeot', 'tyeop', 'tyeoh', 'tye', 'tyeg', 'tyegg', 'tyegs', 'tyen', 'tyenj', 'tyenh', 'tyed', 'tyel', 'tyelg', 'tyelm', 'tyelb', + 0x90 => 'tyels', 'tyelt', 'tyelp', 'tyelh', 'tyem', 'tyeb', 'tyebs', 'tyes', 'tyess', 'tyeng', 'tyej', 'tyec', 'tyek', 'tyet', 'tyep', 'tyeh', + 0xA0 => 'to', 'tog', 'togg', 'togs', 'ton', 'tonj', 'tonh', 'tod', 'tol', 'tolg', 'tolm', 'tolb', 'tols', 'tolt', 'tolp', 'tolh', + 0xB0 => 'tom', 'tob', 'tobs', 'tos', 'toss', 'tong', 'toj', 'toc', 'tok', 'tot', 'top', 'toh', 'twa', 'twag', 'twagg', 'twags', + 0xC0 => 'twan', 'twanj', 'twanh', 'twad', 'twal', 'twalg', 'twalm', 'twalb', 'twals', 'twalt', 'twalp', 'twalh', 'twam', 'twab', 'twabs', 'twas', + 0xD0 => 'twass', 'twang', 'twaj', 'twac', 'twak', 'twat', 'twap', 'twah', 'twae', 'twaeg', 'twaegg', 'twaegs', 'twaen', 'twaenj', 'twaenh', 'twaed', + 0xE0 => 'twael', 'twaelg', 'twaelm', 'twaelb', 'twaels', 'twaelt', 'twaelp', 'twaelh', 'twaem', 'twaeb', 'twaebs', 'twaes', 'twaess', 'twaeng', 'twaej', 'twaec', + 0xF0 => 'twaek', 'twaet', 'twaep', 'twaeh', 'toe', 'toeg', 'toegg', 'toegs', 'toen', 'toenj', 'toenh', 'toed', 'toel', 'toelg', 'toelm', 'toelb', +]; diff --git a/resources/transliteration-data/xd2.php b/resources/transliteration-data/xd2.php new file mode 100644 index 000000000..37e0d5953 --- /dev/null +++ b/resources/transliteration-data/xd2.php @@ -0,0 +1,20 @@ + 'toels', 'toelt', 'toelp', 'toelh', 'toem', 'toeb', 'toebs', 'toes', 'toess', 'toeng', 'toej', 'toec', 'toek', 'toet', 'toep', 'toeh', + 0x10 => 'tyo', 'tyog', 'tyogg', 'tyogs', 'tyon', 'tyonj', 'tyonh', 'tyod', 'tyol', 'tyolg', 'tyolm', 'tyolb', 'tyols', 'tyolt', 'tyolp', 'tyolh', + 0x20 => 'tyom', 'tyob', 'tyobs', 'tyos', 'tyoss', 'tyong', 'tyoj', 'tyoc', 'tyok', 'tyot', 'tyop', 'tyoh', 'tu', 'tug', 'tugg', 'tugs', + 0x30 => 'tun', 'tunj', 'tunh', 'tud', 'tul', 'tulg', 'tulm', 'tulb', 'tuls', 'tult', 'tulp', 'tulh', 'tum', 'tub', 'tubs', 'tus', + 0x40 => 'tuss', 'tung', 'tuj', 'tuc', 'tuk', 'tut', 'tup', 'tuh', 'tweo', 'tweog', 'tweogg', 'tweogs', 'tweon', 'tweonj', 'tweonh', 'tweod', + 0x50 => 'tweol', 'tweolg', 'tweolm', 'tweolb', 'tweols', 'tweolt', 'tweolp', 'tweolh', 'tweom', 'tweob', 'tweobs', 'tweos', 'tweoss', 'tweong', 'tweoj', 'tweoc', + 0x60 => 'tweok', 'tweot', 'tweop', 'tweoh', 'twe', 'tweg', 'twegg', 'twegs', 'twen', 'twenj', 'twenh', 'twed', 'twel', 'twelg', 'twelm', 'twelb', + 0x70 => 'twels', 'twelt', 'twelp', 'twelh', 'twem', 'tweb', 'twebs', 'twes', 'twess', 'tweng', 'twej', 'twec', 'twek', 'twet', 'twep', 'tweh', + 0x80 => 'twi', 'twig', 'twigg', 'twigs', 'twin', 'twinj', 'twinh', 'twid', 'twil', 'twilg', 'twilm', 'twilb', 'twils', 'twilt', 'twilp', 'twilh', + 0x90 => 'twim', 'twib', 'twibs', 'twis', 'twiss', 'twing', 'twij', 'twic', 'twik', 'twit', 'twip', 'twih', 'tyu', 'tyug', 'tyugg', 'tyugs', + 0xA0 => 'tyun', 'tyunj', 'tyunh', 'tyud', 'tyul', 'tyulg', 'tyulm', 'tyulb', 'tyuls', 'tyult', 'tyulp', 'tyulh', 'tyum', 'tyub', 'tyubs', 'tyus', + 0xB0 => 'tyuss', 'tyung', 'tyuj', 'tyuc', 'tyuk', 'tyut', 'tyup', 'tyuh', 'teu', 'teug', 'teugg', 'teugs', 'teun', 'teunj', 'teunh', 'teud', + 0xC0 => 'teul', 'teulg', 'teulm', 'teulb', 'teuls', 'teult', 'teulp', 'teulh', 'teum', 'teub', 'teubs', 'teus', 'teuss', 'teung', 'teuj', 'teuc', + 0xD0 => 'teuk', 'teut', 'teup', 'teuh', 'tyi', 'tyig', 'tyigg', 'tyigs', 'tyin', 'tyinj', 'tyinh', 'tyid', 'tyil', 'tyilg', 'tyilm', 'tyilb', + 0xE0 => 'tyils', 'tyilt', 'tyilp', 'tyilh', 'tyim', 'tyib', 'tyibs', 'tyis', 'tyiss', 'tying', 'tyij', 'tyic', 'tyik', 'tyit', 'tyip', 'tyih', + 0xF0 => 'ti', 'tig', 'tigg', 'tigs', 'tin', 'tinj', 'tinh', 'tid', 'til', 'tilg', 'tilm', 'tilb', 'tils', 'tilt', 'tilp', 'tilh', +]; diff --git a/resources/transliteration-data/xd3.php b/resources/transliteration-data/xd3.php new file mode 100644 index 000000000..762fb3481 --- /dev/null +++ b/resources/transliteration-data/xd3.php @@ -0,0 +1,20 @@ + 'tim', 'tib', 'tibs', 'tis', 'tiss', 'ting', 'tij', 'tic', 'tik', 'tit', 'tip', 'tih', 'pa', 'pag', 'pagg', 'pags', + 0x10 => 'pan', 'panj', 'panh', 'pad', 'pal', 'palg', 'palm', 'palb', 'pals', 'palt', 'palp', 'palh', 'pam', 'pab', 'pabs', 'pas', + 0x20 => 'pass', 'pang', 'paj', 'pac', 'pak', 'pat', 'pap', 'pah', 'pae', 'paeg', 'paegg', 'paegs', 'paen', 'paenj', 'paenh', 'paed', + 0x30 => 'pael', 'paelg', 'paelm', 'paelb', 'paels', 'paelt', 'paelp', 'paelh', 'paem', 'paeb', 'paebs', 'paes', 'paess', 'paeng', 'paej', 'paec', + 0x40 => 'paek', 'paet', 'paep', 'paeh', 'pya', 'pyag', 'pyagg', 'pyags', 'pyan', 'pyanj', 'pyanh', 'pyad', 'pyal', 'pyalg', 'pyalm', 'pyalb', + 0x50 => 'pyals', 'pyalt', 'pyalp', 'pyalh', 'pyam', 'pyab', 'pyabs', 'pyas', 'pyass', 'pyang', 'pyaj', 'pyac', 'pyak', 'pyat', 'pyap', 'pyah', + 0x60 => 'pyae', 'pyaeg', 'pyaegg', 'pyaegs', 'pyaen', 'pyaenj', 'pyaenh', 'pyaed', 'pyael', 'pyaelg', 'pyaelm', 'pyaelb', 'pyaels', 'pyaelt', 'pyaelp', 'pyaelh', + 0x70 => 'pyaem', 'pyaeb', 'pyaebs', 'pyaes', 'pyaess', 'pyaeng', 'pyaej', 'pyaec', 'pyaek', 'pyaet', 'pyaep', 'pyaeh', 'peo', 'peog', 'peogg', 'peogs', + 0x80 => 'peon', 'peonj', 'peonh', 'peod', 'peol', 'peolg', 'peolm', 'peolb', 'peols', 'peolt', 'peolp', 'peolh', 'peom', 'peob', 'peobs', 'peos', + 0x90 => 'peoss', 'peong', 'peoj', 'peoc', 'peok', 'peot', 'peop', 'peoh', 'pe', 'peg', 'pegg', 'pegs', 'pen', 'penj', 'penh', 'ped', + 0xA0 => 'pel', 'pelg', 'pelm', 'pelb', 'pels', 'pelt', 'pelp', 'pelh', 'pem', 'peb', 'pebs', 'pes', 'pess', 'peng', 'pej', 'pec', + 0xB0 => 'pek', 'pet', 'pep', 'peh', 'pyeo', 'pyeog', 'pyeogg', 'pyeogs', 'pyeon', 'pyeonj', 'pyeonh', 'pyeod', 'pyeol', 'pyeolg', 'pyeolm', 'pyeolb', + 0xC0 => 'pyeols', 'pyeolt', 'pyeolp', 'pyeolh', 'pyeom', 'pyeob', 'pyeobs', 'pyeos', 'pyeoss', 'pyeong', 'pyeoj', 'pyeoc', 'pyeok', 'pyeot', 'pyeop', 'pyeoh', + 0xD0 => 'pye', 'pyeg', 'pyegg', 'pyegs', 'pyen', 'pyenj', 'pyenh', 'pyed', 'pyel', 'pyelg', 'pyelm', 'pyelb', 'pyels', 'pyelt', 'pyelp', 'pyelh', + 0xE0 => 'pyem', 'pyeb', 'pyebs', 'pyes', 'pyess', 'pyeng', 'pyej', 'pyec', 'pyek', 'pyet', 'pyep', 'pyeh', 'po', 'pog', 'pogg', 'pogs', + 0xF0 => 'pon', 'ponj', 'ponh', 'pod', 'pol', 'polg', 'polm', 'polb', 'pols', 'polt', 'polp', 'polh', 'pom', 'pob', 'pobs', 'pos', +]; diff --git a/resources/transliteration-data/xd4.php b/resources/transliteration-data/xd4.php new file mode 100644 index 000000000..8fc36ac2f --- /dev/null +++ b/resources/transliteration-data/xd4.php @@ -0,0 +1,20 @@ + 'poss', 'pong', 'poj', 'poc', 'pok', 'pot', 'pop', 'poh', 'pwa', 'pwag', 'pwagg', 'pwags', 'pwan', 'pwanj', 'pwanh', 'pwad', + 0x10 => 'pwal', 'pwalg', 'pwalm', 'pwalb', 'pwals', 'pwalt', 'pwalp', 'pwalh', 'pwam', 'pwab', 'pwabs', 'pwas', 'pwass', 'pwang', 'pwaj', 'pwac', + 0x20 => 'pwak', 'pwat', 'pwap', 'pwah', 'pwae', 'pwaeg', 'pwaegg', 'pwaegs', 'pwaen', 'pwaenj', 'pwaenh', 'pwaed', 'pwael', 'pwaelg', 'pwaelm', 'pwaelb', + 0x30 => 'pwaels', 'pwaelt', 'pwaelp', 'pwaelh', 'pwaem', 'pwaeb', 'pwaebs', 'pwaes', 'pwaess', 'pwaeng', 'pwaej', 'pwaec', 'pwaek', 'pwaet', 'pwaep', 'pwaeh', + 0x40 => 'poe', 'poeg', 'poegg', 'poegs', 'poen', 'poenj', 'poenh', 'poed', 'poel', 'poelg', 'poelm', 'poelb', 'poels', 'poelt', 'poelp', 'poelh', + 0x50 => 'poem', 'poeb', 'poebs', 'poes', 'poess', 'poeng', 'poej', 'poec', 'poek', 'poet', 'poep', 'poeh', 'pyo', 'pyog', 'pyogg', 'pyogs', + 0x60 => 'pyon', 'pyonj', 'pyonh', 'pyod', 'pyol', 'pyolg', 'pyolm', 'pyolb', 'pyols', 'pyolt', 'pyolp', 'pyolh', 'pyom', 'pyob', 'pyobs', 'pyos', + 0x70 => 'pyoss', 'pyong', 'pyoj', 'pyoc', 'pyok', 'pyot', 'pyop', 'pyoh', 'pu', 'pug', 'pugg', 'pugs', 'pun', 'punj', 'punh', 'pud', + 0x80 => 'pul', 'pulg', 'pulm', 'pulb', 'puls', 'pult', 'pulp', 'pulh', 'pum', 'pub', 'pubs', 'pus', 'puss', 'pung', 'puj', 'puc', + 0x90 => 'puk', 'put', 'pup', 'puh', 'pweo', 'pweog', 'pweogg', 'pweogs', 'pweon', 'pweonj', 'pweonh', 'pweod', 'pweol', 'pweolg', 'pweolm', 'pweolb', + 0xA0 => 'pweols', 'pweolt', 'pweolp', 'pweolh', 'pweom', 'pweob', 'pweobs', 'pweos', 'pweoss', 'pweong', 'pweoj', 'pweoc', 'pweok', 'pweot', 'pweop', 'pweoh', + 0xB0 => 'pwe', 'pweg', 'pwegg', 'pwegs', 'pwen', 'pwenj', 'pwenh', 'pwed', 'pwel', 'pwelg', 'pwelm', 'pwelb', 'pwels', 'pwelt', 'pwelp', 'pwelh', + 0xC0 => 'pwem', 'pweb', 'pwebs', 'pwes', 'pwess', 'pweng', 'pwej', 'pwec', 'pwek', 'pwet', 'pwep', 'pweh', 'pwi', 'pwig', 'pwigg', 'pwigs', + 0xD0 => 'pwin', 'pwinj', 'pwinh', 'pwid', 'pwil', 'pwilg', 'pwilm', 'pwilb', 'pwils', 'pwilt', 'pwilp', 'pwilh', 'pwim', 'pwib', 'pwibs', 'pwis', + 0xE0 => 'pwiss', 'pwing', 'pwij', 'pwic', 'pwik', 'pwit', 'pwip', 'pwih', 'pyu', 'pyug', 'pyugg', 'pyugs', 'pyun', 'pyunj', 'pyunh', 'pyud', + 0xF0 => 'pyul', 'pyulg', 'pyulm', 'pyulb', 'pyuls', 'pyult', 'pyulp', 'pyulh', 'pyum', 'pyub', 'pyubs', 'pyus', 'pyuss', 'pyung', 'pyuj', 'pyuc', +]; diff --git a/resources/transliteration-data/xd5.php b/resources/transliteration-data/xd5.php new file mode 100644 index 000000000..bba87bf9a --- /dev/null +++ b/resources/transliteration-data/xd5.php @@ -0,0 +1,20 @@ + 'pyuk', 'pyut', 'pyup', 'pyuh', 'peu', 'peug', 'peugg', 'peugs', 'peun', 'peunj', 'peunh', 'peud', 'peul', 'peulg', 'peulm', 'peulb', + 0x10 => 'peuls', 'peult', 'peulp', 'peulh', 'peum', 'peub', 'peubs', 'peus', 'peuss', 'peung', 'peuj', 'peuc', 'peuk', 'peut', 'peup', 'peuh', + 0x20 => 'pyi', 'pyig', 'pyigg', 'pyigs', 'pyin', 'pyinj', 'pyinh', 'pyid', 'pyil', 'pyilg', 'pyilm', 'pyilb', 'pyils', 'pyilt', 'pyilp', 'pyilh', + 0x30 => 'pyim', 'pyib', 'pyibs', 'pyis', 'pyiss', 'pying', 'pyij', 'pyic', 'pyik', 'pyit', 'pyip', 'pyih', 'pi', 'pig', 'pigg', 'pigs', + 0x40 => 'pin', 'pinj', 'pinh', 'pid', 'pil', 'pilg', 'pilm', 'pilb', 'pils', 'pilt', 'pilp', 'pilh', 'pim', 'pib', 'pibs', 'pis', + 0x50 => 'piss', 'ping', 'pij', 'pic', 'pik', 'pit', 'pip', 'pih', 'ha', 'hag', 'hagg', 'hags', 'han', 'hanj', 'hanh', 'had', + 0x60 => 'hal', 'halg', 'halm', 'halb', 'hals', 'halt', 'halp', 'halh', 'ham', 'hab', 'habs', 'has', 'hass', 'hang', 'haj', 'hac', + 0x70 => 'hak', 'hat', 'hap', 'hah', 'hae', 'haeg', 'haegg', 'haegs', 'haen', 'haenj', 'haenh', 'haed', 'hael', 'haelg', 'haelm', 'haelb', + 0x80 => 'haels', 'haelt', 'haelp', 'haelh', 'haem', 'haeb', 'haebs', 'haes', 'haess', 'haeng', 'haej', 'haec', 'haek', 'haet', 'haep', 'haeh', + 0x90 => 'hya', 'hyag', 'hyagg', 'hyags', 'hyan', 'hyanj', 'hyanh', 'hyad', 'hyal', 'hyalg', 'hyalm', 'hyalb', 'hyals', 'hyalt', 'hyalp', 'hyalh', + 0xA0 => 'hyam', 'hyab', 'hyabs', 'hyas', 'hyass', 'hyang', 'hyaj', 'hyac', 'hyak', 'hyat', 'hyap', 'hyah', 'hyae', 'hyaeg', 'hyaegg', 'hyaegs', + 0xB0 => 'hyaen', 'hyaenj', 'hyaenh', 'hyaed', 'hyael', 'hyaelg', 'hyaelm', 'hyaelb', 'hyaels', 'hyaelt', 'hyaelp', 'hyaelh', 'hyaem', 'hyaeb', 'hyaebs', 'hyaes', + 0xC0 => 'hyaess', 'hyaeng', 'hyaej', 'hyaec', 'hyaek', 'hyaet', 'hyaep', 'hyaeh', 'heo', 'heog', 'heogg', 'heogs', 'heon', 'heonj', 'heonh', 'heod', + 0xD0 => 'heol', 'heolg', 'heolm', 'heolb', 'heols', 'heolt', 'heolp', 'heolh', 'heom', 'heob', 'heobs', 'heos', 'heoss', 'heong', 'heoj', 'heoc', + 0xE0 => 'heok', 'heot', 'heop', 'heoh', 'he', 'heg', 'hegg', 'hegs', 'hen', 'henj', 'henh', 'hed', 'hel', 'helg', 'helm', 'helb', + 0xF0 => 'hels', 'helt', 'help', 'helh', 'hem', 'heb', 'hebs', 'hes', 'hess', 'heng', 'hej', 'hec', 'hek', 'het', 'hep', 'heh', +]; diff --git a/resources/transliteration-data/xd6.php b/resources/transliteration-data/xd6.php new file mode 100644 index 000000000..8eafde7b3 --- /dev/null +++ b/resources/transliteration-data/xd6.php @@ -0,0 +1,20 @@ + 'hyeo', 'hyeog', 'hyeogg', 'hyeogs', 'hyeon', 'hyeonj', 'hyeonh', 'hyeod', 'hyeol', 'hyeolg', 'hyeolm', 'hyeolb', 'hyeols', 'hyeolt', 'hyeolp', 'hyeolh', + 0x10 => 'hyeom', 'hyeob', 'hyeobs', 'hyeos', 'hyeoss', 'hyeong', 'hyeoj', 'hyeoc', 'hyeok', 'hyeot', 'hyeop', 'hyeoh', 'hye', 'hyeg', 'hyegg', 'hyegs', + 0x20 => 'hyen', 'hyenj', 'hyenh', 'hyed', 'hyel', 'hyelg', 'hyelm', 'hyelb', 'hyels', 'hyelt', 'hyelp', 'hyelh', 'hyem', 'hyeb', 'hyebs', 'hyes', + 0x30 => 'hyess', 'hyeng', 'hyej', 'hyec', 'hyek', 'hyet', 'hyep', 'hyeh', 'ho', 'hog', 'hogg', 'hogs', 'hon', 'honj', 'honh', 'hod', + 0x40 => 'hol', 'holg', 'holm', 'holb', 'hols', 'holt', 'holp', 'holh', 'hom', 'hob', 'hobs', 'hos', 'hoss', 'hong', 'hoj', 'hoc', + 0x50 => 'hok', 'hot', 'hop', 'hoh', 'hwa', 'hwag', 'hwagg', 'hwags', 'hwan', 'hwanj', 'hwanh', 'hwad', 'hwal', 'hwalg', 'hwalm', 'hwalb', + 0x60 => 'hwals', 'hwalt', 'hwalp', 'hwalh', 'hwam', 'hwab', 'hwabs', 'hwas', 'hwass', 'hwang', 'hwaj', 'hwac', 'hwak', 'hwat', 'hwap', 'hwah', + 0x70 => 'hwae', 'hwaeg', 'hwaegg', 'hwaegs', 'hwaen', 'hwaenj', 'hwaenh', 'hwaed', 'hwael', 'hwaelg', 'hwaelm', 'hwaelb', 'hwaels', 'hwaelt', 'hwaelp', 'hwaelh', + 0x80 => 'hwaem', 'hwaeb', 'hwaebs', 'hwaes', 'hwaess', 'hwaeng', 'hwaej', 'hwaec', 'hwaek', 'hwaet', 'hwaep', 'hwaeh', 'hoe', 'hoeg', 'hoegg', 'hoegs', + 0x90 => 'hoen', 'hoenj', 'hoenh', 'hoed', 'hoel', 'hoelg', 'hoelm', 'hoelb', 'hoels', 'hoelt', 'hoelp', 'hoelh', 'hoem', 'hoeb', 'hoebs', 'hoes', + 0xA0 => 'hoess', 'hoeng', 'hoej', 'hoec', 'hoek', 'hoet', 'hoep', 'hoeh', 'hyo', 'hyog', 'hyogg', 'hyogs', 'hyon', 'hyonj', 'hyonh', 'hyod', + 0xB0 => 'hyol', 'hyolg', 'hyolm', 'hyolb', 'hyols', 'hyolt', 'hyolp', 'hyolh', 'hyom', 'hyob', 'hyobs', 'hyos', 'hyoss', 'hyong', 'hyoj', 'hyoc', + 0xC0 => 'hyok', 'hyot', 'hyop', 'hyoh', 'hu', 'hug', 'hugg', 'hugs', 'hun', 'hunj', 'hunh', 'hud', 'hul', 'hulg', 'hulm', 'hulb', + 0xD0 => 'huls', 'hult', 'hulp', 'hulh', 'hum', 'hub', 'hubs', 'hus', 'huss', 'hung', 'huj', 'huc', 'huk', 'hut', 'hup', 'huh', + 0xE0 => 'hweo', 'hweog', 'hweogg', 'hweogs', 'hweon', 'hweonj', 'hweonh', 'hweod', 'hweol', 'hweolg', 'hweolm', 'hweolb', 'hweols', 'hweolt', 'hweolp', 'hweolh', + 0xF0 => 'hweom', 'hweob', 'hweobs', 'hweos', 'hweoss', 'hweong', 'hweoj', 'hweoc', 'hweok', 'hweot', 'hweop', 'hweoh', 'hwe', 'hweg', 'hwegg', 'hwegs', +]; diff --git a/resources/transliteration-data/xd7.php b/resources/transliteration-data/xd7.php new file mode 100644 index 000000000..d3b5c513e --- /dev/null +++ b/resources/transliteration-data/xd7.php @@ -0,0 +1,20 @@ + 'hwen', 'hwenj', 'hwenh', 'hwed', 'hwel', 'hwelg', 'hwelm', 'hwelb', 'hwels', 'hwelt', 'hwelp', 'hwelh', 'hwem', 'hweb', 'hwebs', 'hwes', + 0x10 => 'hwess', 'hweng', 'hwej', 'hwec', 'hwek', 'hwet', 'hwep', 'hweh', 'hwi', 'hwig', 'hwigg', 'hwigs', 'hwin', 'hwinj', 'hwinh', 'hwid', + 0x20 => 'hwil', 'hwilg', 'hwilm', 'hwilb', 'hwils', 'hwilt', 'hwilp', 'hwilh', 'hwim', 'hwib', 'hwibs', 'hwis', 'hwiss', 'hwing', 'hwij', 'hwic', + 0x30 => 'hwik', 'hwit', 'hwip', 'hwih', 'hyu', 'hyug', 'hyugg', 'hyugs', 'hyun', 'hyunj', 'hyunh', 'hyud', 'hyul', 'hyulg', 'hyulm', 'hyulb', + 0x40 => 'hyuls', 'hyult', 'hyulp', 'hyulh', 'hyum', 'hyub', 'hyubs', 'hyus', 'hyuss', 'hyung', 'hyuj', 'hyuc', 'hyuk', 'hyut', 'hyup', 'hyuh', + 0x50 => 'heu', 'heug', 'heugg', 'heugs', 'heun', 'heunj', 'heunh', 'heud', 'heul', 'heulg', 'heulm', 'heulb', 'heuls', 'heult', 'heulp', 'heulh', + 0x60 => 'heum', 'heub', 'heubs', 'heus', 'heuss', 'heung', 'heuj', 'heuc', 'heuk', 'heut', 'heup', 'heuh', 'hyi', 'hyig', 'hyigg', 'hyigs', + 0x70 => 'hyin', 'hyinj', 'hyinh', 'hyid', 'hyil', 'hyilg', 'hyilm', 'hyilb', 'hyils', 'hyilt', 'hyilp', 'hyilh', 'hyim', 'hyib', 'hyibs', 'hyis', + 0x80 => 'hyiss', 'hying', 'hyij', 'hyic', 'hyik', 'hyit', 'hyip', 'hyih', 'hi', 'hig', 'higg', 'higs', 'hin', 'hinj', 'hinh', 'hid', + 0x90 => 'hil', 'hilg', 'hilm', 'hilb', 'hils', 'hilt', 'hilp', 'hilh', 'him', 'hib', 'hibs', 'his', 'hiss', 'hing', 'hij', 'hic', + 0xA0 => 'hik', 'hit', 'hip', 'hih', null, null, null, null, null, null, null, null, null, null, null, null, + 0xB0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0xC0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0xD0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0xE0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0xF0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, +]; diff --git a/resources/transliteration-data/xf9.php b/resources/transliteration-data/xf9.php new file mode 100644 index 000000000..0a3026317 --- /dev/null +++ b/resources/transliteration-data/xf9.php @@ -0,0 +1,20 @@ + 'Kay ', 'Kayng ', 'Ke ', 'Ko ', 'Kol ', 'Koc ', 'Kwi ', 'Kwi ', 'Kyun ', 'Kul ', 'Kum ', 'Na ', 'Na ', 'Na ', 'La ', 'Na ', + 0x10 => 'Na ', 'Na ', 'Na ', 'Na ', 'Nak ', 'Nak ', 'Nak ', 'Nak ', 'Nak ', 'Nak ', 'Nak ', 'Nan ', 'Nan ', 'Nan ', 'Nan ', 'Nan ', + 0x20 => 'Nan ', 'Nam ', 'Nam ', 'Nam ', 'Nam ', 'Nap ', 'Nap ', 'Nap ', 'Nang ', 'Nang ', 'Nang ', 'Nang ', 'Nang ', 'Nay ', 'Nayng ', 'No ', + 0x30 => 'No ', 'No ', 'No ', 'No ', 'No ', 'No ', 'No ', 'No ', 'No ', 'No ', 'No ', 'Nok ', 'Nok ', 'Nok ', 'Nok ', 'Nok ', + 0x40 => 'Nok ', 'Non ', 'Nong ', 'Nong ', 'Nong ', 'Nong ', 'Noy ', 'Noy ', 'Noy ', 'Noy ', 'Nwu ', 'Nwu ', 'Nwu ', 'Nwu ', 'Nwu ', 'Nwu ', + 0x50 => 'Nwu ', 'Nwu ', 'Nuk ', 'Nuk ', 'Num ', 'Nung ', 'Nung ', 'Nung ', 'Nung ', 'Nung ', 'Twu ', 'La ', 'Lak ', 'Lak ', 'Lan ', 'Lyeng ', + 0x60 => 'Lo ', 'Lyul ', 'Li ', 'Pey ', 'Pen ', 'Pyen ', 'Pwu ', 'Pwul ', 'Pi ', 'Sak ', 'Sak ', 'Sam ', 'Sayk ', 'Sayng ', 'Sep ', 'Sey ', + 0x70 => 'Sway ', 'Sin ', 'Sim ', 'Sip ', 'Ya ', 'Yak ', 'Yak ', 'Yang ', 'Yang ', 'Yang ', 'Yang ', 'Yang ', 'Yang ', 'Yang ', 'Yang ', 'Ye ', + 0x80 => 'Ye ', 'Ye ', 'Ye ', 'Ye ', 'Ye ', 'Ye ', 'Ye ', 'Ye ', 'Ye ', 'Ye ', 'Yek ', 'Yek ', 'Yek ', 'Yek ', 'Yen ', 'Yen ', + 0x90 => 'Yen ', 'Yen ', 'Yen ', 'Yen ', 'Yen ', 'Yen ', 'Yen ', 'Yen ', 'Yen ', 'Yen ', 'Yen ', 'Yen ', 'Yel ', 'Yel ', 'Yel ', 'Yel ', + 0xA0 => 'Yel ', 'Yel ', 'Yem ', 'Yem ', 'Yem ', 'Yem ', 'Yem ', 'Yep ', 'Yeng ', 'Yeng ', 'Yeng ', 'Yeng ', 'Yeng ', 'Yeng ', 'Yeng ', 'Yeng ', + 0xB0 => 'Yeng ', 'Yeng ', 'Yeng ', 'Yeng ', 'Yeng ', 'Yey ', 'Yey ', 'Yey ', 'Yey ', 'O ', 'Yo ', 'Yo ', 'Yo ', 'Yo ', 'Yo ', 'Yo ', + 0xC0 => 'Yo ', 'Yo ', 'Yo ', 'Yo ', 'Yong ', 'Wun ', 'Wen ', 'Yu ', 'Yu ', 'Yu ', 'Yu ', 'Yu ', 'Yu ', 'Yu ', 'Yu ', 'Yu ', + 0xD0 => 'Yu ', 'Yuk ', 'Yuk ', 'Yuk ', 'Yun ', 'Yun ', 'Yun ', 'Yun ', 'Yul ', 'Yul ', 'Yul ', 'Yul ', 'Yung ', 'I ', 'I ', 'I ', + 0xE0 => 'I ', 'I ', 'I ', 'I ', 'I ', 'I ', 'I ', 'I ', 'I ', 'I ', 'I ', 'Ik ', 'Ik ', 'In ', 'In ', 'In ', + 0xF0 => 'In ', 'In ', 'In ', 'In ', 'Im ', 'Im ', 'Im ', 'Ip ', 'Ip ', 'Ip ', 'Cang ', 'Cek ', 'Ci ', 'Cip ', 'Cha ', 'Chek ', +]; diff --git a/resources/transliteration-data/xfa.php b/resources/transliteration-data/xfa.php new file mode 100644 index 000000000..3e5e8c30a --- /dev/null +++ b/resources/transliteration-data/xfa.php @@ -0,0 +1,20 @@ + 'Chey ', 'Thak ', 'Thak ', 'Thang ', 'Thayk ', 'Thong ', 'Pho ', 'Phok ', 'Hang ', 'Hang ', 'Hyen ', 'Hwak ', 'Wu ', 'Huo ', null, null, + 0x10 => 'Zhong ', null, 'Qing ', null, null, 'Xi ', 'Zhu ', 'Yi ', 'Li ', 'Shen ', 'Xiang ', 'Fu ', 'Jing ', 'Jing ', 'Yu ', null, + 0x20 => 'Hagi ', null, 'Zhu ', null, null, 'Yi ', 'Du ', null, null, null, 'Fan ', 'Si ', 'Guan ', null, null, null, + 0x30 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0x40 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0x50 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0x60 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0x70 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0x80 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0x90 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0xA0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0xB0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0xC0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0xD0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0xE0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0xF0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, +]; diff --git a/resources/transliteration-data/xfb.php b/resources/transliteration-data/xfb.php new file mode 100644 index 000000000..f9b490080 --- /dev/null +++ b/resources/transliteration-data/xfb.php @@ -0,0 +1,20 @@ + 'ff', 'fi', 'fl', 'ffi', 'ffl', 'st', 'st', null, null, null, null, null, null, null, null, null, + 0x10 => null, null, null, 'mn', 'me', 'mi', 'vn', 'mkh', null, null, null, null, null, 'yi', '', 'ay', + 0x20 => '`', '', 'd', 'h', 'k', 'l', 'm', 'm', 't', '+', 'sh', 's', 'sh', 's', 'a', 'a', + 0x30 => '', 'b', 'g', 'd', 'h', 'v', 'z', null, 't', 'y', 'k', 'k', 'l', null, 'l', null, + 0x40 => 'n', 'n', null, 'p', 'p', null, 'ts', 'ts', 'r', 'sh', 't', 'vo', 'b', 'k', 'p', 'l', + 0x50 => '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 0x60 => '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 0x70 => '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 0x80 => '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 0x90 => '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 0xA0 => '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 0xB0 => '', '', null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0xC0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0xD0 => null, null, null, '', '', '', '', '', '', '', '', '', '', '', '', '', + 0xE0 => '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 0xF0 => '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', +]; diff --git a/resources/transliteration-data/xfc.php b/resources/transliteration-data/xfc.php new file mode 100644 index 000000000..fbef1dc70 --- /dev/null +++ b/resources/transliteration-data/xfc.php @@ -0,0 +1,20 @@ + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 0x10 => '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 0x20 => '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 0x30 => '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 0x40 => '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 0x50 => '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 0x60 => '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 0x70 => '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 0x80 => '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 0x90 => '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 0xA0 => '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 0xB0 => '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 0xC0 => '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 0xD0 => '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 0xE0 => '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 0xF0 => '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', +]; diff --git a/resources/transliteration-data/xfd.php b/resources/transliteration-data/xfd.php new file mode 100644 index 000000000..e865886c8 --- /dev/null +++ b/resources/transliteration-data/xfd.php @@ -0,0 +1,20 @@ + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 0x10 => '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 0x20 => '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 0x30 => '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 0x40 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0x50 => '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 0x60 => '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 0x70 => '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 0x80 => '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 0x90 => null, null, '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 0xA0 => '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 0xB0 => '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 0xC0 => '', '', '', '', '', '', '', '', null, null, null, null, null, null, null, null, + 0xD0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0xE0 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0xF0 => '', '', '', '', '', '', '', '', '', '', '', '', null, null, null, null, +]; diff --git a/resources/transliteration-data/xfe.php b/resources/transliteration-data/xfe.php new file mode 100644 index 000000000..6a59f6104 --- /dev/null +++ b/resources/transliteration-data/xfe.php @@ -0,0 +1,20 @@ + null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0x10 => null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + 0x20 => '', '', '', '~', null, null, null, null, null, null, null, null, null, null, null, null, + 0x30 => '..', '--', '-', '_', '_', '(', ') ', '{', '} ', '[', '] ', '[(', ')] ', '<<', '>> ', '<', + 0x40 => '> ', '[', '] ', '{', '}', null, null, null, null, '', '', '', '', '', '', '', + 0x50 => ',', ',', '.', '', ';', ':', '?', '!', '-', '(', ')', '{', '}', '{', '}', '#', + 0x60 => '&', '*', '+', '-', '<', '>', '=', '', '\\', '$', '%', '@', null, null, null, null, + 0x70 => '', '', '', null, '', null, '', '', '', '', '', '', '', '', '', '', + 0x80 => '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 0x90 => '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 0xA0 => '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 0xB0 => '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 0xC0 => '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 0xD0 => '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 0xE0 => '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 0xF0 => '', '', '', '', '', '', '', '', '', '', '', '', '', null, null, '', +]; diff --git a/resources/transliteration-data/xff.php b/resources/transliteration-data/xff.php new file mode 100644 index 000000000..75f2bd7ed --- /dev/null +++ b/resources/transliteration-data/xff.php @@ -0,0 +1,20 @@ + null, '!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/', + 0x10 => '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?', + 0x20 => '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', + 0x30 => 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^', '_', + 0x40 => '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', + 0x50 => 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~', null, + 0x60 => null, '.', '[', ']', ',', '*', 'wo', 'a', 'i', 'u', 'e', 'o', 'ya', 'yu', 'yo', 'tu', + 0x70 => '+', 'a', 'i', 'u', 'e', 'o', 'ka', 'ki', 'ku', 'ke', 'ko', 'sa', 'si', 'su', 'se', 'so', + 0x80 => 'ta', 'ti', 'tu', 'te', 'to', 'na', 'ni', 'nu', 'ne', 'no', 'ha', 'hi', 'hu', 'he', 'ho', 'ma', + 0x90 => 'mi', 'mu', 'me', 'mo', 'ya', 'yu', 'yo', 'ra', 'ri', 'ru', 're', 'ro', 'wa', 'n', ':', ';', + 0xA0 => '', 'g', 'gg', 'gs', 'n', 'nj', 'nh', 'd', 'dd', 'r', 'lg', 'lm', 'lb', 'ls', 'lt', 'lp', + 0xB0 => 'rh', 'm', 'b', 'bb', 'bs', 's', 'ss', '', 'j', 'jj', 'c', 'k', 't', 'p', 'h', null, + 0xC0 => null, null, 'a', 'ae', 'ya', 'yae', 'eo', 'e', null, null, 'yeo', 'ye', 'o', 'wa', 'wae', 'oe', + 0xD0 => null, null, 'yo', 'u', 'weo', 'we', 'wi', 'yu', null, null, 'eu', 'yi', 'i', null, null, null, + 0xE0 => '/C', 'PS', '!', '-', '|', 'Y=', 'W=', null, '|', '-', '|', '-', '|', '#', 'O', null, + 0xF0 => null, null, null, null, null, null, null, null, null, '{', '|', '}', '', '', '', '', +]; diff --git a/sendtomail.php b/sendtomail.php new file mode 100644 index 000000000..533b076b4 --- /dev/null +++ b/sendtomail.php @@ -0,0 +1,110 @@ +getDataById($idData); + +if (filesize($data->getLocalPath()) > 10 * 1024 * 1024) { + echo 'Attachment too big'; + exit; +} + +$mail = new PHPMailer(); + +$mail->IsSMTP(); +$mail->Timeout = 30; // 30 seconds as some files can be big +$mail->Host = $config['cops_mail_configuration']["smtp.host"]; +if (!empty($config['cops_mail_configuration']["smtp.secure"])) { + $mail->SMTPSecure = $config['cops_mail_configuration']["smtp.secure"]; + $mail->Port = 465; +} +$mail->SMTPAuth = !empty($config['cops_mail_configuration']["smtp.username"]); +if (!empty($config['cops_mail_configuration']["smtp.username"])) { + $mail->Username = $config['cops_mail_configuration']["smtp.username"]; +} +if (!empty($config['cops_mail_configuration']["smtp.password"])) { + $mail->Password = $config['cops_mail_configuration']["smtp.password"]; +} +if (!empty($config['cops_mail_configuration']["smtp.secure"])) { + $mail->SMTPSecure = $config['cops_mail_configuration']["smtp.secure"]; +} +if (!empty($config['cops_mail_configuration']["smtp.port"])) { + $mail->Port = $config['cops_mail_configuration']["smtp.port"]; +} + +$mail->From = $config['cops_mail_configuration']["address.from"]; +$mail->FromName = $config['cops_title_default']; + +foreach (explode(";", $emailDest) as $emailAddress) { + if (empty($emailAddress)) { + continue; + } + $mail->AddAddress($emailAddress); +} + +$mail->AddAttachment($data->getLocalPath()); + +$mail->IsHTML(true); +$mail->CharSet = "UTF-8"; +$mail->Subject = 'Sent by COPS : '; +if (!empty($config['cops_mail_configuration']["subject"])) { + $mail->Subject = $config['cops_mail_configuration']["subject"]; +} +$mail->Subject .= $data->getUpdatedFilename(); +$mail->Body = "

    " . $book->title . "

    " . $book->getAuthorsName() . "

    " . $book->getComment(); +$mail->AltBody = "Sent by COPS"; + +if (!$mail->Send()) { + echo localize("mail.messagenotsent"); + echo 'Mailer Error: ' . $mail->ErrorInfo; + exit; +} + +echo localize("mail.messagesent"); diff --git a/serie.php b/serie.php deleted file mode 100644 index 33287f853..000000000 --- a/serie.php +++ /dev/null @@ -1,75 +0,0 @@ - - */ - -require_once('base.php'); - -class Serie extends Base { - const ALL_SERIES_ID = "calibre:series"; - - public $id; - public $name; - - public function __construct($pid, $pname) { - $this->id = $pid; - $this->name = $pname; - } - - public function getUri () { - return "?page=".parent::PAGE_SERIE_DETAIL."&id=$this->id"; - } - - public function getEntryId () { - return self::ALL_SERIES_ID.":".$this->id; - } - - public static function getCount() { - $nSeries = parent::getDb ()->query('select count(*) from series')->fetchColumn(); - $entry = new Entry (localize("series.title"), self::ALL_SERIES_ID, - str_format (localize("series.alphabetical"), $nSeries), "text", - array ( new LinkNavigation ("?page=".parent::PAGE_ALL_SERIES))); - return $entry; - } - - public static function getSerieByBookId ($bookId) { - $result = parent::getDb ()->prepare('select series.id as id, name -from books_series_link, series -where series.id = series and book = ?'); - $result->execute (array ($bookId)); - if ($post = $result->fetchObject ()) { - return new Serie ($post->id, $post->name); - } - return NULL; - } - - public static function getSerieById ($serieId) { - $result = parent::getDb ()->prepare('select id, name from series where id = ?'); - $result->execute (array ($serieId)); - if ($post = $result->fetchObject ()) { - return new Serie ($post->id, $post->name); - } - return NULL; - } - - public static function getAllSeries() { - $result = parent::getDb ()->query('select series.id as id, series.name as name, series.sort as sort, count(*) as count -from series, books_series_link -where series.id = series -group by series.id, series.name, series.sort -order by series.sort'); - $entryArray = array(); - while ($post = $result->fetchObject ()) - { - $serie = new Serie ($post->id, $post->sort); - array_push ($entryArray, new Entry ($serie->name, $serie->getEntryId (), - str_format (localize("bookword", $post->count), $post->count), "text", - array ( new LinkNavigation ($serie->getUri ())))); - } - return $entryArray; - } -} -?> \ No newline at end of file diff --git a/style.css b/style.css deleted file mode 100644 index 12607dfc8..000000000 --- a/style.css +++ /dev/null @@ -1,272 +0,0 @@ -/* Global Box Sizing and Font-Smoothing */ -*, *:after, *:before { - box-sizing:border-box; - -webkit-box-sizing:border-box; - -moz-box-sizing:border-box; - -webkit-font-smoothing:antialiased; - -moz-font-smoothing:antialiased; - -o-font-smoothing:antialiased; - font-smoothing:antialiased; - text-rendering:optimizeLegibility; -} - -html { font-size: 100%; -webkit-text-size-adjust: 100%; - -ms-text-size-adjust: 100%; } - -body { - font-family: 'Open Sans', sans-serif; - line-height:18px; - color: #1c1c1c; /* Lighter on the eyes than #000 Black */ - margin: 0px; background: #cccccc; background-size: cover; -} - -img { - border: 0px; - max-width: 100%; - height: auto; - width: auto\9; /* ie8 */ -} - -/* ========================================================================== - Typography stuff goes here - ========================================================================== */ -h1,h2,h3,h4,h5,h6 { font-weight: bold; margin:0; padding:0;} -/*h1 see mediaqueries*/ -h2 {font-size: 1.2em;} -h3 {font-size: 1.1em;} -h4 {font-size: 1.0em; } -h5 {font-size: 0.83em;} -h6 {font-size: 0.75em;} - -a:hover, a:active { outline: none; } -a { color: #000066; font-weight: 800; text-decoration: none;} -a:visited { color:#414141 ; } -a:hover { color:#000; text-decoration: none; } -.frontpage a:hover { display:inline-block; width: 100%; background-color: #778899; /*Dirty IE Hack*/ zoom: 1; *display: inline;} -.link a:hover { display:inline-block; width: 100%; background-color: #778899; /*Dirty IE Hack*/ zoom: 1; *display: inline;} - -img -{ -margin:0; -padding:0; -border:0; -} - -/* ============================================================================= - Main container stuff goes here and other globals - ========================================================================== */ -.container{ - background: #414141; border:1px solid #000; border-radius:10px; - max-width:800px;width:95%;margin:0 auto;position:relative; } - -.fancyabout { font-weight:400; text-decoration: none; } - -/* ============================================================================= - Header stuff goes here - ========================================================================== */ -header { - clear:both; - color:white; - text-align:center; - text-transform:uppercase; - display:block; - box-shadow:inset 0px -5px 8px #000000; - min-height:70px; - border-radius: 10px 10px 0px 0px; -} - -.headleft { - float: left; -} - -header h1{ - float:none; - padding-top:25px; -text-shadow: 0px 4px 3px rgba(0,0,0,0.4), - 0px 8px 13px rgba(0,0,0,0.1), - 0px 18px 23px rgba(0,0,0,0.1); -} - -.headright { - float: right; -} - -/* ============================================================================= - Section and Article stuff goes here - ========================================================================== */ -section { -clear:both; -background-color: #fff; -} - -article { -border-bottom: 1px solid black; -max-width:800px; -} - -/*-------------frontpage article-------------*/ - -.frontpage h2 { - padding: 5px 0 0 5px; -} - -.frontpage h4 { - padding: 5px 0 5px 20px; - font-style: italic; -} - -/*-------------books article-------------*/ -.books { - clear: both; - padding: 10px; - min-height: 90px; -} - -.cover { - float:left; - margin: 0 10px 0 0; - min-width: 56px; - min-height: 70px; -} - -.download { - float: right; - line-height:40px; - text-align: right; -} - -.download a { - border-radius: 6px; - box-shadow:0 0 10px #000; - background: darkgray; - background: radial-gradient(#666, black); - color: #EEE; - text-decoration : none; - font-weight: bold; - padding: 5px 10px 5px 10px; -} - - -.books h4{ - display: inline; - font-style: italic; -} - -/*-------------books popup article-------------*/ -.bookpopup h2{ - margin: 15px 15px; -} - -.bookpopup h3{ - display:inline; /*Dirty IE Hack*/ zoom: 1; *display: inline; -} - -.bookpopup p{ - display:inline; /*Dirty IE Hack*/ zoom: 1; *display: inline; -} - -.bookpopup h4{ - border-top: 1px solid black; -} - -.fullclickpopup{ - display: block; -} -/* ============================================================================= - Footer stuff goes here - ========================================================================== */ -footer -{ -clear:both; -box-shadow:inset 0px 5px 8px #000000; -border-radius: 0px 0px 10px 10px; -height:32px; -} - -footer a{ - float: right; -} -/* ============================================================================= - Aside stuff goes here - ========================================================================== */ -#tool -{ -color:white; -background: #414141; -width:100%; -height:32px; -overflow: hidden; -} - - -/*-------------Search Aside-------------*/ -#tool input[type=text] -{ -vertical-align: middle; -width: 100%; -margin: 5px; -} - -.stop select -{ -vertical-align: middle; -margin: 5px; -} - -#sort -{ -cursor:pointer; -} - -.stop -{ -display: block; -overflow: hidden; -} - -#loading -{ -display:none; -position:fixed; -left:0; -top:0; -width:100%; -height:100%; -background-color: #ccc; -filter: alpha(opacity=70); -opacity: 0.70; -text-align: center; -padding-top: 120px; -} - -/* ============================================================================= - Mediaquerie stuff goes here - ========================================================================== */ -/* 100px and greater */ -@media only screen and (min-width: 100px) { -h1 {font-size: 1em;} -.container { width:100%; } -} - -/* 320px and greater */ -@media only screen and (min-width: 320px) { -h1 {font-size: 1.2em;} -} - -/* 480px and greater */ -@media only screen and (min-width: 480px) { -h1 {font-size: 1.5em;} -body { font-size: 1em;/*12px/16px */ - font-weight:450; /* Better supported than 'lighter' attribute */ - } -} - -/* 810px and greater */ -@media only screen and (min-width: 768px) { -h1 {font-size: 2em;} -.container { box-shadow:0 0 20px #000; } -body { margin: 5px; - font-size: 0.85em;/*12px/16px */ - font-weight:400; /* Better supported than 'lighter' attribute */ - } -} \ No newline at end of file diff --git a/styles/cops-monocle.css b/styles/cops-monocle.css new file mode 100644 index 000000000..d9592c92c --- /dev/null +++ b/styles/cops-monocle.css @@ -0,0 +1,273 @@ +body { + margin: 0; + padding: 0; + background: #000; + -webkit-user-select: none; + -webkit-text-size-adjust: none; +} + +#components { + display: none; +} + +#reader, #readerBg { + position: absolute; + width: 100%; + height: 100%; +} + +#reader div pre { + white-space: normal; + font: normal 100% serif; +} + +/* from smallest and outermost to largest and innermost */ +.dummyPage { + position: absolute; + left: 0; + top: 20px; + bottom: 20px; + right: 15px; + background-color: #FCF6F0; + -webkit-box-shadow: 2px 2px 4px #754; + -moz-box-shadow: 2px 2px 4px #754; + box-shadow: 2px 2px 4px #754; + -webkit-border-top-left-radius: 26px 6px; + -webkit-border-bottom-left-radius: 26px 6px; + -moz-border-top-left-radius: 26px 6px; + -moz-border-bottom-left-radius: 26px 6px; + border-top-left-radius: 26px 6px; + border-bottom-left-radius: 26px 6px; +} +.dummyPage + .dummyPage { + top: 16px; + bottom: 16px; + right: 16px; + -webkit-box-shadow: 1px 0 2px #A99; + -moz-box-shadow: 1px 0 2px #A99; + box-shadow: 1px 0 2px #A99; +} +.dummyPage + .dummyPage + .dummyPage { + top: 13px; + bottom: 13px; + right: 18px; + background-color: #FFF9F4; +} +.dummyPage + .dummyPage + .dummyPage + .dummyPage { + top: 10px; + bottom: 10px; + right: 21px; +} +.dummyPage + .dummyPage + .dummyPage + .dummyPage + .dummyPage { + top: 8px; + bottom: 8px; + right: 25px; +} +.jacket { + position: absolute; + top: 1px; + bottom: 1px; + right: 3px; + left: 65%; + -webkit-box-shadow: -3px 0 3px #311; + -moz-box-shadow: -3px 0 3px #311; + box-shadow: -3px 0 3px #311; + -webkit-border-top-right-radius: 3px; + -webkit-border-bottom-right-radius: 3px; + -moz-border-top-right-radius: 3px; + -moz-border-bottom-right-radius: 3px; + border-top-right-radius: 3px; + border-bottom-right-radius: 3px; + background-color: #F7F7F7; + background: -webkit-linear-gradient(0deg, #DDD, #FFF); + background: -moz-linear-gradient(0deg , #DDD, #FFF); + background: linear-gradient(90deg, #DDD, #FFF); +} +.board { + position: absolute; + top: 1px; + bottom: 1px; + width: 90%; + background-color: #974; + border: 1px solid #852; +} + +.runner { + color: #542; + text-transform: uppercase; + font-size: 82%; +} + +.pageNumber, .bookTitle, .chapterTitle { + padding: 3% 2%; +} + +.bookTitle, .chapterTitle { + position: absolute; + top: 1%; + left: 6%; + cursor: pointer; + padding: 0; +} + +.chapterTitle { + top: auto; + bottom: 1%; + right: 20%; +} + +.pageNumber { + position: absolute; + bottom: 1%; + right: 8%; + padding-right: 0; +} + +#readerBg { + background-color: #000; +} + +#toc ul.root { + position: absolute; + top: 50px; + left: 8%; + max-height: 75%; + max-width: 80%; + background: #E0D3C0; + -webkit-box-shadow: 1px 2px 2px #652; + -moz-box-shadow: 1px 2px 2px #652; + -webkit-border-radius: 10px; + -moz-border-radius: 10px; + border-radius: 10px; + overflow-y: auto; + color: #432; + font: 11pt Georgia, serif; + text-shadow: 1px 1px #EEE6D0; + border: 1px solid #EED; + z-index: 9; +} + +.tocArrow { + position: absolute; + top: 40px; + left: 16%; + width: 20px; + height: 20px; + -webkit-transform: rotateZ(45deg); + background: #E0D3C0; + z-index: 8; +} + +#toc li { + list-style: none; + line-height: 220%; + padding-left: 1em; + padding-right: 2em; + border-bottom: 2px groove #FFF6E9; + cursor: pointer; +} + +#toc li span { + display: block; +} + +#toc ul li:last-child { + border-bottom: none; +} + +#toc ul { + margin: 0; + padding: 0; +} +#toc ul.root { + border-top: none; +} + + + +/* Overrides to core elements */ + +div.monelem_container { + background: none; + width: auto; +} + +div.monelem_page { + top: 6px; + bottom: 6px; + right: 4px; + border-color: #CBA; + outline: none; + -webkit-box-shadow: 1px 0 1px #CBA; + -moz-box-shadow: 1px 0 1px #CBA; + box-shadow: 1px 0 2px #CBA; + -webkit-border-top-left-radius: 26px 4px; + -webkit-border-bottom-left-radius: 26px 4px; + -moz-border-top-left-radius: 26px 4px; + -moz-border-bottom-left-radius: 26px 4px; + border-top-left-radius: 26px 4px; + border-bottom-left-radius: 26px 4px; + background-color: #FFFFFE; + background-image: -webkit-linear-gradient(0deg, #EDEAE8 0px, #FFFFFE 24px); + background-image: -moz-linear-gradient(0deg, #EDEAE8 0px, #FFFFFE 24px); + background-image: linear-gradient(90deg, #EDEAE8 0px, #FFFFFE 24px); +} + +div.monelem_sheaf { + left: 6%; + right: 8%; + top: 8%; + bottom: 8%; +} + + +/* Overriding magnifier button display */ + +div.monelem_controls_magnifier_button { + color: #632; + padding: 2%; + top: 1%; + right: 6%; +} + + +/* Overriding table of contents display */ + +div.monelem_controls_contents_container { + background: #E0D3C0; + border: 1px solid #EED; + font: 11pt Georgia, serif; + color: #432; + text-shadow: 1px 1px #FFF6E0; +} + +div.monelem_controls_contents_chapter { + border-bottom: 2px groove #FFF6E9; +} + +li.monelem_controls_contents_chapter_active { + text-shadow: -1px -1px #876; + background: #BA9; +} + + +/* Overriding the scrubber display */ +div.monelem_controls_scrubber_container { + left: 5.5%; + right: 9%; + bottom: 2%; + background: #FFFEFC; +} + +div.monelem_controls_scrubber_track { + border-color: #432; +} + +div.monelem_controls_scrubber_needle { + border-color: #432; + background: #E0D3C0; +} + +div.monelem_controls_scrubber_trail { + background: #E0D3C0; +} diff --git a/styles/cops-monocle.js b/styles/cops-monocle.js new file mode 100644 index 000000000..20af0f9d3 --- /dev/null +++ b/styles/cops-monocle.js @@ -0,0 +1,184 @@ +/** global: Monocle */ +Monocle.DEBUG = true; + +(function () { + + /** global: Monocle */ + Monocle.Styles.container.right = "24px"; + + // Initialize the reader element. + /** global: Monocle */ + Monocle.Events.listen( + window, + 'load', + function () { + var readerOptions = {}; + + /* PLACE SAVER */ + var bkTitle = bookData.getMetaData('title'); + var placeSaver = new Monocle.Controls.PlaceSaver(bkTitle); + readerOptions.place = placeSaver.savedPlace(); + readerOptions.panels = Monocle.Panels.Marginal; + readerOptions.stylesheet = "body { " + + "color: #210;" + + "font-family: Palatino, Georgia, serif;" + + "}"; + + /* Initialize the reader */ + window.reader = Monocle.Reader( + 'reader', + bookData, + readerOptions, + function(reader) { + reader.addControl(placeSaver, 'invisible'); + + /* SPINNER */ + /** global: Monocle */ + var spinner = Monocle.Controls.Spinner(reader); + reader.addControl(spinner, 'page', { hidden: true }); + spinner.listenForUsualDelays('reader'); + + /* Because the 'reader' element changes size on window resize, + * we should notify it of this event. */ + /** global: Monocle */ + Monocle.Events.listen( + window, + 'resize', + function () { window.reader.resized() } + ); + + /** global: Monocle */ + Monocle.Events.listen(window.top.document, 'keyup', function(evt) { + var eventCharCode = evt.charCode || evt.keyCode; + var dir = null; + var flipper = reader.Flipper; + if (eventCharCode == 33 || eventCharCode == 37) { // Page down or Left arrow + dir = -1; + } else if (eventCharCode == 34 || eventCharCode == 39 ) { // Page down or Right arrow + dir = 1; + } + if (dir) { + reader.moveTo({ direction: dir }); + evt.preventDefault(); + } + }); + + /* MAGNIFIER CONTROL */ + /** global: Monocle */ + var magnifier = new Monocle.Controls.Magnifier(reader); + reader.addControl(magnifier, 'page'); + + /* BOOK TITLE RUNNING HEAD */ + var bookTitle = {} + /** global: Monocle */ + bookTitle.contentsMenu = Monocle.Controls.Contents(reader); + reader.addControl(bookTitle.contentsMenu, 'popover', { hidden: true }); + bookTitle.createControlElements = function () { + var cntr = document.createElement('div'); + cntr.className = "bookTitle"; + var runner = document.createElement('div'); + runner.className = "runner"; + runner.innerHTML = reader.getBook().getMetaData('title'); + cntr.appendChild(runner); + + /** global: Monocle */ + Monocle.Events.listenForContact( + cntr, + { + start: function (evt) { + if (evt.preventDefault) { + evt.stopPropagation(); + evt.preventDefault(); + } else { + evt.returnValue = false; + } + reader.showControl(bookTitle.contentsMenu); + } + } + ); + + return cntr; + } + reader.addControl(bookTitle, 'page'); + + + /* CHAPTER TITLE RUNNING HEAD */ + var chapterTitle = { + runners: [], + createControlElements: function (page) { + var cntr = document.createElement('div'); + cntr.className = "chapterTitle"; + var runner = document.createElement('div'); + runner.className = "runner"; + cntr.appendChild(runner); + this.runners.push(runner); + this.update(page); + return cntr; + }, + update: function (page) { + var place = reader.getPlace(page); + if (place) { + this.runners[page.m.pageIndex].innerHTML = place.chapterTitle(); + } + } + } + reader.addControl(chapterTitle, 'page'); + reader.listen( + 'monocle:pagechange', + function (evt) { chapterTitle.update(evt.m.page); } + ); + + + /* PAGE NUMBER RUNNING HEAD */ + var pageNumber = { + runners: [], + createControlElements: function (page) { + var cntr = document.createElement('div'); + cntr.className = "pageNumber"; + var runner = document.createElement('div'); + runner.className = "runner"; + cntr.appendChild(runner); + this.runners.push(runner); + this.update(page, page.m.place.pageNumber()); + return cntr; + }, + update: function (page, pageNumber) { + if (pageNumber) { + this.runners[page.m.pageIndex].innerHTML = pageNumber; + } + } + } + reader.addControl(pageNumber, 'page'); + reader.listen( + 'monocle:pagechange', + function (evt) { + pageNumber.update(evt.m.page, evt.m.pageNumber); + } + ); + + /* Scrubber */ + /** global: Monocle */ + var scrubber = new Monocle.Controls.Scrubber(reader); + reader.addControl(scrubber, 'popover', { hidden: true }); + var showFn = function (evt) { + evt.stopPropagation(); + reader.showControl(scrubber); + scrubber.updateNeedles(); + } + for (var i = 0; i < chapterTitle.runners.length; ++i) { + /** global: Monocle */ + Monocle.Events.listenForContact( + chapterTitle.runners[i].parentNode, + { start: showFn } + ); + /** global: Monocle */ + Monocle.Events.listenForContact( + pageNumber.runners[i].parentNode, + { start: showFn } + ); + } + } + ); + } + ); +})(); diff --git a/tag.php b/tag.php deleted file mode 100644 index c45df2598..000000000 --- a/tag.php +++ /dev/null @@ -1,64 +0,0 @@ - - */ - -require_once('base.php'); - -class tag extends Base { - const ALL_TAGS_ID = "calibre:tags"; - - public $id; - public $name; - - public function __construct($pid, $pname) { - $this->id = $pid; - $this->name = $pname; - } - - public function getUri () { - return "?page=".parent::PAGE_TAG_DETAIL."&id=$this->id"; - } - - public function getEntryId () { - return self::ALL_TAGS_ID.":".$this->id; - } - - public static function getCount() { - $nTags = parent::getDb ()->query('select count(*) from tags')->fetchColumn(); - $entry = new Entry (localize("tags.title"), self::ALL_TAGS_ID, - str_format (localize("tags.alphabetical"), $nTags), "text", - array ( new LinkNavigation ("?page=".parent::PAGE_ALL_TAGS))); - return $entry; - } - - public static function getTagById ($tagId) { - $result = parent::getDb ()->prepare('select id, name from tags where id = ?'); - $result->execute (array ($tagId)); - if ($post = $result->fetchObject ()) { - return new Tag ($post->id, $post->name); - } - return NULL; - } - - public static function getAllTags() { - $result = parent::getDb ()->query('select tags.id as id, tags.name as name, count(*) as count -from tags, books_tags_link -where tags.id = tag -group by tags.id, tags.name -order by tags.name'); - $entryArray = array(); - while ($post = $result->fetchObject ()) - { - $tag = new Tag ($post->id, $post->name); - array_push ($entryArray, new Entry ($tag->name, $tag->getEntryId (), - str_format (localize("bookword", $post->count), $post->count), "text", - array ( new LinkNavigation ($tag->getUri ())))); - } - return $entryArray; - } -} -?> \ No newline at end of file diff --git a/templates/bootstrap/bookdetail.html b/templates/bootstrap/bookdetail.html new file mode 100644 index 000000000..09040e4b2 --- /dev/null +++ b/templates/bootstrap/bookdetail.html @@ -0,0 +1,76 @@ +
    + +
    +

    + {{=htmlspecialchars (it.title)}} +

    +

    {{=it.c.i18n.authorsTitle}}: + {{~it.book.authors:author:i}} + {{? i > 0}}, {{?}}{{=htmlspecialchars (author.name)}} + {{~}} +

    + {{? it.book.tagsName != ""}} +

    {{=it.c.i18n.tagsTitle}}: + {{~it.book.tags:tag:i}} + {{? i > 0}}, {{?}}{{=htmlspecialchars (tag.name)}} + {{~}} +

    + {{?}} + {{? it.book.seriesName != ""}} +

    {{=it.c.i18n.seriesTitle}} : {{=htmlspecialchars (it.book.seriesCompleteName)}}

    + {{?}} +
    +
    +
    + {{~it.book.datas:data:i}} + {{=data.format}} + + {{? data.mail == 1}} + + + {{?}} + {{? data.readerUrl != ""}} + + + {{?}} +
    + {{~}} +
    +
    +
    + +
    +
    + {{? it.book.publisherName != ""}} +

    +

    {{=it.c.i18n.publisherName}}:

    {{=htmlspecialchars (it.book.publisherName)}} +

    + {{?}} + {{? it.book.pubDate != ""}} +

    +

    {{=it.c.i18n.pubdateTitle}}:

    {{=it.book.pubDate}} +

    + {{?}} + {{? it.book.languagesName != ""}} +

    +

    {{=it.c.i18n.languagesTitle}}:

    {{=it.book.languagesName}} +

    + {{?}} + {{~it.book.customcolumns_preview :column:column_index}} +

    +

    {{=column.customColumnType.columnTitle}}:

    {{=column.htmlvalue}} +

    + {{~}} + {{? it.book.content != ""}} +
    +

    {{=it.c.i18n.contentTitle}}

    +
    {{=it.book.content}}
    + {{?}} +
    +
    diff --git a/templates/bootstrap/file.html b/templates/bootstrap/file.html new file mode 100644 index 000000000..0c7650c05 --- /dev/null +++ b/templates/bootstrap/file.html @@ -0,0 +1,150 @@ + + + + + + + + + + + + + + + {{=it.title}} + + + + +{{? it.server_side_rendering == 0}} + + + + + +{{?}} + + + + + + + + + + + + + + + + +{{? it.server_side_rendering == 0}} + +{{?}} + diff --git a/templates/bootstrap/footer.html b/templates/bootstrap/footer.html new file mode 100644 index 000000000..e69de29bb diff --git a/templates/bootstrap/header.html b/templates/bootstrap/header.html new file mode 100644 index 000000000..a52fa3b4f --- /dev/null +++ b/templates/bootstrap/header.html @@ -0,0 +1,29 @@ + diff --git a/templates/bootstrap/main.html b/templates/bootstrap/main.html new file mode 100644 index 000000000..d9c4091ea --- /dev/null +++ b/templates/bootstrap/main.html @@ -0,0 +1,73 @@ +
    +{{? it.page == 13 || it.page == 16}} + {{? it.page == 13}} + {{#def.bookdetail}} + {{??}} + {{= it.fullhtml}} + {{?}} +{{??}} +
    +
      +
    +
    +
    +{{~it.entries:entry:i}} + {{? it.containsBook == 0}} +
    +
    + +
    + {{=entry.number}} +
    +
    +
    + {{??}} +
    +
    + +
    +
    + {{? entry.book.hasCover == 1}} + + {{=it.c.i18n.coverAlt}} + + {{?}} +
    +
    {{=htmlspecialchars (entry.book.authorsName)}}
    + {{? entry.book.tagsName != ""}}
    {{=htmlspecialchars (entry.book.tagsName)}}
    {{?}} + {{? entry.book.seriesName != ""}}
    {{=htmlspecialchars (entry.book.seriesName)}} ({{=entry.book.seriesIndex}})
    {{?}} + {{~entry.book.customcolumns_list :column:column_index}} +
    {{=column.customColumnType.columnTitle}} : {{=column.htmlvalue}}
    + {{~}} + {{~entry.book.preferedData:data:j}} +
    + {{~}} +
    + {{~entry.book.preferedData:data:j}} +

    + {{=data.name}} + +

    + {{~}} +
    +
    +
    +
    + {{?}} +{{~}} +
    +{{?}} +{{? it.isPaginated == 1}} + +{{?}} +
    diff --git a/templates/bootstrap/page.html b/templates/bootstrap/page.html new file mode 100644 index 000000000..88139c888 --- /dev/null +++ b/templates/bootstrap/page.html @@ -0,0 +1,3 @@ +{{#def.header}} +{{#def.main}} +{{#def.footer}} diff --git a/templates/bootstrap/scripts/cops.js b/templates/bootstrap/scripts/cops.js new file mode 100644 index 000000000..3383895c0 --- /dev/null +++ b/templates/bootstrap/scripts/cops.js @@ -0,0 +1,4 @@ +function postRefresh() +{ + $('[data-toggle="tooltip"]').tooltip(); +} \ No newline at end of file diff --git a/templates/bootstrap/styles/style-base.css b/templates/bootstrap/styles/style-base.css new file mode 100644 index 000000000..4823668e1 --- /dev/null +++ b/templates/bootstrap/styles/style-base.css @@ -0,0 +1,3 @@ +.panel-body { padding: 5px; } + +.bottomright {position:absolute; bottom:0; margin-bottom:25px; right: 20px;} \ No newline at end of file diff --git a/templates/bootstrap/styles/style-default.css b/templates/bootstrap/styles/style-default.css new file mode 100644 index 000000000..4823668e1 --- /dev/null +++ b/templates/bootstrap/styles/style-default.css @@ -0,0 +1,3 @@ +.panel-body { padding: 5px; } + +.bottomright {position:absolute; bottom:0; margin-bottom:25px; right: 20px;} \ No newline at end of file diff --git a/templates/bootstrap/suggestion.html b/templates/bootstrap/suggestion.html new file mode 100644 index 000000000..1107dadee --- /dev/null +++ b/templates/bootstrap/suggestion.html @@ -0,0 +1 @@ +

    {{=it.title}}

    \ No newline at end of file diff --git a/templates/bootstrap2/bookdetail.html b/templates/bootstrap2/bookdetail.html new file mode 100644 index 000000000..b45cfbd20 --- /dev/null +++ b/templates/bootstrap2/bookdetail.html @@ -0,0 +1,91 @@ +
    +
    +
    + {{? it.book.hasCover == 1}} +
    + + {{=it.c.i18n.coverAlt}} + + {{?}} +
    +
    + +
    + {{~it.book.datas:data:i}} +
    + {{=data.format}} + {{? data.mail == 1}} + + + {{?}} + {{? data.readerUrl != ""}} + + + {{?}} +
    + {{~}} +
    + + +
    +

    {{=htmlspecialchars (it.title)}}

    +

    {{~it.book.authors:author:i}}{{? i > 0}}, {{?}}{{=htmlspecialchars (author.name)}}{{~}}

    + {{? it.book.seriesName != ""}} +

    {{=htmlspecialchars (it.book.seriesName)}} ({{=it.book.seriesIndex}})

    + {{?}} +
    + + +
    + + {{? it.book.languagesName != ""}} +

    + {{=it.c.i18n.languagesTitle}}: {{=it.book.languagesName}} +

    + {{?}} + + {{? it.book.identifiers != ""}} +
    +

    + + {{~it.book.identifiers:id:i}}{{=htmlspecialchars (id.name)}} {{~}} +

    +
    + {{?}} + + {{? it.book.tagsName != ""}} +
    + + {{~it.book.tags:tag:i}}{{=htmlspecialchars (tag.name)}} {{~}} +
    + {{?}} + + {{? it.book.publisherName != ""}} +

    +

    {{=it.c.i18n.publisherName}}: {{=htmlspecialchars (it.book.publisherName)}}

    +

    + {{?}} + {{? it.book.pubDate != ""}} +

    +

    {{=it.c.i18n.pubdateTitle}}: {{=it.book.pubDate}}

    +

    + {{?}} + {{~it.book.customcolumns_preview :column:column_index}} +

    +

    {{=column.customColumnType.columnTitle}}: {{=column.htmlvalue}}

    +

    + {{~}} + +
    + +
    + +
    +
    + {{? it.book.content != ""}} +
    +

    {{=it.c.i18n.contentTitle}}

    +
    {{=it.book.content}}
    + {{?}} +
    +
    diff --git a/templates/bootstrap2/file.html b/templates/bootstrap2/file.html new file mode 100644 index 000000000..3bf7bccf5 --- /dev/null +++ b/templates/bootstrap2/file.html @@ -0,0 +1,210 @@ + + + + + + + + + + + + + + + {{=it.title}} + + + + +{{? it.server_side_rendering == 0}} + + + + + +{{?}} + + + + + + + + + + + + + + + + +{{? it.server_side_rendering == 0}} + +{{?}} + diff --git a/templates/bootstrap2/footer.html b/templates/bootstrap2/footer.html new file mode 100644 index 000000000..e69de29bb diff --git a/templates/bootstrap2/header.html b/templates/bootstrap2/header.html new file mode 100644 index 000000000..12a3663de --- /dev/null +++ b/templates/bootstrap2/header.html @@ -0,0 +1,31 @@ + diff --git a/templates/bootstrap2/main.html b/templates/bootstrap2/main.html new file mode 100644 index 000000000..149cf8850 --- /dev/null +++ b/templates/bootstrap2/main.html @@ -0,0 +1,84 @@ +
    +{{? it.page == 13 || it.page == 16}} + {{? it.page == 13}} + {{#def.bookdetail}} + {{??}} + {{= it.fullhtml}} + {{?}} +{{??}} +
    +
      +
    +
    + +{{? it.containsBook == 0}} +
    +
    + {{~it.entries:entry:i}} + + {{~}} +
    +
    +{{??}} +
    + {{~it.entries:entry:i}} +
    +
    + {{? entry.book.hasCover == 1}} + + {{=it.c.i18n.coverAlt}} + + {{?}} +
    +
    +

    {{=htmlspecialchars (entry.title)}}

    +
    {{=htmlspecialchars (entry.book.authorsName)}}
    + {{? entry.book.seriesName != ""}}
    {{=htmlspecialchars (entry.book.seriesName)}} ({{=entry.book.seriesIndex}})
    {{?}} + + {{~entry.book.customcolumns_list :column:column_index}} +
    {{=column.customColumnType.columnTitle}} : {{=column.htmlvalue}}
    + {{~}} +
    +
    +
    + + {{? entry.book.preferedData.length > 1}}
    {{?}} + {{~entry.book.preferedData:data:j}} + {{? j == 0}} + {{=data.name}} + {{? entry.book.preferedData.length > 1}} + + {{? entry.book.preferedData.length > 1}}{{?}} + {{?}} + {{~}} + {{? entry.book.preferedData.length > 1}}
    {{?}} +
    +
    + {{~}} +
    +{{?}} +{{?}} +{{? it.isPaginated == 1}} + +{{?}} +
    diff --git a/templates/bootstrap2/page.html b/templates/bootstrap2/page.html new file mode 100644 index 000000000..88139c888 --- /dev/null +++ b/templates/bootstrap2/page.html @@ -0,0 +1,3 @@ +{{#def.header}} +{{#def.main}} +{{#def.footer}} diff --git a/templates/bootstrap2/scripts/cops.js b/templates/bootstrap2/scripts/cops.js new file mode 100644 index 000000000..2647a549f --- /dev/null +++ b/templates/bootstrap2/scripts/cops.js @@ -0,0 +1,7 @@ +function postRefresh() +{ + $('[data-toggle="tooltip"]').tooltip(); + hash = window.location.hash.replace("#", ""); + var elmnt = document.getElementById(hash); + if (elmnt) elmnt.scrollIntoView(); +} \ No newline at end of file diff --git a/templates/bootstrap2/styles/style-base.css b/templates/bootstrap2/styles/style-base.css new file mode 100644 index 000000000..4823668e1 --- /dev/null +++ b/templates/bootstrap2/styles/style-base.css @@ -0,0 +1,3 @@ +.panel-body { padding: 5px; } + +.bottomright {position:absolute; bottom:0; margin-bottom:25px; right: 20px;} \ No newline at end of file diff --git a/templates/bootstrap2/styles/style-default.css b/templates/bootstrap2/styles/style-default.css new file mode 100644 index 000000000..4823668e1 --- /dev/null +++ b/templates/bootstrap2/styles/style-default.css @@ -0,0 +1,3 @@ +.panel-body { padding: 5px; } + +.bottomright {position:absolute; bottom:0; margin-bottom:25px; right: 20px;} \ No newline at end of file diff --git a/templates/bootstrap2/styles/typeahead.css b/templates/bootstrap2/styles/typeahead.css new file mode 100644 index 000000000..23ccbc109 --- /dev/null +++ b/templates/bootstrap2/styles/typeahead.css @@ -0,0 +1,200 @@ +/* + * typehead.js-bootstrap3.less + * @version 0.2.3 + * https://github.com/hyspace/typeahead.js-bootstrap3.less + * + * Licensed under the MIT license: + * http://www.opensource.org/licenses/MIT + */ +.has-warning .twitter-typeahead .tt-input, +.has-warning .twitter-typeahead .tt-hint { + border-color: #8a6d3b; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} +.has-warning .twitter-typeahead .tt-input:focus, +.has-warning .twitter-typeahead .tt-hint:focus { + border-color: #66512c; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b; +} +.has-error .twitter-typeahead .tt-input, +.has-error .twitter-typeahead .tt-hint { + border-color: #a94442; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} +.has-error .twitter-typeahead .tt-input:focus, +.has-error .twitter-typeahead .tt-hint:focus { + border-color: #843534; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483; +} +.has-success .twitter-typeahead .tt-input, +.has-success .twitter-typeahead .tt-hint { + border-color: #3c763d; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} +.has-success .twitter-typeahead .tt-input:focus, +.has-success .twitter-typeahead .tt-hint:focus { + border-color: #2b542c; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168; +} +.input-group .twitter-typeahead:first-child .tt-input, +.input-group .twitter-typeahead:first-child .tt-hint { + border-bottom-left-radius: 4px; + border-top-left-radius: 4px; + width: 100%; +} +.input-group .twitter-typeahead:last-child .tt-input, +.input-group .twitter-typeahead:last-child .tt-hint { + border-bottom-right-radius: 4px; + border-top-right-radius: 4px; + width: 100%; +} +.input-group.input-group-sm .twitter-typeahead .tt-input, +.input-group.input-group-sm .twitter-typeahead .tt-hint { + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +select.input-group.input-group-sm .twitter-typeahead .tt-input, +select.input-group.input-group-sm .twitter-typeahead .tt-hint { + height: 30px; + line-height: 30px; +} +textarea.input-group.input-group-sm .twitter-typeahead .tt-input, +textarea.input-group.input-group-sm .twitter-typeahead .tt-hint, +select[multiple].input-group.input-group-sm .twitter-typeahead .tt-input, +select[multiple].input-group.input-group-sm .twitter-typeahead .tt-hint { + height: auto; +} +.input-group.input-group-sm .twitter-typeahead:not(:first-child):not(:last-child) .tt-input, +.input-group.input-group-sm .twitter-typeahead:not(:first-child):not(:last-child) .tt-hint { + border-radius: 0; +} +.input-group.input-group-sm .twitter-typeahead:first-child .tt-input, +.input-group.input-group-sm .twitter-typeahead:first-child .tt-hint { + border-bottom-left-radius: 3px; + border-top-left-radius: 3px; + border-bottom-right-radius: 0; + border-top-right-radius: 0; +} +.input-group.input-group-sm .twitter-typeahead:last-child .tt-input, +.input-group.input-group-sm .twitter-typeahead:last-child .tt-hint { + border-bottom-left-radius: 0; + border-top-left-radius: 0; + border-bottom-right-radius: 3px; + border-top-right-radius: 3px; +} +.input-group.input-group-lg .twitter-typeahead .tt-input, +.input-group.input-group-lg .twitter-typeahead .tt-hint { + height: 46px; + padding: 10px 16px; + font-size: 18px; + line-height: 1.33; + border-radius: 6px; +} +select.input-group.input-group-lg .twitter-typeahead .tt-input, +select.input-group.input-group-lg .twitter-typeahead .tt-hint { + height: 46px; + line-height: 46px; +} +textarea.input-group.input-group-lg .twitter-typeahead .tt-input, +textarea.input-group.input-group-lg .twitter-typeahead .tt-hint, +select[multiple].input-group.input-group-lg .twitter-typeahead .tt-input, +select[multiple].input-group.input-group-lg .twitter-typeahead .tt-hint { + height: auto; +} +.input-group.input-group-lg .twitter-typeahead:not(:first-child):not(:last-child) .tt-input, +.input-group.input-group-lg .twitter-typeahead:not(:first-child):not(:last-child) .tt-hint { + border-radius: 0; +} +.input-group.input-group-lg .twitter-typeahead:first-child .tt-input, +.input-group.input-group-lg .twitter-typeahead:first-child .tt-hint { + border-bottom-left-radius: 6px; + border-top-left-radius: 6px; + border-bottom-right-radius: 0; + border-top-right-radius: 0; +} +.input-group.input-group-lg .twitter-typeahead:last-child .tt-input, +.input-group.input-group-lg .twitter-typeahead:last-child .tt-hint { + border-bottom-left-radius: 0; + border-top-left-radius: 0; + border-bottom-right-radius: 6px; + border-top-right-radius: 6px; +} +.twitter-typeahead { + width: 100%; + float: left; +} +.input-group .twitter-typeahead { + display: table-cell !important; +} +.twitter-typeahead .tt-hint { + color: #999999; +} +.twitter-typeahead .tt-input { + z-index: 2; +} +.twitter-typeahead .tt-input[disabled], +.twitter-typeahead .tt-input[readonly], +fieldset[disabled] .twitter-typeahead .tt-input { + cursor: not-allowed; + background-color: #eeeeee !important; +} +.tt-dropdown-menu, +.tt-menu { + position: absolute; + top: 100%; + left: 0; + z-index: 1000; + min-width: 160px; + width: 100%; + padding: 5px 0; + margin: 2px 0 0; + list-style: none; + font-size: 14px; + background-color: #ffffff; + border: 1px solid #cccccc; + border: 1px solid rgba(0, 0, 0, 0.15); + border-radius: 4px; + -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); + box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); + background-clip: padding-box; + *border-right-width: 2px; + *border-bottom-width: 2px; +} +.tt-dropdown-menu .tt-suggestion, +.tt-menu .tt-suggestion { + display: block; + padding: 3px 20px; + clear: both; + font-weight: normal; + line-height: 1.42857143; + color: #333333; +} +.tt-dropdown-menu .tt-suggestion.tt-cursor, +.tt-menu .tt-suggestion.tt-cursor, +.tt-dropdown-menu .tt-suggestion:hover, +.tt-menu .tt-suggestion:hover { + cursor: pointer; + text-decoration: none; + outline: 0; + background-color: #f5f5f5; + color: #262626; +} +.tt-dropdown-menu .tt-suggestion.tt-cursor a, +.tt-menu .tt-suggestion.tt-cursor a, +.tt-dropdown-menu .tt-suggestion:hover a, +.tt-menu .tt-suggestion:hover a { + color: #262626; +} +.tt-dropdown-menu .tt-suggestion p, +.tt-menu .tt-suggestion p { + margin: 0; +} diff --git a/templates/bootstrap2/suggestion.html b/templates/bootstrap2/suggestion.html new file mode 100644 index 000000000..1107dadee --- /dev/null +++ b/templates/bootstrap2/suggestion.html @@ -0,0 +1 @@ +

    {{=it.title}}

    \ No newline at end of file diff --git a/templates/default/bookdetail.html b/templates/default/bookdetail.html new file mode 100644 index 000000000..5b667a5c3 --- /dev/null +++ b/templates/default/bookdetail.html @@ -0,0 +1,67 @@ +
    + + {{? it.book.hasCover == 1}} + + {{=it.c.i18n.coverAlt}} + + {{?}} + +

    + {{~it.book.datas:data:i}} + {{=data.format}} + + {{? data.mail == 1}} + + {{?}} + {{? data.readerUrl != ""}} + + {{?}} +
    + {{~}} +

    +

    {{=htmlspecialchars (it.title)}}

    +

    +

    {{=it.c.i18n.authorsTitle}}:

    + {{~it.book.authors:author:i}} + {{? i > 0}}, {{?}}{{=htmlspecialchars (author.name)}} + {{~}} +

    + {{? it.book.tagsName != ""}} +

    +

    {{=it.c.i18n.tagsTitle}}:

    + {{~it.book.tags:tag:i}} + {{? i > 0}}, {{?}}{{=htmlspecialchars (tag.name)}} + {{~}} +

    + {{?}} + {{? it.book.seriesName != ""}} +

    +

    {{=it.c.i18n.seriesTitle}} :

    {{=htmlspecialchars (it.book.seriesCompleteName)}} +

    + {{?}} + {{? it.book.publisherName != ""}} +

    +

    {{=it.c.i18n.publisherName}}:

    {{=htmlspecialchars (it.book.publisherName)}} +

    + {{?}} + {{? it.book.pubDate != ""}} +

    +

    {{=it.c.i18n.pubdateTitle}}:

    {{=it.book.pubDate}} +

    + {{?}} + {{? it.book.languagesName != ""}} +

    +

    {{=it.c.i18n.languagesTitle}}:

    {{=it.book.languagesName}} +

    + {{?}} + {{~it.book.customcolumns_preview :column:column_index}} +

    +

    {{=column.customColumnType.columnTitle}}:

    {{=column.htmlvalue}} +

    + {{~}} + {{? it.book.content != ""}} +
    +

    {{=it.c.i18n.contentTitle}}

    +
    {{=it.book.content}}
    + {{?}} +
    diff --git a/templates/default/file.html b/templates/default/file.html new file mode 100644 index 000000000..bcab519c4 --- /dev/null +++ b/templates/default/file.html @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + {{=it.title}} + + + + +{{? it.server_side_rendering == 0}} + + + + + +{{?}} + + + + + + + + + {{=it.customHeader}} + +{{? it.server_side_rendering == 0}} + +{{?}} + diff --git a/templates/default/footer.html b/templates/default/footer.html new file mode 100644 index 000000000..ebdd1b3b4 --- /dev/null +++ b/templates/default/footer.html @@ -0,0 +1,15 @@ +
    +
    +
    +
    +
    +
    +
    + {{? it.isPaginated == 1}} +
    + {{? it.prevLink != ""}}
    {{?}} +

    {{=it.currentPage}} / {{=it.maxPage}}

    + {{? it.nextLink != ""}}
    {{?}} +
    + {{?}} +
    \ No newline at end of file diff --git a/templates/default/header.html b/templates/default/header.html new file mode 100644 index 000000000..3295def47 --- /dev/null +++ b/templates/default/header.html @@ -0,0 +1,50 @@ +
    + +
    +
    + {{? it.c.config.server_side_rendering == 0}} +
    + {{?}} +
    +

    {{=it.title}}

    +
    +
    +
    +
    +
    + + {{? it.databaseId != ""}} + + {{?}} + +
    + +
    +
    + {{? it.c.config.server_side_rendering == 0}} + +
    +
      +
    +
    + {{?}} +
    +
    diff --git a/templates/default/main.html b/templates/default/main.html new file mode 100644 index 000000000..0f3492d4f --- /dev/null +++ b/templates/default/main.html @@ -0,0 +1,52 @@ +
    +{{? it.page == 13 || it.page == 16}} + {{? it.page == 13}} + {{#def.bookdetail}} + {{??}} + {{= it.fullhtml}} + {{?}} +{{??}} +{{~it.entries:entry:i}} + {{? it.containsBook == 0}} + + {{??}} +
    + + {{? entry.book.hasCover == 1}} + + {{=it.c.i18n.coverAlt}} + + {{?}} + +

    + {{~entry.book.preferedData:data:j}} + {{=data.name}} + +
    + {{~}} +

    + +
    +

    {{=htmlspecialchars (entry.title)}} + {{? entry.book.pubDate != ""}}({{=entry.book.pubDate}}){{?}} + {{? entry.book.rating != ""}}{{=entry.book.rating}}{{?}} +

    +

    {{=it.c.i18n.authorsTitle}} :

    {{=htmlspecialchars (entry.book.authorsName)}}
    + {{? entry.book.tagsName != ""}}

    {{=it.c.i18n.tagsTitle}} :

    {{=htmlspecialchars (entry.book.tagsName)}}
    {{?}} + {{? entry.book.seriesName != ""}}

    {{=it.c.i18n.seriesTitle}} :

    {{=htmlspecialchars (entry.book.seriesName)}} ({{=entry.book.seriesIndex}})
    {{?}} + {{~entry.book.customcolumns_list :column:column_index}} +

    {{=column.customColumnType.columnTitle}} :

    {{=column.htmlvalue}}
    + {{~}} +
    +
    + {{?}} +{{~}} +{{?}} +
    diff --git a/templates/default/page.html b/templates/default/page.html new file mode 100644 index 000000000..20f1e0a3e --- /dev/null +++ b/templates/default/page.html @@ -0,0 +1,5 @@ +
    +{{#def.header}} +{{#def.main}} +{{#def.footer}} +
    \ No newline at end of file diff --git a/templates/default/styles/fa-solid.min.css b/templates/default/styles/fa-solid.min.css new file mode 100644 index 000000000..a06374a30 --- /dev/null +++ b/templates/default/styles/fa-solid.min.css @@ -0,0 +1,5 @@ +/*! + * Font Awesome Free 5.0.13 by @fontawesome - https://fontawesome.com + * License - https://fontawesome.com/license (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) + */ +@font-face{font-family:Font Awesome\ 5 Free;font-style:normal;font-weight:900;src:url(../webfonts/fa-solid-900.eot);src:url(../webfonts/fa-solid-900.eot?#iefix) format("embedded-opentype"),url(../webfonts/fa-solid-900.woff2) format("woff2"),url(../webfonts/fa-solid-900.woff) format("woff"),url(../webfonts/fa-solid-900.ttf) format("truetype"),url(../webfonts/fa-solid-900.svg#fontawesome) format("svg")}.fa,.fas{font-family:Font Awesome\ 5 Free;font-weight:900} \ No newline at end of file diff --git a/templates/default/styles/fontawesome.min.css b/templates/default/styles/fontawesome.min.css new file mode 100644 index 000000000..9c931e489 --- /dev/null +++ b/templates/default/styles/fontawesome.min.css @@ -0,0 +1,5 @@ +/*! + * Font Awesome Free 5.0.13 by @fontawesome - https://fontawesome.com + * License - https://fontawesome.com/license (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) + */ +.fa,.fab,.fal,.far,.fas{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1}.fa-lg{font-size:1.33333em;line-height:.75em;vertical-align:-.0667em}.fa-xs{font-size:.75em}.fa-sm{font-size:.875em}.fa-1x{font-size:1em}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-6x{font-size:6em}.fa-7x{font-size:7em}.fa-8x{font-size:8em}.fa-9x{font-size:9em}.fa-10x{font-size:10em}.fa-fw{text-align:center;width:1.25em}.fa-ul{list-style-type:none;margin-left:2.5em;padding-left:0}.fa-ul>li{position:relative}.fa-li{left:-2em;position:absolute;text-align:center;width:2em;line-height:inherit}.fa-border{border:.08em solid #eee;border-radius:.1em;padding:.2em .25em .15em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left,.fab.fa-pull-left,.fal.fa-pull-left,.far.fa-pull-left,.fas.fa-pull-left{margin-right:.3em}.fa.fa-pull-right,.fab.fa-pull-right,.fal.fa-pull-right,.far.fa-pull-right,.fas.fa-pull-right{margin-left:.3em}.fa-spin{animation:a 2s infinite linear}.fa-pulse{animation:a 1s infinite steps(8)}@keyframes a{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";transform:scaleX(-1)}.fa-flip-vertical{transform:scaleY(-1)}.fa-flip-horizontal.fa-flip-vertical,.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)"}.fa-flip-horizontal.fa-flip-vertical{transform:scale(-1)}:root .fa-flip-horizontal,:root .fa-flip-vertical,:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270{-webkit-filter:none;filter:none}.fa-stack{display:inline-block;height:2em;line-height:2em;position:relative;vertical-align:middle;width:2em}.fa-stack-1x,.fa-stack-2x{left:0;position:absolute;text-align:center;width:100%}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-500px:before{content:"\f26e"}.fa-accessible-icon:before{content:"\f368"}.fa-accusoft:before{content:"\f369"}.fa-address-book:before{content:"\f2b9"}.fa-address-card:before{content:"\f2bb"}.fa-adjust:before{content:"\f042"}.fa-adn:before{content:"\f170"}.fa-adversal:before{content:"\f36a"}.fa-affiliatetheme:before{content:"\f36b"}.fa-algolia:before{content:"\f36c"}.fa-align-center:before{content:"\f037"}.fa-align-justify:before{content:"\f039"}.fa-align-left:before{content:"\f036"}.fa-align-right:before{content:"\f038"}.fa-allergies:before{content:"\f461"}.fa-amazon:before{content:"\f270"}.fa-amazon-pay:before{content:"\f42c"}.fa-ambulance:before{content:"\f0f9"}.fa-american-sign-language-interpreting:before{content:"\f2a3"}.fa-amilia:before{content:"\f36d"}.fa-anchor:before{content:"\f13d"}.fa-android:before{content:"\f17b"}.fa-angellist:before{content:"\f209"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-down:before{content:"\f107"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angrycreative:before{content:"\f36e"}.fa-angular:before{content:"\f420"}.fa-app-store:before{content:"\f36f"}.fa-app-store-ios:before{content:"\f370"}.fa-apper:before{content:"\f371"}.fa-apple:before{content:"\f179"}.fa-apple-pay:before{content:"\f415"}.fa-archive:before{content:"\f187"}.fa-arrow-alt-circle-down:before{content:"\f358"}.fa-arrow-alt-circle-left:before{content:"\f359"}.fa-arrow-alt-circle-right:before{content:"\f35a"}.fa-arrow-alt-circle-up:before{content:"\f35b"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-down:before{content:"\f063"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrows-alt:before{content:"\f0b2"}.fa-arrows-alt-h:before{content:"\f337"}.fa-arrows-alt-v:before{content:"\f338"}.fa-assistive-listening-systems:before{content:"\f2a2"}.fa-asterisk:before{content:"\f069"}.fa-asymmetrik:before{content:"\f372"}.fa-at:before{content:"\f1fa"}.fa-audible:before{content:"\f373"}.fa-audio-description:before{content:"\f29e"}.fa-autoprefixer:before{content:"\f41c"}.fa-avianex:before{content:"\f374"}.fa-aviato:before{content:"\f421"}.fa-aws:before{content:"\f375"}.fa-backward:before{content:"\f04a"}.fa-balance-scale:before{content:"\f24e"}.fa-ban:before{content:"\f05e"}.fa-band-aid:before{content:"\f462"}.fa-bandcamp:before{content:"\f2d5"}.fa-barcode:before{content:"\f02a"}.fa-bars:before{content:"\f0c9"}.fa-baseball-ball:before{content:"\f433"}.fa-basketball-ball:before{content:"\f434"}.fa-bath:before{content:"\f2cd"}.fa-battery-empty:before{content:"\f244"}.fa-battery-full:before{content:"\f240"}.fa-battery-half:before{content:"\f242"}.fa-battery-quarter:before{content:"\f243"}.fa-battery-three-quarters:before{content:"\f241"}.fa-bed:before{content:"\f236"}.fa-beer:before{content:"\f0fc"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-bell:before{content:"\f0f3"}.fa-bell-slash:before{content:"\f1f6"}.fa-bicycle:before{content:"\f206"}.fa-bimobject:before{content:"\f378"}.fa-binoculars:before{content:"\f1e5"}.fa-birthday-cake:before{content:"\f1fd"}.fa-bitbucket:before{content:"\f171"}.fa-bitcoin:before{content:"\f379"}.fa-bity:before{content:"\f37a"}.fa-black-tie:before{content:"\f27e"}.fa-blackberry:before{content:"\f37b"}.fa-blender:before{content:"\f517"}.fa-blind:before{content:"\f29d"}.fa-blogger:before{content:"\f37c"}.fa-blogger-b:before{content:"\f37d"}.fa-bluetooth:before{content:"\f293"}.fa-bluetooth-b:before{content:"\f294"}.fa-bold:before{content:"\f032"}.fa-bolt:before{content:"\f0e7"}.fa-bomb:before{content:"\f1e2"}.fa-book:before{content:"\f02d"}.fa-book-open:before{content:"\f518"}.fa-bookmark:before{content:"\f02e"}.fa-bowling-ball:before{content:"\f436"}.fa-box:before{content:"\f466"}.fa-box-open:before{content:"\f49e"}.fa-boxes:before{content:"\f468"}.fa-braille:before{content:"\f2a1"}.fa-briefcase:before{content:"\f0b1"}.fa-briefcase-medical:before{content:"\f469"}.fa-broadcast-tower:before{content:"\f519"}.fa-broom:before{content:"\f51a"}.fa-btc:before{content:"\f15a"}.fa-bug:before{content:"\f188"}.fa-building:before{content:"\f1ad"}.fa-bullhorn:before{content:"\f0a1"}.fa-bullseye:before{content:"\f140"}.fa-burn:before{content:"\f46a"}.fa-buromobelexperte:before{content:"\f37f"}.fa-bus:before{content:"\f207"}.fa-buysellads:before{content:"\f20d"}.fa-calculator:before{content:"\f1ec"}.fa-calendar:before{content:"\f133"}.fa-calendar-alt:before{content:"\f073"}.fa-calendar-check:before{content:"\f274"}.fa-calendar-minus:before{content:"\f272"}.fa-calendar-plus:before{content:"\f271"}.fa-calendar-times:before{content:"\f273"}.fa-camera:before{content:"\f030"}.fa-camera-retro:before{content:"\f083"}.fa-capsules:before{content:"\f46b"}.fa-car:before{content:"\f1b9"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-caret-square-down:before{content:"\f150"}.fa-caret-square-left:before{content:"\f191"}.fa-caret-square-right:before{content:"\f152"}.fa-caret-square-up:before{content:"\f151"}.fa-caret-up:before{content:"\f0d8"}.fa-cart-arrow-down:before{content:"\f218"}.fa-cart-plus:before{content:"\f217"}.fa-cc-amazon-pay:before{content:"\f42d"}.fa-cc-amex:before{content:"\f1f3"}.fa-cc-apple-pay:before{content:"\f416"}.fa-cc-diners-club:before{content:"\f24c"}.fa-cc-discover:before{content:"\f1f2"}.fa-cc-jcb:before{content:"\f24b"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-cc-paypal:before{content:"\f1f4"}.fa-cc-stripe:before{content:"\f1f5"}.fa-cc-visa:before{content:"\f1f0"}.fa-centercode:before{content:"\f380"}.fa-certificate:before{content:"\f0a3"}.fa-chalkboard:before{content:"\f51b"}.fa-chalkboard-teacher:before{content:"\f51c"}.fa-chart-area:before{content:"\f1fe"}.fa-chart-bar:before{content:"\f080"}.fa-chart-line:before{content:"\f201"}.fa-chart-pie:before{content:"\f200"}.fa-check:before{content:"\f00c"}.fa-check-circle:before{content:"\f058"}.fa-check-square:before{content:"\f14a"}.fa-chess:before{content:"\f439"}.fa-chess-bishop:before{content:"\f43a"}.fa-chess-board:before{content:"\f43c"}.fa-chess-king:before{content:"\f43f"}.fa-chess-knight:before{content:"\f441"}.fa-chess-pawn:before{content:"\f443"}.fa-chess-queen:before{content:"\f445"}.fa-chess-rook:before{content:"\f447"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-down:before{content:"\f078"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-chevron-up:before{content:"\f077"}.fa-child:before{content:"\f1ae"}.fa-chrome:before{content:"\f268"}.fa-church:before{content:"\f51d"}.fa-circle:before{content:"\f111"}.fa-circle-notch:before{content:"\f1ce"}.fa-clipboard:before{content:"\f328"}.fa-clipboard-check:before{content:"\f46c"}.fa-clipboard-list:before{content:"\f46d"}.fa-clock:before{content:"\f017"}.fa-clone:before{content:"\f24d"}.fa-closed-captioning:before{content:"\f20a"}.fa-cloud:before{content:"\f0c2"}.fa-cloud-download-alt:before{content:"\f381"}.fa-cloud-upload-alt:before{content:"\f382"}.fa-cloudscale:before{content:"\f383"}.fa-cloudsmith:before{content:"\f384"}.fa-cloudversify:before{content:"\f385"}.fa-code:before{content:"\f121"}.fa-code-branch:before{content:"\f126"}.fa-codepen:before{content:"\f1cb"}.fa-codiepie:before{content:"\f284"}.fa-coffee:before{content:"\f0f4"}.fa-cog:before{content:"\f013"}.fa-cogs:before{content:"\f085"}.fa-coins:before{content:"\f51e"}.fa-columns:before{content:"\f0db"}.fa-comment:before{content:"\f075"}.fa-comment-alt:before{content:"\f27a"}.fa-comment-dots:before{content:"\f4ad"}.fa-comment-slash:before{content:"\f4b3"}.fa-comments:before{content:"\f086"}.fa-compact-disc:before{content:"\f51f"}.fa-compass:before{content:"\f14e"}.fa-compress:before{content:"\f066"}.fa-connectdevelop:before{content:"\f20e"}.fa-contao:before{content:"\f26d"}.fa-copy:before{content:"\f0c5"}.fa-copyright:before{content:"\f1f9"}.fa-couch:before{content:"\f4b8"}.fa-cpanel:before{content:"\f388"}.fa-creative-commons:before{content:"\f25e"}.fa-creative-commons-by:before{content:"\f4e7"}.fa-creative-commons-nc:before{content:"\f4e8"}.fa-creative-commons-nc-eu:before{content:"\f4e9"}.fa-creative-commons-nc-jp:before{content:"\f4ea"}.fa-creative-commons-nd:before{content:"\f4eb"}.fa-creative-commons-pd:before{content:"\f4ec"}.fa-creative-commons-pd-alt:before{content:"\f4ed"}.fa-creative-commons-remix:before{content:"\f4ee"}.fa-creative-commons-sa:before{content:"\f4ef"}.fa-creative-commons-sampling:before{content:"\f4f0"}.fa-creative-commons-sampling-plus:before{content:"\f4f1"}.fa-creative-commons-share:before{content:"\f4f2"}.fa-credit-card:before{content:"\f09d"}.fa-crop:before{content:"\f125"}.fa-crosshairs:before{content:"\f05b"}.fa-crow:before{content:"\f520"}.fa-crown:before{content:"\f521"}.fa-css3:before{content:"\f13c"}.fa-css3-alt:before{content:"\f38b"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-cut:before{content:"\f0c4"}.fa-cuttlefish:before{content:"\f38c"}.fa-d-and-d:before{content:"\f38d"}.fa-dashcube:before{content:"\f210"}.fa-database:before{content:"\f1c0"}.fa-deaf:before{content:"\f2a4"}.fa-delicious:before{content:"\f1a5"}.fa-deploydog:before{content:"\f38e"}.fa-deskpro:before{content:"\f38f"}.fa-desktop:before{content:"\f108"}.fa-deviantart:before{content:"\f1bd"}.fa-diagnoses:before{content:"\f470"}.fa-dice:before{content:"\f522"}.fa-dice-five:before{content:"\f523"}.fa-dice-four:before{content:"\f524"}.fa-dice-one:before{content:"\f525"}.fa-dice-six:before{content:"\f526"}.fa-dice-three:before{content:"\f527"}.fa-dice-two:before{content:"\f528"}.fa-digg:before{content:"\f1a6"}.fa-digital-ocean:before{content:"\f391"}.fa-discord:before{content:"\f392"}.fa-discourse:before{content:"\f393"}.fa-divide:before{content:"\f529"}.fa-dna:before{content:"\f471"}.fa-dochub:before{content:"\f394"}.fa-docker:before{content:"\f395"}.fa-dollar-sign:before{content:"\f155"}.fa-dolly:before{content:"\f472"}.fa-dolly-flatbed:before{content:"\f474"}.fa-donate:before{content:"\f4b9"}.fa-door-closed:before{content:"\f52a"}.fa-door-open:before{content:"\f52b"}.fa-dot-circle:before{content:"\f192"}.fa-dove:before{content:"\f4ba"}.fa-download:before{content:"\f019"}.fa-draft2digital:before{content:"\f396"}.fa-dribbble:before{content:"\f17d"}.fa-dribbble-square:before{content:"\f397"}.fa-dropbox:before{content:"\f16b"}.fa-drupal:before{content:"\f1a9"}.fa-dumbbell:before{content:"\f44b"}.fa-dyalog:before{content:"\f399"}.fa-earlybirds:before{content:"\f39a"}.fa-ebay:before{content:"\f4f4"}.fa-edge:before{content:"\f282"}.fa-edit:before{content:"\f044"}.fa-eject:before{content:"\f052"}.fa-elementor:before{content:"\f430"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-ember:before{content:"\f423"}.fa-empire:before{content:"\f1d1"}.fa-envelope:before{content:"\f0e0"}.fa-envelope-open:before{content:"\f2b6"}.fa-envelope-square:before{content:"\f199"}.fa-envira:before{content:"\f299"}.fa-equals:before{content:"\f52c"}.fa-eraser:before{content:"\f12d"}.fa-erlang:before{content:"\f39d"}.fa-ethereum:before{content:"\f42e"}.fa-etsy:before{content:"\f2d7"}.fa-euro-sign:before{content:"\f153"}.fa-exchange-alt:before{content:"\f362"}.fa-exclamation:before{content:"\f12a"}.fa-exclamation-circle:before{content:"\f06a"}.fa-exclamation-triangle:before{content:"\f071"}.fa-expand:before{content:"\f065"}.fa-expand-arrows-alt:before{content:"\f31e"}.fa-expeditedssl:before{content:"\f23e"}.fa-external-link-alt:before{content:"\f35d"}.fa-external-link-square-alt:before{content:"\f360"}.fa-eye:before{content:"\f06e"}.fa-eye-dropper:before{content:"\f1fb"}.fa-eye-slash:before{content:"\f070"}.fa-facebook:before{content:"\f09a"}.fa-facebook-f:before{content:"\f39e"}.fa-facebook-messenger:before{content:"\f39f"}.fa-facebook-square:before{content:"\f082"}.fa-fast-backward:before{content:"\f049"}.fa-fast-forward:before{content:"\f050"}.fa-fax:before{content:"\f1ac"}.fa-feather:before{content:"\f52d"}.fa-female:before{content:"\f182"}.fa-fighter-jet:before{content:"\f0fb"}.fa-file:before{content:"\f15b"}.fa-file-alt:before{content:"\f15c"}.fa-file-archive:before{content:"\f1c6"}.fa-file-audio:before{content:"\f1c7"}.fa-file-code:before{content:"\f1c9"}.fa-file-excel:before{content:"\f1c3"}.fa-file-image:before{content:"\f1c5"}.fa-file-medical:before{content:"\f477"}.fa-file-medical-alt:before{content:"\f478"}.fa-file-pdf:before{content:"\f1c1"}.fa-file-powerpoint:before{content:"\f1c4"}.fa-file-video:before{content:"\f1c8"}.fa-file-word:before{content:"\f1c2"}.fa-film:before{content:"\f008"}.fa-filter:before{content:"\f0b0"}.fa-fire:before{content:"\f06d"}.fa-fire-extinguisher:before{content:"\f134"}.fa-firefox:before{content:"\f269"}.fa-first-aid:before{content:"\f479"}.fa-first-order:before{content:"\f2b0"}.fa-first-order-alt:before{content:"\f50a"}.fa-firstdraft:before{content:"\f3a1"}.fa-flag:before{content:"\f024"}.fa-flag-checkered:before{content:"\f11e"}.fa-flask:before{content:"\f0c3"}.fa-flickr:before{content:"\f16e"}.fa-flipboard:before{content:"\f44d"}.fa-fly:before{content:"\f417"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-font:before{content:"\f031"}.fa-font-awesome:before{content:"\f2b4"}.fa-font-awesome-alt:before{content:"\f35c"}.fa-font-awesome-flag:before{content:"\f425"}.fa-font-awesome-logo-full:before{content:"\f4e6"}.fa-fonticons:before{content:"\f280"}.fa-fonticons-fi:before{content:"\f3a2"}.fa-football-ball:before{content:"\f44e"}.fa-fort-awesome:before{content:"\f286"}.fa-fort-awesome-alt:before{content:"\f3a3"}.fa-forumbee:before{content:"\f211"}.fa-forward:before{content:"\f04e"}.fa-foursquare:before{content:"\f180"}.fa-free-code-camp:before{content:"\f2c5"}.fa-freebsd:before{content:"\f3a4"}.fa-frog:before{content:"\f52e"}.fa-frown:before{content:"\f119"}.fa-fulcrum:before{content:"\f50b"}.fa-futbol:before{content:"\f1e3"}.fa-galactic-republic:before{content:"\f50c"}.fa-galactic-senate:before{content:"\f50d"}.fa-gamepad:before{content:"\f11b"}.fa-gas-pump:before{content:"\f52f"}.fa-gavel:before{content:"\f0e3"}.fa-gem:before{content:"\f3a5"}.fa-genderless:before{content:"\f22d"}.fa-get-pocket:before{content:"\f265"}.fa-gg:before{content:"\f260"}.fa-gg-circle:before{content:"\f261"}.fa-gift:before{content:"\f06b"}.fa-git:before{content:"\f1d3"}.fa-git-square:before{content:"\f1d2"}.fa-github:before{content:"\f09b"}.fa-github-alt:before{content:"\f113"}.fa-github-square:before{content:"\f092"}.fa-gitkraken:before{content:"\f3a6"}.fa-gitlab:before{content:"\f296"}.fa-gitter:before{content:"\f426"}.fa-glass-martini:before{content:"\f000"}.fa-glasses:before{content:"\f530"}.fa-glide:before{content:"\f2a5"}.fa-glide-g:before{content:"\f2a6"}.fa-globe:before{content:"\f0ac"}.fa-gofore:before{content:"\f3a7"}.fa-golf-ball:before{content:"\f450"}.fa-goodreads:before{content:"\f3a8"}.fa-goodreads-g:before{content:"\f3a9"}.fa-google:before{content:"\f1a0"}.fa-google-drive:before{content:"\f3aa"}.fa-google-play:before{content:"\f3ab"}.fa-google-plus:before{content:"\f2b3"}.fa-google-plus-g:before{content:"\f0d5"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-wallet:before{content:"\f1ee"}.fa-graduation-cap:before{content:"\f19d"}.fa-gratipay:before{content:"\f184"}.fa-grav:before{content:"\f2d6"}.fa-greater-than:before{content:"\f531"}.fa-greater-than-equal:before{content:"\f532"}.fa-gripfire:before{content:"\f3ac"}.fa-grunt:before{content:"\f3ad"}.fa-gulp:before{content:"\f3ae"}.fa-h-square:before{content:"\f0fd"}.fa-hacker-news:before{content:"\f1d4"}.fa-hacker-news-square:before{content:"\f3af"}.fa-hand-holding:before{content:"\f4bd"}.fa-hand-holding-heart:before{content:"\f4be"}.fa-hand-holding-usd:before{content:"\f4c0"}.fa-hand-lizard:before{content:"\f258"}.fa-hand-paper:before{content:"\f256"}.fa-hand-peace:before{content:"\f25b"}.fa-hand-point-down:before{content:"\f0a7"}.fa-hand-point-left:before{content:"\f0a5"}.fa-hand-point-right:before{content:"\f0a4"}.fa-hand-point-up:before{content:"\f0a6"}.fa-hand-pointer:before{content:"\f25a"}.fa-hand-rock:before{content:"\f255"}.fa-hand-scissors:before{content:"\f257"}.fa-hand-spock:before{content:"\f259"}.fa-hands:before{content:"\f4c2"}.fa-hands-helping:before{content:"\f4c4"}.fa-handshake:before{content:"\f2b5"}.fa-hashtag:before{content:"\f292"}.fa-hdd:before{content:"\f0a0"}.fa-heading:before{content:"\f1dc"}.fa-headphones:before{content:"\f025"}.fa-heart:before{content:"\f004"}.fa-heartbeat:before{content:"\f21e"}.fa-helicopter:before{content:"\f533"}.fa-hips:before{content:"\f452"}.fa-hire-a-helper:before{content:"\f3b0"}.fa-history:before{content:"\f1da"}.fa-hockey-puck:before{content:"\f453"}.fa-home:before{content:"\f015"}.fa-hooli:before{content:"\f427"}.fa-hospital:before{content:"\f0f8"}.fa-hospital-alt:before{content:"\f47d"}.fa-hospital-symbol:before{content:"\f47e"}.fa-hotjar:before{content:"\f3b1"}.fa-hourglass:before{content:"\f254"}.fa-hourglass-end:before{content:"\f253"}.fa-hourglass-half:before{content:"\f252"}.fa-hourglass-start:before{content:"\f251"}.fa-houzz:before{content:"\f27c"}.fa-html5:before{content:"\f13b"}.fa-hubspot:before{content:"\f3b2"}.fa-i-cursor:before{content:"\f246"}.fa-id-badge:before{content:"\f2c1"}.fa-id-card:before{content:"\f2c2"}.fa-id-card-alt:before{content:"\f47f"}.fa-image:before{content:"\f03e"}.fa-images:before{content:"\f302"}.fa-imdb:before{content:"\f2d8"}.fa-inbox:before{content:"\f01c"}.fa-indent:before{content:"\f03c"}.fa-industry:before{content:"\f275"}.fa-infinity:before{content:"\f534"}.fa-info:before{content:"\f129"}.fa-info-circle:before{content:"\f05a"}.fa-instagram:before{content:"\f16d"}.fa-internet-explorer:before{content:"\f26b"}.fa-ioxhost:before{content:"\f208"}.fa-italic:before{content:"\f033"}.fa-itunes:before{content:"\f3b4"}.fa-itunes-note:before{content:"\f3b5"}.fa-java:before{content:"\f4e4"}.fa-jedi-order:before{content:"\f50e"}.fa-jenkins:before{content:"\f3b6"}.fa-joget:before{content:"\f3b7"}.fa-joomla:before{content:"\f1aa"}.fa-js:before{content:"\f3b8"}.fa-js-square:before{content:"\f3b9"}.fa-jsfiddle:before{content:"\f1cc"}.fa-key:before{content:"\f084"}.fa-keybase:before{content:"\f4f5"}.fa-keyboard:before{content:"\f11c"}.fa-keycdn:before{content:"\f3ba"}.fa-kickstarter:before{content:"\f3bb"}.fa-kickstarter-k:before{content:"\f3bc"}.fa-kiwi-bird:before{content:"\f535"}.fa-korvue:before{content:"\f42f"}.fa-language:before{content:"\f1ab"}.fa-laptop:before{content:"\f109"}.fa-laravel:before{content:"\f3bd"}.fa-lastfm:before{content:"\f202"}.fa-lastfm-square:before{content:"\f203"}.fa-leaf:before{content:"\f06c"}.fa-leanpub:before{content:"\f212"}.fa-lemon:before{content:"\f094"}.fa-less:before{content:"\f41d"}.fa-less-than:before{content:"\f536"}.fa-less-than-equal:before{content:"\f537"}.fa-level-down-alt:before{content:"\f3be"}.fa-level-up-alt:before{content:"\f3bf"}.fa-life-ring:before{content:"\f1cd"}.fa-lightbulb:before{content:"\f0eb"}.fa-line:before{content:"\f3c0"}.fa-link:before{content:"\f0c1"}.fa-linkedin:before{content:"\f08c"}.fa-linkedin-in:before{content:"\f0e1"}.fa-linode:before{content:"\f2b8"}.fa-linux:before{content:"\f17c"}.fa-lira-sign:before{content:"\f195"}.fa-list:before{content:"\f03a"}.fa-list-alt:before{content:"\f022"}.fa-list-ol:before{content:"\f0cb"}.fa-list-ul:before{content:"\f0ca"}.fa-location-arrow:before{content:"\f124"}.fa-lock:before{content:"\f023"}.fa-lock-open:before{content:"\f3c1"}.fa-long-arrow-alt-down:before{content:"\f309"}.fa-long-arrow-alt-left:before{content:"\f30a"}.fa-long-arrow-alt-right:before{content:"\f30b"}.fa-long-arrow-alt-up:before{content:"\f30c"}.fa-low-vision:before{content:"\f2a8"}.fa-lyft:before{content:"\f3c3"}.fa-magento:before{content:"\f3c4"}.fa-magic:before{content:"\f0d0"}.fa-magnet:before{content:"\f076"}.fa-male:before{content:"\f183"}.fa-mandalorian:before{content:"\f50f"}.fa-map:before{content:"\f279"}.fa-map-marker:before{content:"\f041"}.fa-map-marker-alt:before{content:"\f3c5"}.fa-map-pin:before{content:"\f276"}.fa-map-signs:before{content:"\f277"}.fa-mars:before{content:"\f222"}.fa-mars-double:before{content:"\f227"}.fa-mars-stroke:before{content:"\f229"}.fa-mars-stroke-h:before{content:"\f22b"}.fa-mars-stroke-v:before{content:"\f22a"}.fa-mastodon:before{content:"\f4f6"}.fa-maxcdn:before{content:"\f136"}.fa-medapps:before{content:"\f3c6"}.fa-medium:before{content:"\f23a"}.fa-medium-m:before{content:"\f3c7"}.fa-medkit:before{content:"\f0fa"}.fa-medrt:before{content:"\f3c8"}.fa-meetup:before{content:"\f2e0"}.fa-meh:before{content:"\f11a"}.fa-memory:before{content:"\f538"}.fa-mercury:before{content:"\f223"}.fa-microchip:before{content:"\f2db"}.fa-microphone:before{content:"\f130"}.fa-microphone-alt:before{content:"\f3c9"}.fa-microphone-alt-slash:before{content:"\f539"}.fa-microphone-slash:before{content:"\f131"}.fa-microsoft:before{content:"\f3ca"}.fa-minus:before{content:"\f068"}.fa-minus-circle:before{content:"\f056"}.fa-minus-square:before{content:"\f146"}.fa-mix:before{content:"\f3cb"}.fa-mixcloud:before{content:"\f289"}.fa-mizuni:before{content:"\f3cc"}.fa-mobile:before{content:"\f10b"}.fa-mobile-alt:before{content:"\f3cd"}.fa-modx:before{content:"\f285"}.fa-monero:before{content:"\f3d0"}.fa-money-bill:before{content:"\f0d6"}.fa-money-bill-alt:before{content:"\f3d1"}.fa-money-bill-wave:before{content:"\f53a"}.fa-money-bill-wave-alt:before{content:"\f53b"}.fa-money-check:before{content:"\f53c"}.fa-money-check-alt:before{content:"\f53d"}.fa-moon:before{content:"\f186"}.fa-motorcycle:before{content:"\f21c"}.fa-mouse-pointer:before{content:"\f245"}.fa-music:before{content:"\f001"}.fa-napster:before{content:"\f3d2"}.fa-neuter:before{content:"\f22c"}.fa-newspaper:before{content:"\f1ea"}.fa-nintendo-switch:before{content:"\f418"}.fa-node:before{content:"\f419"}.fa-node-js:before{content:"\f3d3"}.fa-not-equal:before{content:"\f53e"}.fa-notes-medical:before{content:"\f481"}.fa-npm:before{content:"\f3d4"}.fa-ns8:before{content:"\f3d5"}.fa-nutritionix:before{content:"\f3d6"}.fa-object-group:before{content:"\f247"}.fa-object-ungroup:before{content:"\f248"}.fa-odnoklassniki:before{content:"\f263"}.fa-odnoklassniki-square:before{content:"\f264"}.fa-old-republic:before{content:"\f510"}.fa-opencart:before{content:"\f23d"}.fa-openid:before{content:"\f19b"}.fa-opera:before{content:"\f26a"}.fa-optin-monster:before{content:"\f23c"}.fa-osi:before{content:"\f41a"}.fa-outdent:before{content:"\f03b"}.fa-page4:before{content:"\f3d7"}.fa-pagelines:before{content:"\f18c"}.fa-paint-brush:before{content:"\f1fc"}.fa-palette:before{content:"\f53f"}.fa-palfed:before{content:"\f3d8"}.fa-pallet:before{content:"\f482"}.fa-paper-plane:before{content:"\f1d8"}.fa-paperclip:before{content:"\f0c6"}.fa-parachute-box:before{content:"\f4cd"}.fa-paragraph:before{content:"\f1dd"}.fa-parking:before{content:"\f540"}.fa-paste:before{content:"\f0ea"}.fa-patreon:before{content:"\f3d9"}.fa-pause:before{content:"\f04c"}.fa-pause-circle:before{content:"\f28b"}.fa-paw:before{content:"\f1b0"}.fa-paypal:before{content:"\f1ed"}.fa-pen-square:before{content:"\f14b"}.fa-pencil-alt:before{content:"\f303"}.fa-people-carry:before{content:"\f4ce"}.fa-percent:before{content:"\f295"}.fa-percentage:before{content:"\f541"}.fa-periscope:before{content:"\f3da"}.fa-phabricator:before{content:"\f3db"}.fa-phoenix-framework:before{content:"\f3dc"}.fa-phoenix-squadron:before{content:"\f511"}.fa-phone:before{content:"\f095"}.fa-phone-slash:before{content:"\f3dd"}.fa-phone-square:before{content:"\f098"}.fa-phone-volume:before{content:"\f2a0"}.fa-php:before{content:"\f457"}.fa-pied-piper:before{content:"\f2ae"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-pied-piper-hat:before{content:"\f4e5"}.fa-pied-piper-pp:before{content:"\f1a7"}.fa-piggy-bank:before{content:"\f4d3"}.fa-pills:before{content:"\f484"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-p:before{content:"\f231"}.fa-pinterest-square:before{content:"\f0d3"}.fa-plane:before{content:"\f072"}.fa-play:before{content:"\f04b"}.fa-play-circle:before{content:"\f144"}.fa-playstation:before{content:"\f3df"}.fa-plug:before{content:"\f1e6"}.fa-plus:before{content:"\f067"}.fa-plus-circle:before{content:"\f055"}.fa-plus-square:before{content:"\f0fe"}.fa-podcast:before{content:"\f2ce"}.fa-poo:before{content:"\f2fe"}.fa-portrait:before{content:"\f3e0"}.fa-pound-sign:before{content:"\f154"}.fa-power-off:before{content:"\f011"}.fa-prescription-bottle:before{content:"\f485"}.fa-prescription-bottle-alt:before{content:"\f486"}.fa-print:before{content:"\f02f"}.fa-procedures:before{content:"\f487"}.fa-product-hunt:before{content:"\f288"}.fa-project-diagram:before{content:"\f542"}.fa-pushed:before{content:"\f3e1"}.fa-puzzle-piece:before{content:"\f12e"}.fa-python:before{content:"\f3e2"}.fa-qq:before{content:"\f1d6"}.fa-qrcode:before{content:"\f029"}.fa-question:before{content:"\f128"}.fa-question-circle:before{content:"\f059"}.fa-quidditch:before{content:"\f458"}.fa-quinscape:before{content:"\f459"}.fa-quora:before{content:"\f2c4"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-r-project:before{content:"\f4f7"}.fa-random:before{content:"\f074"}.fa-ravelry:before{content:"\f2d9"}.fa-react:before{content:"\f41b"}.fa-readme:before{content:"\f4d5"}.fa-rebel:before{content:"\f1d0"}.fa-receipt:before{content:"\f543"}.fa-recycle:before{content:"\f1b8"}.fa-red-river:before{content:"\f3e3"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-alien:before{content:"\f281"}.fa-reddit-square:before{content:"\f1a2"}.fa-redo:before{content:"\f01e"}.fa-redo-alt:before{content:"\f2f9"}.fa-registered:before{content:"\f25d"}.fa-rendact:before{content:"\f3e4"}.fa-renren:before{content:"\f18b"}.fa-reply:before{content:"\f3e5"}.fa-reply-all:before{content:"\f122"}.fa-replyd:before{content:"\f3e6"}.fa-researchgate:before{content:"\f4f8"}.fa-resolving:before{content:"\f3e7"}.fa-retweet:before{content:"\f079"}.fa-ribbon:before{content:"\f4d6"}.fa-road:before{content:"\f018"}.fa-robot:before{content:"\f544"}.fa-rocket:before{content:"\f135"}.fa-rocketchat:before{content:"\f3e8"}.fa-rockrms:before{content:"\f3e9"}.fa-rss:before{content:"\f09e"}.fa-rss-square:before{content:"\f143"}.fa-ruble-sign:before{content:"\f158"}.fa-ruler:before{content:"\f545"}.fa-ruler-combined:before{content:"\f546"}.fa-ruler-horizontal:before{content:"\f547"}.fa-ruler-vertical:before{content:"\f548"}.fa-rupee-sign:before{content:"\f156"}.fa-safari:before{content:"\f267"}.fa-sass:before{content:"\f41e"}.fa-save:before{content:"\f0c7"}.fa-schlix:before{content:"\f3ea"}.fa-school:before{content:"\f549"}.fa-screwdriver:before{content:"\f54a"}.fa-scribd:before{content:"\f28a"}.fa-search:before{content:"\f002"}.fa-search-minus:before{content:"\f010"}.fa-search-plus:before{content:"\f00e"}.fa-searchengin:before{content:"\f3eb"}.fa-seedling:before{content:"\f4d8"}.fa-sellcast:before{content:"\f2da"}.fa-sellsy:before{content:"\f213"}.fa-server:before{content:"\f233"}.fa-servicestack:before{content:"\f3ec"}.fa-share:before{content:"\f064"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-share-square:before{content:"\f14d"}.fa-shekel-sign:before{content:"\f20b"}.fa-shield-alt:before{content:"\f3ed"}.fa-ship:before{content:"\f21a"}.fa-shipping-fast:before{content:"\f48b"}.fa-shirtsinbulk:before{content:"\f214"}.fa-shoe-prints:before{content:"\f54b"}.fa-shopping-bag:before{content:"\f290"}.fa-shopping-basket:before{content:"\f291"}.fa-shopping-cart:before{content:"\f07a"}.fa-shower:before{content:"\f2cc"}.fa-sign:before{content:"\f4d9"}.fa-sign-in-alt:before{content:"\f2f6"}.fa-sign-language:before{content:"\f2a7"}.fa-sign-out-alt:before{content:"\f2f5"}.fa-signal:before{content:"\f012"}.fa-simplybuilt:before{content:"\f215"}.fa-sistrix:before{content:"\f3ee"}.fa-sitemap:before{content:"\f0e8"}.fa-sith:before{content:"\f512"}.fa-skull:before{content:"\f54c"}.fa-skyatlas:before{content:"\f216"}.fa-skype:before{content:"\f17e"}.fa-slack:before{content:"\f198"}.fa-slack-hash:before{content:"\f3ef"}.fa-sliders-h:before{content:"\f1de"}.fa-slideshare:before{content:"\f1e7"}.fa-smile:before{content:"\f118"}.fa-smoking:before{content:"\f48d"}.fa-smoking-ban:before{content:"\f54d"}.fa-snapchat:before{content:"\f2ab"}.fa-snapchat-ghost:before{content:"\f2ac"}.fa-snapchat-square:before{content:"\f2ad"}.fa-snowflake:before{content:"\f2dc"}.fa-sort:before{content:"\f0dc"}.fa-sort-alpha-down:before{content:"\f15d"}.fa-sort-alpha-up:before{content:"\f15e"}.fa-sort-amount-down:before{content:"\f160"}.fa-sort-amount-up:before{content:"\f161"}.fa-sort-down:before{content:"\f0dd"}.fa-sort-numeric-down:before{content:"\f162"}.fa-sort-numeric-up:before{content:"\f163"}.fa-sort-up:before{content:"\f0de"}.fa-soundcloud:before{content:"\f1be"}.fa-space-shuttle:before{content:"\f197"}.fa-speakap:before{content:"\f3f3"}.fa-spinner:before{content:"\f110"}.fa-spotify:before{content:"\f1bc"}.fa-square:before{content:"\f0c8"}.fa-square-full:before{content:"\f45c"}.fa-stack-exchange:before{content:"\f18d"}.fa-stack-overflow:before{content:"\f16c"}.fa-star:before{content:"\f005"}.fa-star-half:before{content:"\f089"}.fa-staylinked:before{content:"\f3f5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-steam-symbol:before{content:"\f3f6"}.fa-step-backward:before{content:"\f048"}.fa-step-forward:before{content:"\f051"}.fa-stethoscope:before{content:"\f0f1"}.fa-sticker-mule:before{content:"\f3f7"}.fa-sticky-note:before{content:"\f249"}.fa-stop:before{content:"\f04d"}.fa-stop-circle:before{content:"\f28d"}.fa-stopwatch:before{content:"\f2f2"}.fa-store:before{content:"\f54e"}.fa-store-alt:before{content:"\f54f"}.fa-strava:before{content:"\f428"}.fa-stream:before{content:"\f550"}.fa-street-view:before{content:"\f21d"}.fa-strikethrough:before{content:"\f0cc"}.fa-stripe:before{content:"\f429"}.fa-stripe-s:before{content:"\f42a"}.fa-stroopwafel:before{content:"\f551"}.fa-studiovinari:before{content:"\f3f8"}.fa-stumbleupon:before{content:"\f1a4"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-subscript:before{content:"\f12c"}.fa-subway:before{content:"\f239"}.fa-suitcase:before{content:"\f0f2"}.fa-sun:before{content:"\f185"}.fa-superpowers:before{content:"\f2dd"}.fa-superscript:before{content:"\f12b"}.fa-supple:before{content:"\f3f9"}.fa-sync:before{content:"\f021"}.fa-sync-alt:before{content:"\f2f1"}.fa-syringe:before{content:"\f48e"}.fa-table:before{content:"\f0ce"}.fa-table-tennis:before{content:"\f45d"}.fa-tablet:before{content:"\f10a"}.fa-tablet-alt:before{content:"\f3fa"}.fa-tablets:before{content:"\f490"}.fa-tachometer-alt:before{content:"\f3fd"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-tape:before{content:"\f4db"}.fa-tasks:before{content:"\f0ae"}.fa-taxi:before{content:"\f1ba"}.fa-teamspeak:before{content:"\f4f9"}.fa-telegram:before{content:"\f2c6"}.fa-telegram-plane:before{content:"\f3fe"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-terminal:before{content:"\f120"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-th:before{content:"\f00a"}.fa-th-large:before{content:"\f009"}.fa-th-list:before{content:"\f00b"}.fa-themeisle:before{content:"\f2b2"}.fa-thermometer:before{content:"\f491"}.fa-thermometer-empty:before{content:"\f2cb"}.fa-thermometer-full:before{content:"\f2c7"}.fa-thermometer-half:before{content:"\f2c9"}.fa-thermometer-quarter:before{content:"\f2ca"}.fa-thermometer-three-quarters:before{content:"\f2c8"}.fa-thumbs-down:before{content:"\f165"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbtack:before{content:"\f08d"}.fa-ticket-alt:before{content:"\f3ff"}.fa-times:before{content:"\f00d"}.fa-times-circle:before{content:"\f057"}.fa-tint:before{content:"\f043"}.fa-toggle-off:before{content:"\f204"}.fa-toggle-on:before{content:"\f205"}.fa-toolbox:before{content:"\f552"}.fa-trade-federation:before{content:"\f513"}.fa-trademark:before{content:"\f25c"}.fa-train:before{content:"\f238"}.fa-transgender:before{content:"\f224"}.fa-transgender-alt:before{content:"\f225"}.fa-trash:before{content:"\f1f8"}.fa-trash-alt:before{content:"\f2ed"}.fa-tree:before{content:"\f1bb"}.fa-trello:before{content:"\f181"}.fa-tripadvisor:before{content:"\f262"}.fa-trophy:before{content:"\f091"}.fa-truck:before{content:"\f0d1"}.fa-truck-loading:before{content:"\f4de"}.fa-truck-moving:before{content:"\f4df"}.fa-tshirt:before{content:"\f553"}.fa-tty:before{content:"\f1e4"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-tv:before{content:"\f26c"}.fa-twitch:before{content:"\f1e8"}.fa-twitter:before{content:"\f099"}.fa-twitter-square:before{content:"\f081"}.fa-typo3:before{content:"\f42b"}.fa-uber:before{content:"\f402"}.fa-uikit:before{content:"\f403"}.fa-umbrella:before{content:"\f0e9"}.fa-underline:before{content:"\f0cd"}.fa-undo:before{content:"\f0e2"}.fa-undo-alt:before{content:"\f2ea"}.fa-uniregistry:before{content:"\f404"}.fa-universal-access:before{content:"\f29a"}.fa-university:before{content:"\f19c"}.fa-unlink:before{content:"\f127"}.fa-unlock:before{content:"\f09c"}.fa-unlock-alt:before{content:"\f13e"}.fa-untappd:before{content:"\f405"}.fa-upload:before{content:"\f093"}.fa-usb:before{content:"\f287"}.fa-user:before{content:"\f007"}.fa-user-alt:before{content:"\f406"}.fa-user-alt-slash:before{content:"\f4fa"}.fa-user-astronaut:before{content:"\f4fb"}.fa-user-check:before{content:"\f4fc"}.fa-user-circle:before{content:"\f2bd"}.fa-user-clock:before{content:"\f4fd"}.fa-user-cog:before{content:"\f4fe"}.fa-user-edit:before{content:"\f4ff"}.fa-user-friends:before{content:"\f500"}.fa-user-graduate:before{content:"\f501"}.fa-user-lock:before{content:"\f502"}.fa-user-md:before{content:"\f0f0"}.fa-user-minus:before{content:"\f503"}.fa-user-ninja:before{content:"\f504"}.fa-user-plus:before{content:"\f234"}.fa-user-secret:before{content:"\f21b"}.fa-user-shield:before{content:"\f505"}.fa-user-slash:before{content:"\f506"}.fa-user-tag:before{content:"\f507"}.fa-user-tie:before{content:"\f508"}.fa-user-times:before{content:"\f235"}.fa-users:before{content:"\f0c0"}.fa-users-cog:before{content:"\f509"}.fa-ussunnah:before{content:"\f407"}.fa-utensil-spoon:before{content:"\f2e5"}.fa-utensils:before{content:"\f2e7"}.fa-vaadin:before{content:"\f408"}.fa-venus:before{content:"\f221"}.fa-venus-double:before{content:"\f226"}.fa-venus-mars:before{content:"\f228"}.fa-viacoin:before{content:"\f237"}.fa-viadeo:before{content:"\f2a9"}.fa-viadeo-square:before{content:"\f2aa"}.fa-vial:before{content:"\f492"}.fa-vials:before{content:"\f493"}.fa-viber:before{content:"\f409"}.fa-video:before{content:"\f03d"}.fa-video-slash:before{content:"\f4e2"}.fa-vimeo:before{content:"\f40a"}.fa-vimeo-square:before{content:"\f194"}.fa-vimeo-v:before{content:"\f27d"}.fa-vine:before{content:"\f1ca"}.fa-vk:before{content:"\f189"}.fa-vnv:before{content:"\f40b"}.fa-volleyball-ball:before{content:"\f45f"}.fa-volume-down:before{content:"\f027"}.fa-volume-off:before{content:"\f026"}.fa-volume-up:before{content:"\f028"}.fa-vuejs:before{content:"\f41f"}.fa-walking:before{content:"\f554"}.fa-wallet:before{content:"\f555"}.fa-warehouse:before{content:"\f494"}.fa-weibo:before{content:"\f18a"}.fa-weight:before{content:"\f496"}.fa-weixin:before{content:"\f1d7"}.fa-whatsapp:before{content:"\f232"}.fa-whatsapp-square:before{content:"\f40c"}.fa-wheelchair:before{content:"\f193"}.fa-whmcs:before{content:"\f40d"}.fa-wifi:before{content:"\f1eb"}.fa-wikipedia-w:before{content:"\f266"}.fa-window-close:before{content:"\f410"}.fa-window-maximize:before{content:"\f2d0"}.fa-window-minimize:before{content:"\f2d1"}.fa-window-restore:before{content:"\f2d2"}.fa-windows:before{content:"\f17a"}.fa-wine-glass:before{content:"\f4e3"}.fa-wolf-pack-battalion:before{content:"\f514"}.fa-won-sign:before{content:"\f159"}.fa-wordpress:before{content:"\f19a"}.fa-wordpress-simple:before{content:"\f411"}.fa-wpbeginner:before{content:"\f297"}.fa-wpexplorer:before{content:"\f2de"}.fa-wpforms:before{content:"\f298"}.fa-wrench:before{content:"\f0ad"}.fa-x-ray:before{content:"\f497"}.fa-xbox:before{content:"\f412"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-y-combinator:before{content:"\f23b"}.fa-yahoo:before{content:"\f19e"}.fa-yandex:before{content:"\f413"}.fa-yandex-international:before{content:"\f414"}.fa-yelp:before{content:"\f1e9"}.fa-yen-sign:before{content:"\f157"}.fa-yoast:before{content:"\f2b1"}.fa-youtube:before{content:"\f167"}.fa-youtube-square:before{content:"\f431"}.sr-only{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.sr-only-focusable:active,.sr-only-focusable:focus{clip:auto;height:auto;margin:0;overflow:visible;position:static;width:auto} \ No newline at end of file diff --git a/templates/default/styles/style-base.css b/templates/default/styles/style-base.css new file mode 100644 index 000000000..b6e29c514 --- /dev/null +++ b/templates/default/styles/style-base.css @@ -0,0 +1,437 @@ +/* Global Box Sizing and Font-Smoothing */ +*, *:after, *:before { + box-sizing:border-box; + -webkit-box-sizing:border-box; + -moz-box-sizing:border-box; + -webkit-font-smoothing:antialiased; + -moz-font-smoothing:antialiased; + -o-font-smoothing:antialiased; + font-smoothing:antialiased; +} + +html { font-size: 100%; -webkit-text-size-adjust: 100%; + -ms-text-size-adjust: 100%; } + +body { + font-family: "Century Gothic", CenturyGothic, Geneva, AppleGothic, sans-serif; + line-height:18px; + color: #1c1c1c; /* Lighter on the eyes than #000 Black */ + margin: 0px; background: #cccccc; background-size: cover; +} + +img { + border: 0px; + max-width: 100%; + height: auto; + width: auto\9; /* ie8 */ +} + +/* ========================================================================== + Typography stuff goes here + ========================================================================== */ +h1,h2,h3,h4,h5,h6 { font-weight: bold; margin:0; padding:0;} +/*h1 see mediaqueries*/ +h2 {font-size: 1.2em;} +h3 {font-size: 1.1em;} +h4 {font-size: 1.0em; } +h5 {font-size: 0.83em;} +h6 {font-size: 0.75em;} + +a:hover, a:focus, a:active { outline: none; } +a { color: #000066; font-weight: 800; text-decoration: none;} +a:hover { color:#000; text-decoration: none; } +.frontpage a {display:block; } +.frontpage a:hover { width: 100%; background-color: #778899;} +.books:hover { width: 100%; background-color: #778899; } +.link a:hover { display:inline-block; width: 100%; background-color: #778899; /*Dirty IE Hack*/ zoom: 1; *display: inline;} + +.mfp-content .bookpopup { + position: relative; + background: #FFF; + padding: 20px; + width: auto; + max-width: 700px; + margin: 20px auto; + min-height: 198px; +} + +#email { +width: 300px; +} + +.filtered { +display: none; +} + +#filter { +clear:both; +} + +#filter ul { +margin: 0; +padding: 0; +list-style-type: none; +text-align: left; +text-transform:none; +} + +#filter ul li { +cursor: pointer; +} + +li { +display: inline-block; +padding: .2em 1em; +margin: 2px; +color: black; +background-color: white; +opacity: 0.5; +} + +.filter-include { + border-left:thick solid blue; + opacity: 1; +} + +.filter-include:after { + content: " \2713"; /* Tick mark */ +} + +.filter-exclude { + border-right:thick solid red; + opacity: 1; +} + +.filter-exclude:after { + content: " \2717"; /* Check mark */ +} + +img +{ +margin:0; +padding:0; +border:0; +} + +/* ============================================================================= + Main container stuff goes here and other globals + ========================================================================== */ +.container{ + background: #414141; border:1px solid #000; + max-width:800px;width:95%;margin:0 auto;position:relative; } + +/* ============================================================================= + Header stuff goes here + ========================================================================== */ +header { + clear:both; + color:white; + text-align:center; + text-transform:uppercase; + display:block; + min-height:70px; +} + +.hicon{ + display:inline-block; + color:lightgray; + text-align: center; + margin: 0 2px; +} + +.submit { + color: lightgray; + cursor: pointer; + background-color: transparent; + background-image: none; + border-color: transparent; + display: table-cell; +} + +.hicon64{ + font-size: 64px; + line-height: 64px; + width: 64px; + height: 64px; +} + +.hicon32{ + width: 32px; + height: 32px; +} + +.headleft { + float: left; +} + +.headcenter +{ +float:none; +margin:auto; +text-align:center; +height:70px; +display:table; +} + +header h1{ + display: table-cell; + vertical-align: middle; + text-align: center; + line-height: 100%; +} + +.headright { + float: right; + /*for ios compatibility*/ + cursor: pointer; +} + +/* ============================================================================= + Section and Article stuff goes here + ========================================================================== */ +section { +clear:both; +background-color: #fff; +} + +article { +border-bottom: 1px solid black; +max-width:800px; +} + +/*-------------frontpage article-------------*/ + +.frontpage h2 { + padding: 5px 0 0 5px; +} + +.frontpage h4 { + padding: 5px 0 5px 20px; + font-style: italic; +} + +/*-------------books article-------------*/ +.books { + clear: both; + min-height: 90px; + position: relative; +} + +.books .cover { + float:left; + margin: 4px 10px 4px 4px; + width: 60px; + height: 82px; + position: absolute; +} + +.books .fancydetail .fullclickpopup { + margin: 0px 0px 4px 75px; +} + +.bookpopup .cover { + float:left; + margin: 4px 10px 4px 4px; + width: 100px; + height: 150px; +} + +.cover img { + max-width:100%; + max-height:100%; + color: white; +} + +.download { + float: right; + line-height:40px; + text-align: right; + margin: 6px; +} + +.download a { + background: darkgray; + color: #EEE; + text-decoration : none; + font-weight: bold; + padding: 5px 10px 5px 10px; + text-align: center; +} + +.download img { + vertical-align:middle; +} + +.books h4{ + display: inline; + font-style: italic; +} + +/*-------------books popup article-------------*/ +.bookpopup h2{ + margin: 15px 15px; +} + +.bookpopup h3{ + display:inline; /*Dirty IE Hack*/ zoom: 1; *display: inline; +} + +.bookpopup h4{ + border-top: 1px solid black; +} + +.fullclickpopup{ + display: block; + min-height: 86px; +} + +section .bookpopup{ + padding: 8px 8px; + min-height: 175px; +} + +/* ============================================================================= + Footer stuff goes here + ========================================================================== */ +footer +{ +clear:both; +color:white; +height:32px; +} + +.footleft +{ +float:left; +height:32px; +} + + +.footright +{ +float:right; +height:32px; +} + +.footcenter +{ +margin:auto; +text-align:center; +height:32px; +display:table; +font-weight: bold; +} + +.footcenter p, .footcenter a +{ +display: table-cell; +vertical-align: middle; +text-align: center; +line-height: 100%; +} + +/* ============================================================================= + Aside stuff goes here + ========================================================================== */ +#tool +{ +width:100%; +} + + +/*-------------Search Aside-------------*/ +#tool input[type=text], .twitter-typeahead +{ +vertical-align: middle; +width: 100%; +color: black; +background-color: white; +} + +.tt-hint, .tt-query { + width: 100%; + } + +.stop select +{ +vertical-align: middle; +margin: 4px; +color: black; +} + +#sort +{ +cursor:pointer; +} + +#searchForm { +display: table; +padding: 0 2px; +} + +.stop +{ +display: table-cell; +vertical-align: middle; +width: 100%; +} + +.tt-dropdown-menu { + width: 322px; + text-align: left; + margin-top: 6px; + color: #000066; + padding: 4px 0; + background-color: #fff; + border: 1px solid #ccc; +} + +.tt-header { + border-bottom: 1px solid #CCCCCC; + font-weight: bold; +} + +.tt-suggestion { + padding: 3px 20px; + line-height: 14px; +} + +.tt-suggestion.tt-cursor { + color: #1c1c1c; + background-color: #778899; +} + +.tt-suggestion p { + margin: 0; +} + +/* ============================================================================= + Mediaquerie stuff goes here + ========================================================================== */ +/* 100px and greater */ +@media only screen and (min-width: 100px) { +h1 {font-size: 1em;} +.container { width:100%; } +} + +/* 320px and greater */ +@media only screen and (min-width: 320px) { +h1 {font-size: 1.2em;} +} + +/* 480px and greater */ +@media only screen and (min-width: 480px) { +h1 {font-size: 1.5em;} +body { font-size: 1em;/*12px/16px */ + font-weight:450; /* Better supported than 'lighter' attribute */ + } +} + +/* 768px and greater */ +@media only screen and (min-width: 768px) { +h1 {font-size: 2em; line-height: 1em;} +body { margin: 5px; + font-size: 0.85em;/*12px/16px */ + font-weight:400; /* Better supported than 'lighter' attribute */ + } +} diff --git a/templates/default/styles/style-default.css b/templates/default/styles/style-default.css new file mode 100644 index 000000000..a297ea99f --- /dev/null +++ b/templates/default/styles/style-default.css @@ -0,0 +1,58 @@ +@import url("style-base.css"); + + +/* ============================================================================= + Main container stuff goes here and other globals + ========================================================================== */ +.container { +border-radius:10px; +} + +/* ============================================================================= + Header stuff goes here + ========================================================================== */ +header { + box-shadow:inset 0px -5px 8px #000000; + border-radius: 10px 10px 0px 0px; +} + +.hicon{ + text-shadow: 2px 2px 2px black; +} + +.submit { + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; +} + +header h1{ + display: table-cell; + vertical-align: middle; + text-align: center; + line-height: 100%; +} + +.download a { + border-radius: 6px; + box-shadow:0 0 10px #000; + background: radial-gradient(#666, black); +} + +footer +{ +box-shadow:inset 0px 5px 8px #000000; +border-radius: 0px 0px 10px 10px; +} + + +/* ============================================================================= + Mediaquerie stuff goes here + ========================================================================== */ +/* 768px and greater */ +@media only screen and (min-width: 768px) { +.container { box-shadow:0 0 20px #000; } +} \ No newline at end of file diff --git a/templates/default/styles/style-eink.css b/templates/default/styles/style-eink.css new file mode 100644 index 000000000..2cc0b53ab --- /dev/null +++ b/templates/default/styles/style-eink.css @@ -0,0 +1,63 @@ +@import url("style-base.css"); + +a { + color: black; + font-weight: bold; +} +.frontpage a:hover, .books:hover { background-color: white;} + +#filter ul { +font-variant: normal; +} + +li, .container { +background-color: white; +} + +header { + color: black; + text-transform: none; + border-bottom: 2px dashed gray; + font-variant: small-caps; + letter-spacing: 2px; +} + +#tool input[type=text], .twitter-typeahead +{ + font-variant: normal; +} + +.hicon, .footcenter, .submit, .fullclickpopup{ + color:black; +} + +.frontpage h2 { + text-align: center; + letter-spacing: 2px; + color: black; + font-family: "Helvetica Neue", Arial, Helvetica, Geneva, sans-serif; +} + +.frontpage h4 { + padding: 5px 0; + text-align: center; + color: gray; + font-size: 13px; + text-decoration: overline; + } + +.download a { + background: black; + color: white; +} + + +.tt-dropdown-menu { + color: black; + background-color: white; + border: 1px solid #ccc; +} +.tt-suggestion.tt-is-under-cursor { + color: black; + background-color: white; +} \ No newline at end of file diff --git a/templates/default/styles/style-iphone.css b/templates/default/styles/style-iphone.css new file mode 100644 index 000000000..6e2f68188 --- /dev/null +++ b/templates/default/styles/style-iphone.css @@ -0,0 +1,116 @@ +@import url("style-base.css"); +/* ============================================================================= + Main container goes here and other globals + ========================================================================== */ + +.st, .sp, .sa, .se, .ss { + font: normal normal 400 14px Helvetica Neue Interface, Helvetica Neue, Helvetica; + color: #007aff; } + +.st { + font-weight: 600; } + +.frontpage a { + display: block; } + .frontpage a:hover { + width: 100%; + background-color: #e2e1e6; } + +.books:hover { + width: 100%; + background-color: #e2e1e6; } + +a { + color: #007aff; + font-weight: 600; } + a:hover { + color: black; } + +/*iphone - reduction des tailles de police et taille fixe en px*/ +body { + font: normal normal 300 12px Helvetica Neue Interface, Helvetica Neue, Helvetica; + color: black; } + +h2 { + font: normal normal 400 16px Helvetica Neue Interface, Helvetica Neue, Helvetica; + color: #007aff; } + +h3 { + font: normal normal 400 14px Helvetica Neue Interface, Helvetica Neue, Helvetica; + color: black; } + +h4 { + font: normal normal 400 14px Helvetica Neue Interface, Helvetica Neue, Helvetica; + color: black; } + +/*iphone - Suppression des arrondis +.container { +border-radius:10px; +} +*/ +/* ============================================================================= + Header stuff goes here + ========================================================================== */ +/* +header { +iphone - Suppression ombrage (bug avec formulaire recherche) + box-shadow:inset 0px -5px 8px #000000; +iphone - Suppression des arrondis + border-radius: 10px 10px 0px 0px; +}*/ +.hicon { + text-shadow: 2px 2px 2px black; } + +/*iphone - icone trop bas */ +#tool .hicon32 { + margin-top: -5px; } + +.submit { + border-radius: 0; + box-shadow: none; } + +header h1 { + vertical-align: middle; + text-align: center; + font: normal normal 500 24px Helvetica Neue Interface, Helvetica Neue, Helvetica; + color: #007aff; } + +.download a { + font: normal normal 400 16px Helvetica Neue Interface, Helvetica Neue, Helvetica; + color: #007aff; + box-shadow: 0 0 10px #c8c7cc; + color: #007aff; + border-color: #007aff; + border-radius: 5px; + border-style: solid; + border-width: 1px; + background: white; } + +/*iphone - bouton de donwload en haut dans book detail +(manque de place en mode paysage)*/ +.bookpopup .download { + float: none; + margin: -12px 30px -2px 4px; } + +/*iphone - modification des marges pour cover dans detail*/ +.bookpopup .cover { + margin: 27px 4px 4px 0px; } + +.mfp-content .bookpopup { + /*iphone - Taille minimum du detail du livre en popup + pour que la pochette ne depasse pas + (pas seulement pour iphone) */ + min-height: 210px; } + +footer { + box-shadow: inset 0px 5px 10px #000000; + /*iphone - Suppression des arrondis + border-radius: 0px 0px 10px 10px;*/ } + +/* ============================================================================= + Media query stuff goes here + ========================================================================== */ +/* 768px and greater */ +@media only screen and (min-width: 768px) { + .container { + box-shadow: 0 0 20px #000; } } diff --git a/templates/default/styles/style-iphone7.css b/templates/default/styles/style-iphone7.css new file mode 100644 index 000000000..85b18b9d6 --- /dev/null +++ b/templates/default/styles/style-iphone7.css @@ -0,0 +1,116 @@ +@import url("style-base.css"); +/* ============================================================================= + Main container stuff goes here and other globals + ========================================================================== */ + +.st, .sp, .sa, .se, .ss { + font: -apple-system-body; + color: #007aff; } + +.st { + font-weight: 600; } + +.frontpage a { + display: block; } + .frontpage a:hover { + width: 100%; + background-color: #e2e1e6; } + +.books:hover { + width: 100%; + background-color: #e2e1e6; } + +a { + color: #007aff; + font-weight: 600; } + a:hover { + color: black; } + +/*iphone - reduction des tailles de police et taille fixe en px*/ +body { + font: -apple-system-body; + color: black; } + +h2 { + font: -apple-system-subheadline; + color: #007aff; } + +h3 { + font: -apple-system-subheadline; + color: black; } + +h4 { + font: -apple-system-subheadline; + color: black; } + +/*iphone - Suppression des arrondis +.container { +border-radius:10px; +} +*/ +/* ============================================================================= + Header stuff goes here + ========================================================================== */ +/* +header { +iphone - Suppression ombrage (bug avec formulaire recherche) + box-shadow:inset 0px -5px 8px #000000; +iphone - Suppression des arrondis + border-radius: 10px 10px 0px 0px; +}*/ +.hicon { + text-shadow: 2px 2px 2px black; } + +/*iphone - icone trop bas */ +#tool .hicon32 { + margin-top: -5px; } + +.submit { + border-radius: 0; + box-shadow: none; } + +header h1 { + vertical-align: middle; + text-align: center; + font: -apple-system-headline; + color: #007aff; } + +.download a { + font: -apple-system-subheadline; + color: #007aff; + box-shadow: 0 0 10px #c8c7cc; + color: #007aff; + border-color: #007aff; + border-radius: 5px; + border-style: solid; + border-width: 1px; + background: white; } + +/*iphone - bouton de donwload en haut dans book detail +(manque de place en mode paysage)*/ +.bookpopup .download { + float: none; + margin: -12px 30px -2px 4px; } + +/*iphone - modification des marges pour cover dans detail*/ +.bookpopup .cover { + margin: 27px 4px 4px 0px; } + +.mfp-content .bookpopup { + /*iphone - Taille minimum du detail du livre en popup + pour que la pochette ne depasse pas + (pas seulement pour iphone) */ + min-height: 210px; } + +footer { + box-shadow: inset 0px 5px 10px #000000; + /*iphone - Suppression des arrondis + border-radius: 0px 0px 10px 10px;*/ } + +/* ============================================================================= + Media query stuff goes here + ========================================================================== */ +/* 768px and greater */ +@media only screen and (min-width: 768px) { + .container { + box-shadow: 0 0 20px #000; } } diff --git a/templates/default/suggestion.html b/templates/default/suggestion.html new file mode 100644 index 000000000..1107dadee --- /dev/null +++ b/templates/default/suggestion.html @@ -0,0 +1 @@ +

    {{=it.title}}

    \ No newline at end of file diff --git a/templates/default/webfonts/fa-solid-900.eot b/templates/default/webfonts/fa-solid-900.eot new file mode 100644 index 000000000..a32dc8aeb Binary files /dev/null and b/templates/default/webfonts/fa-solid-900.eot differ diff --git a/templates/default/webfonts/fa-solid-900.svg b/templates/default/webfonts/fa-solid-900.svg new file mode 100644 index 000000000..94bb8f27b --- /dev/null +++ b/templates/default/webfonts/fa-solid-900.svg @@ -0,0 +1,1896 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/templates/default/webfonts/fa-solid-900.ttf b/templates/default/webfonts/fa-solid-900.ttf new file mode 100644 index 000000000..4e518ad49 Binary files /dev/null and b/templates/default/webfonts/fa-solid-900.ttf differ diff --git a/templates/default/webfonts/fa-solid-900.woff b/templates/default/webfonts/fa-solid-900.woff new file mode 100644 index 000000000..277d8cebc Binary files /dev/null and b/templates/default/webfonts/fa-solid-900.woff differ diff --git a/templates/default/webfonts/fa-solid-900.woff2 b/templates/default/webfonts/fa-solid-900.woff2 new file mode 100644 index 000000000..69bd4299c Binary files /dev/null and b/templates/default/webfonts/fa-solid-900.woff2 differ diff --git a/test/BaseWithCustomColumns/metadata.db b/test/BaseWithCustomColumns/metadata.db new file mode 100644 index 000000000..ce359f91c Binary files /dev/null and b/test/BaseWithCustomColumns/metadata.db differ diff --git a/test/BaseWithOneBook/metadata.db b/test/BaseWithOneBook/metadata.db new file mode 100644 index 000000000..a1f24b374 Binary files /dev/null and b/test/BaseWithOneBook/metadata.db differ diff --git a/test/BaseWithSomeBooks/Lewis Carroll/Alice's Adventures in Wonderland (17)/Alice's Adventures in Wonderland - Lewis Carroll.epub b/test/BaseWithSomeBooks/Lewis Carroll/Alice's Adventures in Wonderland (17)/Alice's Adventures in Wonderland - Lewis Carroll.epub new file mode 100644 index 000000000..376ab504e Binary files /dev/null and b/test/BaseWithSomeBooks/Lewis Carroll/Alice's Adventures in Wonderland (17)/Alice's Adventures in Wonderland - Lewis Carroll.epub differ diff --git a/test/BaseWithSomeBooks/Lewis Carroll/Alice's Adventures in Wonderland (17)/cover.jpg b/test/BaseWithSomeBooks/Lewis Carroll/Alice's Adventures in Wonderland (17)/cover.jpg new file mode 100644 index 000000000..da5d852d9 Binary files /dev/null and b/test/BaseWithSomeBooks/Lewis Carroll/Alice's Adventures in Wonderland (17)/cover.jpg differ diff --git a/test/BaseWithSomeBooks/Lewis Carroll/Alice's Adventures in Wonderland (17)/metadata.opf b/test/BaseWithSomeBooks/Lewis Carroll/Alice's Adventures in Wonderland (17)/metadata.opf new file mode 100644 index 000000000..9d3085ce0 --- /dev/null +++ b/test/BaseWithSomeBooks/Lewis Carroll/Alice's Adventures in Wonderland (17)/metadata.opf @@ -0,0 +1,32 @@ + + + + 15 + cdcb34f1-d554-409b-8620-9a4a56c58c68 + Alice's Adventures in Wonderland + Lewis Carroll + calibre (1.3.0) [http://calibre-ebook.com] + 1897-01-13T23:00:00+00:00 + Alice's Adventures in Wonderland (1865) is a novel written by English author Charles Lutwidge Dodgson, better known under the pseudonym Lewis Carroll. It tells the story of a girl named Alice who falls down a rabbit-hole into a fantasy world populated by peculiar and anthropomorphic creatures. +The tale is filled with allusions to Dodgson's friends (and enemies), and to the lessons that British schoolchildren were expected to memorize. The tale plays with logic in ways that have made the story of lasting popularity with adults as well as children. It is considered to be one of the most characteristic examples of the genre of literary nonsense, and its narrative course and structure has been enormously influential, mainly in the fantasy genre. + Feedbooks + urn|uuid|bca234de-5f3c-11e1-837d-001cc0a62c0b + http|//www.feedbooks.com/book/22 + eng + Fantasy + Juvenile + Fiction + + + + + + + + + + + + + + diff --git a/test/BaseWithSomeBooks/metadata.db b/test/BaseWithSomeBooks/metadata.db new file mode 100644 index 000000000..cc869580e Binary files /dev/null and b/test/BaseWithSomeBooks/metadata.db differ diff --git a/test/EpubFsTest.php b/test/EpubFsTest.php new file mode 100644 index 000000000..4b1a98548 --- /dev/null +++ b/test/EpubFsTest.php @@ -0,0 +1,111 @@ + + */ + +require(dirname(__FILE__) . "/../epubfs.php"); +require(dirname(__FILE__) . "/config_test.php"); +use PHPUnit\Framework\TestCase; + +class EpubFsTest extends TestCase +{ + private static $book; + private static $add; + + + public static function setUpBeforeClass(): void + { + $idData = 20; + self::$add = "data=$idData&"; + $myBook = Book::getBookByDataId($idData); + + self::$book = new EPub($myBook->getFilePath("EPUB", $idData)); + self::$book->initSpineComponent(); + } + + public function testUrlImage() + { + $data = getComponentContent(self::$book, "cover.xml", self::$add); + + $src = ""; + if (preg_match("/src\=\'(.*?)\'/", $data, $matches)) { + $src = $matches [1]; + } + $this->assertEquals('epubfs.php?data=20&comp=images~SLASH~cover.png', $src); + } + + public function testUrlHref() + { + $data = getComponentContent(self::$book, "title.xml", self::$add); + + $src = ""; + if (preg_match("/src\=\'(.*?)\'/", $data, $matches)) { + $src = $matches [1]; + } + $this->assertEquals('epubfs.php?data=20&comp=images~SLASH~logo~DASH~feedbooks~DASH~tiny.png', $src); + + $href = ""; + if (preg_match("/href\=\'(.*?)\'/", $data, $matches)) { + $href = $matches [1]; + } + $this->assertEquals('epubfs.php?data=20&comp=css~SLASH~title.css', $href); + } + + public function testImportCss() + { + $data = getComponentContent(self::$book, "css~SLASH~title.css", self::$add); + + $import = ""; + if (preg_match("/import \'(.*?)\'/", $data, $matches)) { + $import = $matches [1]; + } + $this->assertEquals('epubfs.php?data=20&comp=css~SLASH~page.css', $import); + } + + public function testUrlInCss() + { + $data = getComponentContent(self::$book, "css~SLASH~main.css", self::$add); + + $src = ""; + if (preg_match("/url\s*\(\'(.*?)\'\)/", $data, $matches)) { + $src = $matches [1]; + } + $this->assertEquals('epubfs.php?data=20&comp=fonts~SLASH~times.ttf', $src); + } + + public function testDirectLink() + { + $data = getComponentContent(self::$book, "main10.xml", self::$add); + + $src = ""; + if (preg_match("/href\='(.*?)' title=\"Direct Link\"/", $data, $matches)) { + $src = $matches [1]; + } + $this->assertEquals('epubfs.php?data=20&comp=main2.xml', $src); + } + + public function testDirectLinkWithAnchor() + { + $data = getComponentContent(self::$book, "main10.xml", self::$add); + + $src = ""; + if (preg_match("/href\='(.*?)' title=\"Direct Link with anchor\"/", $data, $matches)) { + $src = $matches [1]; + } + $this->assertEquals('epubfs.php?data=20&comp=main2.xml#anchor', $src); + } + + public function testAnchorOnly() + { + $data = getComponentContent(self::$book, "main10.xml", self::$add); + + $src = ""; + if (preg_match("/href\='(.*?)' title=\"Link to anchor\"/", $data, $matches)) { + $src = $matches [1]; + } + $this->assertEquals('#anchor', $src); + } +} diff --git a/test/OPDSTest.php b/test/OPDSTest.php new file mode 100644 index 000000000..b8eb509fb --- /dev/null +++ b/test/OPDSTest.php @@ -0,0 +1,291 @@ + + */ + +require_once(dirname(__FILE__) . "/config_test.php"); +use PHPUnit\Framework\TestCase; + +define("OPDS_RELAX_NG", dirname(__FILE__) . "/opds-relax-ng/opds_catalog_1_1.rng"); +define("OPENSEARCHDESCRIPTION_RELAX_NG", dirname(__FILE__) . "/opds-relax-ng/opensearchdescription.rng"); +define("JING_JAR", dirname(__FILE__) . "/jing.jar"); +define("OPDSVALIDATOR_JAR", dirname(__FILE__) . "/OPDSValidator.jar"); +define("TEST_FEED", dirname(__FILE__) . "/text.atom"); + +class OpdsTest extends TestCase +{ + public static function setUpBeforeClass(): void + { + global $config; + $config['calibre_directory'] = dirname(__FILE__) . "/BaseWithSomeBooks/"; + Base::clearDb(); + } + + public static function tearDownAfterClass(): void + { + if (!file_exists(TEST_FEED)) { + return; + } + unlink(TEST_FEED); + } + + public function jingValidateSchema($feed, $relax = OPDS_RELAX_NG) + { + $path = ""; + $code = null; + $res = system($path . 'java -jar "' . JING_JAR . '" "' . $relax . '" "' . $feed . '"', $code); + if ($res != '') { + echo 'RelaxNG validation error: '.$res; + return false; + //} elseif (isset($code) && $code > 0) { + // echo 'Return code: '.strval($code); + // return false; + } else { + return true; + } + } + + public function opdsValidator($feed) + { + $oldcwd = getcwd(); // Save the old working directory + chdir("test"); + $path = ""; + $res = system($path . 'java -jar "' . OPDSVALIDATOR_JAR . '" "' . $feed . '"'); + chdir($oldcwd); + if ($res != '') { + echo 'OPDS validation error: '.$res; + return false; + } else { + return true; + } + } + + public function opdsCompleteValidation($feed) + { + return $this->jingValidateSchema($feed) && $this->opdsValidator($feed); + } + + public function testPageIndex() + { + global $config; + $page = Base::PAGE_INDEX; + $query = null; + $qid = null; + $n = "1"; + + $_SERVER['QUERY_STRING'] = ""; + $config['cops_subtitle_default'] = "My subtitle"; + + $currentPage = Page::getPage($page, $qid, $query, $n); + $currentPage->InitializeContent(); + + $OPDSRender = new OPDSRenderer(); + + file_put_contents(TEST_FEED, $OPDSRender->render($currentPage)); + $this->AssertTrue($this->jingValidateSchema(TEST_FEED)); + $this->AssertTrue($this->opdsCompleteValidation(TEST_FEED)); + + $_SERVER ["HTTP_USER_AGENT"] = "XXX"; + $config['cops_generate_invalid_opds_stream'] = "1"; + + file_put_contents(TEST_FEED, $OPDSRender->render($currentPage)); + $this->AssertFalse($this->jingValidateSchema(TEST_FEED)); + $this->AssertFalse($this->opdsValidator(TEST_FEED)); + + unset($_SERVER['QUERY_STRING']); + unset($_SERVER['HTTP_USER_AGENT']); + $config['cops_generate_invalid_opds_stream'] = "0"; + } + + /** + * @dataProvider providerPage + */ + public function testMostPages($page, $query) + { + $qid = null; + $n = "1"; + $_SERVER['QUERY_STRING'] = "?page={$page}"; + if (!empty($query)) { + $_SERVER['QUERY_STRING'] .= "&query={$query}"; + } + $_SERVER['REQUEST_URI'] = "feed.php" . $_SERVER['QUERY_STRING']; + + $currentPage = Page::getPage($page, $qid, $query, $n); + $currentPage->InitializeContent(); + + $OPDSRender = new OPDSRenderer(); + + file_put_contents(TEST_FEED, $OPDSRender->render($currentPage)); + $this->AssertTrue($this->opdsCompleteValidation(TEST_FEED)); + + unset($_SERVER['QUERY_STRING']); + unset($_SERVER['REQUEST_URI']); + } + + public function providerPage() + { + return [ + [Base::PAGE_OPENSEARCH, "car"], + [Base::PAGE_ALL_AUTHORS, null], + [Base::PAGE_ALL_SERIES, null], + [Base::PAGE_ALL_TAGS, null], + [Base::PAGE_ALL_PUBLISHERS, null], + [Base::PAGE_ALL_LANGUAGES, null], + [Base::PAGE_ALL_RECENT_BOOKS, null], + [Base::PAGE_ALL_BOOKS, null], + ]; + } + + public function testPageIndexMultipleDatabase() + { + global $config; + $config['calibre_directory'] = ["Some books" => dirname(__FILE__) . "/BaseWithSomeBooks/", + "One book" => dirname(__FILE__) . "/BaseWithOneBook/"]; + Base::clearDb(); + $page = Base::PAGE_INDEX; + $query = null; + $qid = "1"; + $n = "1"; + $_SERVER['QUERY_STRING'] = ""; + + $currentPage = Page::getPage($page, $qid, $query, $n); + $currentPage->InitializeContent(); + + $OPDSRender = new OPDSRenderer(); + + file_put_contents(TEST_FEED, $OPDSRender->render($currentPage)); + $this->AssertTrue($this->opdsCompleteValidation(TEST_FEED)); + + unset($_SERVER['QUERY_STRING']); + $config['calibre_directory'] = dirname(__FILE__) . "/BaseWithSomeBooks/"; + Base::clearDb(); + } + + public function testOpenSearchDescription() + { + $_SERVER['QUERY_STRING'] = ""; + + $OPDSRender = new OPDSRenderer(); + + file_put_contents(TEST_FEED, $OPDSRender->getOpenSearch()); + $this->AssertTrue($this->jingValidateSchema(TEST_FEED, OPENSEARCHDESCRIPTION_RELAX_NG)); + + unset($_SERVER['QUERY_STRING']); + } + + public function testPageAuthorMultipleDatabase() + { + global $config; + $config['calibre_directory'] = ["Some books" => dirname(__FILE__) . "/BaseWithSomeBooks/", + "One book" => dirname(__FILE__) . "/BaseWithOneBook/"]; + Base::clearDb(); + $page = Base::PAGE_AUTHOR_DETAIL; + $query = null; + $qid = "1"; + $n = "1"; + $_SERVER['QUERY_STRING'] = "page=" . Base::PAGE_AUTHOR_DETAIL . "&id=1"; + $_GET ["db"] = "0"; + + $currentPage = Page::getPage($page, $qid, $query, $n); + $currentPage->InitializeContent(); + + $OPDSRender = new OPDSRenderer(); + + file_put_contents(TEST_FEED, $OPDSRender->render($currentPage)); + $this->AssertTrue($this->opdsCompleteValidation(TEST_FEED)); + + unset($_SERVER['QUERY_STRING']); + unset($_GET['db']); + $config['calibre_directory'] = dirname(__FILE__) . "/BaseWithSomeBooks/"; + Base::clearDb(); + } + + public function testPageAuthorsDetail() + { + global $config; + $page = Base::PAGE_AUTHOR_DETAIL; + $query = null; + $qid = "1"; + $n = "1"; + $_SERVER['QUERY_STRING'] = "page=" . Base::PAGE_AUTHOR_DETAIL . "&id=1&n=1"; + + $config['cops_max_item_per_page'] = 2; + + // First page + + $currentPage = Page::getPage($page, $qid, $query, $n); + $currentPage->InitializeContent(); + + $OPDSRender = new OPDSRenderer(); + + file_put_contents(TEST_FEED, $OPDSRender->render($currentPage)); + $this->AssertTrue($this->opdsCompleteValidation(TEST_FEED)); + + // Second page + + $n = 2; + $currentPage = Page::getPage($page, $qid, $query, $n); + $currentPage->InitializeContent(); + + $OPDSRender = new OPDSRenderer(); + + file_put_contents(TEST_FEED, $OPDSRender->render($currentPage)); + $this->AssertTrue($this->opdsCompleteValidation(TEST_FEED)); + + unset($_SERVER['QUERY_STRING']); + // No pagination + $config['cops_max_item_per_page'] = -1; + } + + public function testPageAuthorsDetail_WithFacets() + { + global $config; + $page = Base::PAGE_AUTHOR_DETAIL; + $query = null; + $qid = "1"; + $n = "1"; + $_SERVER['QUERY_STRING'] = "page=" . Base::PAGE_AUTHOR_DETAIL . "&id=1&n=1"; + $_GET["tag"] = "Short Stories"; + + $config['cops_books_filter'] = ["Only Short Stories" => "Short Stories", "No Short Stories" => "!Short Stories"]; + + $currentPage = Page::getPage($page, $qid, $query, $n); + $currentPage->InitializeContent(); + + $OPDSRender = new OPDSRenderer(); + + file_put_contents(TEST_FEED, $OPDSRender->render($currentPage)); + $this->AssertTrue($this->opdsCompleteValidation(TEST_FEED)); + + unset($_SERVER['QUERY_STRING']); + unset($_GET['tag']); + $config['cops_books_filter'] = []; + } + + public function testPageAuthorsDetail_WithoutAnyId() + { + global $config; + $page = Base::PAGE_AUTHOR_DETAIL; + $query = null; + $qid = "1"; + $n = "1"; + $_SERVER['QUERY_STRING'] = "page=" . Base::PAGE_AUTHOR_DETAIL . "&id=1&n=1"; + $_SERVER['REQUEST_URI'] = "index.php?XXXX"; + + + $currentPage = Page::getPage($page, $qid, $query, $n); + $currentPage->InitializeContent(); + $currentPage->idPage = null; + + $OPDSRender = new OPDSRenderer(); + + file_put_contents(TEST_FEED, $OPDSRender->render($currentPage)); + $this->AssertTrue($this->opdsCompleteValidation(TEST_FEED)); + + unset($_SERVER['QUERY_STRING']); + unset($_SERVER['REQUEST_URI']); + } +} diff --git a/test/OPDSValidator.jar b/test/OPDSValidator.jar new file mode 100644 index 000000000..3fe7b3390 Binary files /dev/null and b/test/OPDSValidator.jar differ diff --git a/test/Sauce.php b/test/Sauce.php new file mode 100644 index 000000000..447a59b23 --- /dev/null +++ b/test/Sauce.php @@ -0,0 +1,225 @@ + 'firefox', + 'desiredCapabilities' => [ + 'version' => '28', + 'platform' => 'Windows 8.1', + ], + ], + // run IE11 on Windows 8 on Sauce + [ + 'browserName' => 'internet explorer', + 'desiredCapabilities' => [ + 'version' => '11', + 'platform' => 'Windows 8.1', + ], + ], + // run Safari 7 on Maverick on Sauce + [ + 'browserName' => 'safari', + 'desiredCapabilities' => [ + 'version' => '7', + 'platform' => 'OS X 10.9', + ], + ], + // run Mobile Safari on iOS + [ + 'browserName' => 'iphone', + 'desiredCapabilities' => [ + 'app' => 'safari', + 'device' => 'iPhone 6', + 'version' => '9.2', + 'platform' => 'OS X 10.10', + ], + ], + // run Mobile Browser on Android + [ + 'browserName' => 'Android', + 'desiredCapabilities' => [ + 'version' => '5.1', + 'platform' => 'Linux', + ], + ], + // run Chrome on Linux on Sauce + [ + 'browserName' => 'chrome', + 'desiredCapabilities' => [ + 'version' => '33', + 'platform' => 'Linux', + ], + ], + + + // run Chrome locally + //array( + //'browserName' => 'chrome', + //'local' => true, + //'sessionStrategy' => 'shared' + //) + ]; + + public function setUp() + { + if (isset($_SERVER["TRAVIS_JOB_NUMBER"])) { + $caps = $this->getDesiredCapabilities(); + $caps['build'] = getenv("TRAVIS_JOB_NUMBER"); + $caps['tunnel-identifier'] = getenv("TRAVIS_JOB_NUMBER"); + $caps['idle-timeout'] = "180"; + $this->setDesiredCapabilities($caps); + } + parent::setUp(); + } + + public function setUpPage() + { + if (isset($_SERVER["TRAVIS_JOB_NUMBER"])) { + $this->url('http://127.0.0.1:8080/index.php'); + } else { + $this->url('http://cops-demo.slucas.fr/index.php'); + } + + $driver = $this; + $title_test = function ($value) use ($driver) { + $text = $driver->byXPath('//h1')->text(); + return $text == $value; + }; + + $this->spinAssert("Home Title", $title_test, [ "COPS DEMO" ]); + } + + public function string_to_ascii($string) + { + $ascii = null; + + for ($i = 0; $i < strlen($string); $i++) { + $ascii += ord($string[$i]); + } + + return mb_detect_encoding($string) . "X" . $ascii; + } + + // public function testTitle() + // { + // $driver = $this; + // $title_test = function($value) use ($driver) { + // $text = $driver->byXPath('//h1')->text (); + // return $text == $value; + // }; + + // $author = $this->byXPath ('//h2[contains(text(), "Authors")]'); + // $author->click (); + + // $this->spinAssert("Author Title", $title_test, [ "AUTHORS" ]); + // } + + // public function testCog() + // { + // $cog = $this->byId ("searchImage"); + + // $search = $this->byName ("query"); + // $this->assertFalse ($search->displayed ()); + + // $cog->click (); + + // $search = $this->byName ("query"); + // $this->assertTrue ($search->displayed ()); + // } + + public function testFilter() + { + $driver = $this; + $title_test = function ($value) use ($driver) { + $text = $driver->byXPath('//h1')->text(); + return $text == $value; + }; + + $element_present = function ($using, $id) use ($driver) { + $elements = $driver->elements($driver->using($using)->value($id)); + return count($elements) == 1; + }; + + // Click on the wrench to enable tag filtering + $this->spinWait("", $element_present, [ "class name", 'icon-wrench']); + $this->byClassName("icon-wrench")->click(); + + $this->spinWait("", $element_present, [ "id", "html_tag_filter"]); + $this->byId("html_tag_filter")->click(); + + // Go back to home screen + $this->byClassName("icon-home")->click(); + + $this->spinAssert("Home Title", $title_test, [ "COPS DEMO" ]); + + // Go on the recent page + $author = $this->byXPath('//h2[contains(text(), "Recent")]'); + $author->click(); + + $this->spinAssert("Recent book title", $title_test, [ "RECENT ADDITIONS" ]); + + // Click on the cog to show tag filters + $cog = $this->byId("searchImage"); + $cog->click(); + sleep(1); + // Filter on War & Military + $filter = $this->byXPath('//li[contains(text(), "War")]'); + $filter->click(); + sleep(1); + // Only one book + $filtered = $this->elements($this->using('css selector')->value('*[class="books"]')); + $this->assertEquals(1, count($filtered)); + $filter->click(); + sleep(1); + // 13 book + $filtered = $this->elements($this->using('css selector')->value('*[class="books"]')); + $this->assertEquals(14, count($filtered)); + } + + public function normalSearch($src, $out) + { + $driver = $this; + $title_test = function ($value) use ($driver) { + $text = $driver->byXPath('//h1')->text(); + return $text == $value; + }; + + // Click on the cog to show the search + $cog = $this->byId("searchImage"); + $cog->click(); + //sleep (1); + + // Focus the input and type + $this->waitUntil(function () { + if ($this->byName("query")) { + return true; + } + return null; + }, 1000); + $queryInput = $this->byName("query"); + $queryInput->click(); + $queryInput->value($src); + $queryInput->submit(); + + $this->spinAssert("Home Title", $title_test, [ "SEARCH RESULT FOR *" . $out . "*" ]); + } + + public function testSearchWithoutAccentuatedCharacters() + { + $this->normalSearch("ali", "ALI"); + } + + public function testSearchWithAccentuatedCharacters() + { + if ($this->getBrowser() == "Android") { + $this->markTestIncomplete(); + return; + } + $this->normalSearch("é", "É"); + } +} diff --git a/test/baseTest.php b/test/baseTest.php new file mode 100644 index 000000000..78b35a1e1 --- /dev/null +++ b/test/baseTest.php @@ -0,0 +1,264 @@ + + */ + +require_once(dirname(__FILE__) . "/../base.php"); +require_once(dirname(__FILE__) . "/config_test.php"); +//require_once(dirname(__FILE__) . "/../base.php"); +use PHPUnit\Framework\TestCase; + +class BaseTest extends TestCase +{ + public static function setUpBeforeClass(): void + { + global $config; + $config['calibre_directory'] = dirname(__FILE__) . "/BaseWithSomeBooks/"; + Base::clearDb(); + } + + public function testAddURLParameter() + { + $this->assertEquals("?db=0", addURLParameter("?", "db", "0")); + $this->assertEquals("?key=value&db=0", addURLParameter("?key=value", "db", "0")); + $this->assertEquals("?key=value&otherKey=&db=0", addURLParameter("?key=value&otherKey", "db", "0")); + } + + /** + * FALSE is returned if the create_function failed (meaning there was a syntax error) + * @dataProvider providerTemplate + */ + public function testServerSideRender($template) + { + $_COOKIE["template"] = $template; + $this->assertNull(serverSideRender(null)); + + unset($_COOKIE['template']); + } + + /** + * The function for the head of the HTML catalog + * @dataProvider providerTemplate + */ + public function testGenerateHeader($templateName) + { + $_SERVER["HTTP_USER_AGENT"] = "Firefox"; + global $config; + $headcontent = file_get_contents(dirname(__FILE__) . '/../templates/' . $templateName . '/file.html'); + $template = new doT(); + $tpl = $template->template($headcontent, null); + $data = ["title" => $config['cops_title_default'], + "version" => VERSION, + "opds_url" => $config['cops_full_url'] . "feed.php", + "customHeader" => "", + "template" => $templateName, + "server_side_rendering" => useServerSideRendering(), + "current_css" => getCurrentCss(), + "favico" => $config['cops_icon'], + "getjson_url" => "getJSON.php?" . addURLParameter(getQueryString(), "complete", 1)]; + + $head = $tpl($data); + $this->assertStringContainsString("", $head); + $this->assertStringContainsString("", $head); + } + + public function providerTemplate() + { + return [ + ["bootstrap"], + ["default"], + ]; + } + + public function testLocalize() + { + $this->assertEquals("Authors", localize("authors.title")); + + $this->assertEquals("unknow.key", localize("unknow.key")); + } + + public function testLocalizeFr() + { + $_SERVER['HTTP_ACCEPT_LANGUAGE'] = "fr,fr-fr;q=0.8,en-us;q=0.5,en;q=0.3"; + $this->assertEquals("Auteurs", localize("authors.title", -1, true)); + + $_SERVER['HTTP_ACCEPT_LANGUAGE'] = "en"; + localize("authors.title", -1, true); + } + + public function testLocalizeUnknown() + { + $_SERVER['HTTP_ACCEPT_LANGUAGE'] = "aa"; + $this->assertEquals("Authors", localize("authors.title", -1, true)); + + $_SERVER['HTTP_ACCEPT_LANGUAGE'] = "en"; + localize("authors.title", -1, true); + } + + /** + * @dataProvider providerGetLangAndTranslationFile + */ + public function testGetLangAndTranslationFile($acceptLanguage, $result) + { + $_SERVER['HTTP_ACCEPT_LANGUAGE'] = $acceptLanguage; + [$lang, $lang_file] = GetLangAndTranslationFile(); + $this->assertEquals($result, $lang); + + $_SERVER['HTTP_ACCEPT_LANGUAGE'] = "en"; + localize("authors.title", -1, true); + } + + public function providerGetLangAndTranslationFile() + { + return [ + ["en", "en"], + ["fr,fr-fr;q=0.8,en-us;q=0.5,en;q=0.3", "fr"], + ["fr-FR", "fr"], + ["pt,en-us;q=0.7,en;q=0.3", "en"], + ["pt-br,pt;q=0.8,en-us;q=0.5,en;q=0.3", "pt_BR"], + ["pt-pt,pt;q=0.8,en;q=0.5,en-us;q=0.3", "pt_PT"], + ["zl", "en"], + ]; + } + + /** + * @dataProvider providerGetAcceptLanguages + */ + public function testGetAcceptLanguages($acceptLanguage, $result) + { + $_SERVER['HTTP_ACCEPT_LANGUAGE'] = $acceptLanguage; + $langs = array_keys(GetAcceptLanguages()); + $this->assertEquals($result, $langs[0]); + + $_SERVER['HTTP_ACCEPT_LANGUAGE'] = "en"; + localize("authors.title", -1, true); + } + + public function providerGetAcceptLanguages() + { + return [ + ["en", "en"], + ["en-US", "en_US"], + ["fr,fr-fr;q=0.8,en-us;q=0.5,en;q=0.3", "fr"], // French locale with Firefox + ["fr-FR,fr;q=0.8,en-US;q=0.6,en;q=0.4", "fr_FR"], // French locale with Chrome + ["fr-FR", "fr_FR"], // French locale with IE11 + ["pt-br,pt;q=0.8,en-us;q=0.5,en;q=0.3", "pt_BR"], + ["zl", "zl"], + ]; + } + + public function testBaseFunction() + { + global $config; + + $this->assertFalse(Base::isMultipleDatabaseEnabled()); + $this->assertEquals(["" => dirname(__FILE__) . "/BaseWithSomeBooks/"], Base::getDbList()); + + $config['calibre_directory'] = ["Some books" => dirname(__FILE__) . "/BaseWithSomeBooks/", + "One book" => dirname(__FILE__) . "/BaseWithOneBook/"]; + Base::clearDb(); + + $this->assertTrue(Base::isMultipleDatabaseEnabled()); + $this->assertEquals("Some books", Base::getDbName(0)); + $this->assertEquals("One book", Base::getDbName(1)); + $this->assertEquals($config['calibre_directory'], Base::getDbList()); + + $config['calibre_directory'] = dirname(__FILE__) . "/BaseWithSomeBooks/"; + Base::clearDb(); + } + + public function testCheckDatabaseAvailability_1() + { + $this->assertTrue(Base::checkDatabaseAvailability()); + } + + public function testCheckDatabaseAvailability_2() + { + global $config; + + $config['calibre_directory'] = ["Some books" => dirname(__FILE__) . "/BaseWithSomeBooks/", + "One book" => dirname(__FILE__) . "/BaseWithOneBook/"]; + Base::clearDb(); + + $this->assertTrue(Base::checkDatabaseAvailability()); + + $config['calibre_directory'] = dirname(__FILE__) . "/BaseWithSomeBooks/"; + Base::clearDb(); + } + + /** + * @expectedException Exception + * @expectedExceptionMessage Database <1> not found. + */ + public function testCheckDatabaseAvailability_Exception1() + { + global $config; + + $config['calibre_directory'] = ["Some books" => dirname(__FILE__) . "/BaseWithSomeBooks/", + "One book" => dirname(__FILE__) . "/OneBook/"]; + Base::clearDb(); + + $this->expectException(Exception::class); + $this->expectExceptionMessage('Database <1> not found.'); + + $this->assertTrue(Base::checkDatabaseAvailability()); + + $config['calibre_directory'] = dirname(__FILE__) . "/BaseWithSomeBooks/"; + Base::clearDb(); + } + + /** + * @expectedException Exception + * @expectedExceptionMessage Database <0> not found. + */ + public function testCheckDatabaseAvailability_Exception2() + { + global $config; + + $config['calibre_directory'] = ["Some books" => dirname(__FILE__) . "/SomeBooks/", + "One book" => dirname(__FILE__) . "/BaseWithOneBook/"]; + Base::clearDb(); + + $this->expectException(Exception::class); + $this->expectExceptionMessage('Database <0> not found.'); + + $this->assertTrue(Base::checkDatabaseAvailability()); + + $config['calibre_directory'] = dirname(__FILE__) . "/BaseWithSomeBooks/"; + Base::clearDb(); + } + + /* + Test normalized utf8 string according to unicode.org output + more here : + http://unicode.org/cldr/utility/transform.jsp?a=Latin-ASCII&b=%C3%80%C3%81%C3%82%C3%83%C3%84%C3%85%C3%87%C3%88%C3%89%C3%8A%C3%8B%C3%8C%C3%8D%C3%8E%C3%8F%C5%92%C3%92%C3%93%C3%94%C3%95%C3%96%C3%99%C3%9A%C3%9B%C3%9C%C3%9D%C3%A0%C3%A1%C3%A2%C3%A3%C3%A4%C3%A5%C3%A7%C3%A8%C3%A9%C3%AA%C3%AB%C3%AC%C3%AD%C3%AE%C3%AF%C5%93%C3%B0%C3%B2%C3%B3%C3%B4%C3%B5%C3%B6%C3%B9%C3%BA%C3%BB%C3%BC%C3%BD%C3%BF%C3%B1 + */ + public function testNormalizeUtf8String() + { + $this->assertEquals( + "AAAAAACEEEEIIIIOEOOOOOUUUUYaaaaaaceeeeiiiioedooooouuuuyyn", + normalizeUtf8String("ÀÁÂÃÄÅÇÈÉÊËÌÍÎÏŒÒÓÔÕÖÙÚÛÜÝàáâãäåçèéêëìíîïœðòóôõöùúûüýÿñ") + ); + } + + public function testLoginEnabledWithoutCreds() + { + global $config; + require_once __DIR__.'/../verifyLogin.php'; + $config['cops_basic_authentication'] = [ "username" => "xxx", "password" => "secret"]; + $this->assertFalse(verifyLogin()); + } + + public function testLoginEnabledAndLoggingIn() + { + global $config; + require_once __DIR__.'/../verifyLogin.php'; + $config['cops_basic_authentication'] = [ "username" => "xxx", "password" => "secret"]; + $_SERVER['PHP_AUTH_USER'] = 'xxx'; + $_SERVER['PHP_AUTH_PW'] = 'secret'; + $this->assertTrue(verifyLogin()); + } +} diff --git a/test/bookTest.php b/test/bookTest.php new file mode 100644 index 000000000..206183541 --- /dev/null +++ b/test/bookTest.php @@ -0,0 +1,640 @@ + + */ + +require_once(dirname(__FILE__) . "/config_test.php"); +use PHPUnit\Framework\TestCase; + +/* +Publishers: +id:2 (2 books) Macmillan and Co. London: Lewis Caroll +id:3 (2 books) D. Appleton and Company Alexander Dumas +id:4 (1 book) Macmillan Publishers USA: Jack London +id:5 (1 book) Pierson's Magazine: H. G. Wells +id:6 (8 books) Strand Magazine: Arthur Conan Doyle +*/ + +define("TEST_THUMBNAIL", dirname(__FILE__) . "/thumbnail.jpg"); +define("COVER_WIDTH", 400); +define("COVER_HEIGHT", 600); + +class BookTest extends TestCase +{ + public static function setUpBeforeClass(): void + { + global $config; + $config['calibre_directory'] = dirname(__FILE__) . "/BaseWithSomeBooks/"; + Base::clearDb(); + $book = Book::getBookById(2); + if (!is_dir($book->path)) { + mkdir($book->path, 0777, true); + } + $im = imagecreatetruecolor(COVER_WIDTH, COVER_HEIGHT); + $text_color = imagecolorallocate($im, 255, 0, 0); + imagestring($im, 1, 5, 5, 'Book cover', $text_color); + imagejpeg($im, $book->path . "/cover.jpg", 80); + } + + public static function tearDownAfterClass(): void + { + $book = Book::getBookById(2); + if (!file_exists($book->path . "/cover.jpg")) { + return; + } + unlink($book->path . "/cover.jpg"); + rmdir($book->path); + rmdir(dirname($book->path)); + } + + public function testGetBookCount() + { + $this->assertEquals(15, Book::getBookCount()); + } + + public function testGetCount() + { + $entryArray = Book::getCount(); + $this->assertEquals(2, count($entryArray)); + + $entryAllBooks = $entryArray [0]; + $this->assertEquals("Alphabetical index of the 15 books", $entryAllBooks->content); + + $entryRecentBooks = $entryArray [1]; + $this->assertEquals("50 most recent books", $entryRecentBooks->content); + } + + public function testGetCountRecent() + { + global $config; + $config['cops_recentbooks_limit'] = 0; + $entryArray = Book::getCount(); + + $this->assertEquals(1, count($entryArray)); + + $config['cops_recentbooks_limit'] = 2; + $entryArray = Book::getCount(); + + $entryRecentBooks = $entryArray [1]; + $this->assertEquals("2 most recent books", $entryRecentBooks->content); + + $config['cops_recentbooks_limit'] = 50; + } + + public function testGetBooksByAuthor() + { + // All book by Arthur Conan Doyle + global $config; + + $config['cops_max_item_per_page'] = 5; + [$entryArray, $totalNumber] = Book::getBooksByAuthor(1, 1); + $this->assertEquals(5, count($entryArray)); + $this->assertEquals(8, $totalNumber); + + [$entryArray, $totalNumber] = Book::getBooksByAuthor(1, 2); + $this->assertEquals(3, count($entryArray)); + $this->assertEquals(8, $totalNumber); + + $config['cops_max_item_per_page'] = -1; + [$entryArray, $totalNumber] = Book::getBooksByAuthor(1, -1); + $this->assertEquals(8, count($entryArray)); + $this->assertEquals(-1, $totalNumber); + } + + public function testGetBooksBySeries() + { + // All book from the Sherlock Holmes series + [$entryArray, $totalNumber] = Book::getBooksBySeries(1, -1); + $this->assertEquals(7, count($entryArray)); + $this->assertEquals(-1, $totalNumber); + } + + public function testGetBooksByPublisher() + { + // All books from Strand Magazine + [$entryArray, $totalNumber] = Book::getBooksByPublisher(6, -1); + $this->assertEquals(8, count($entryArray)); + $this->assertEquals(-1, $totalNumber); + } + + public function testGetBooksByTag() + { + // All book with the Fiction tag + [$entryArray, $totalNumber] = Book::getBooksByTag(1, -1); + $this->assertEquals(14, count($entryArray)); + $this->assertEquals(-1, $totalNumber); + } + + public function testGetBooksByLanguage() + { + // All english book (= all books) + [$entryArray, $totalNumber] = Book::getBooksByLanguage(1, -1); + $this->assertEquals(14, count($entryArray)); + $this->assertEquals(-1, $totalNumber); + } + + public function testGetAllBooks() + { + // All books by first letter + $entryArray = Book::getAllBooks(); + $this->assertCount(9, $entryArray); + } + + public function testGetBooksByStartingLetter() + { + // All books by first letter + [$entryArray, $totalNumber] = Book::getBooksByStartingLetter("T", -1); + $this->assertEquals(-1, $totalNumber); + $this->assertCount(3, $entryArray); + } + + public function testGetBookByDataId() + { + $book = Book::getBookByDataId(17); + + $this->assertEquals("Alice's Adventures in Wonderland", $book->getTitle()); + } + + public function testGetAllRecentBooks() + { + // All recent books + global $config; + + $config['cops_recentbooks_limit'] = 2; + + $entryArray = Book::getAllRecentBooks(); + $this->assertCount(2, $entryArray); + + $config['cops_recentbooks_limit'] = 50; + + $entryArray = Book::getAllRecentBooks(); + $this->assertCount(15, $entryArray); + } + + /** + * @dataProvider providerPublicationDate + */ + public function testGetPubDate($pubdate, $expectedYear) + { + $book = Book::getBookById(2); + $book->pubdate = $pubdate; + $this->assertEquals($expectedYear, $book->getPubDate()); + } + + public function providerPublicationDate() + { + return [ + ['2010-10-05 22:00:00+00:00', '2010'], + ['1982-11-15 13:05:29.908657+00:00', '1982'], + ['1562-10-05 00:00:00+00:00', '1562'], + ['0100-12-31 23:00:00+00:00', ''], + ['', ''], + [null, ''], + ]; + } + + public function testGetBookById() + { + // also check most of book's class methods + $book = Book::getBookById(2); + + $linkArray = $book->getLinkArray(); + $this->assertCount(5, $linkArray); + + $this->assertEquals("The Return of Sherlock Holmes", $book->getTitle()); + $this->assertEquals("urn:uuid:87ddbdeb-1e27-4d06-b79b-4b2a3bfc6a5f", $book->getEntryId()); + $this->assertEquals("index.php?page=13&id=2", $book->getDetailUrl()); + $this->assertEquals("Arthur Conan Doyle", $book->getAuthorsName()); + $this->assertEquals("Fiction, Mystery & Detective, Short Stories", $book->getTagsName()); + $this->assertEquals('

    The Return of Sherlock Holmes is a collection of 13 Sherlock Holmes stories, originally published in 1903-1904, by Arthur Conan Doyle.
    The book was first published on March 7, 1905 by Georges Newnes, Ltd and in a Colonial edition by Longmans. 30,000 copies were made of the initial print run. The US edition by McClure, Phillips & Co. added another 28,000 to the run.
    This was the first Holmes collection since 1893, when Holmes had "died" in "The Adventure of the Final Problem". Having published The Hound of the Baskervilles in 1901–1902 (although setting it before Holmes\' death) Doyle came under intense pressure to revive his famous character.

    ', $book->getComment(false)); + $this->assertEquals("English", $book->getLanguages()); + $this->assertEquals("Strand Magazine", $book->getPublisher()->name); + } + + public function testGetBookById_NotFound() + { + $book = Book::getBookById(666); + + $this->assertNull($book); + } + + public function testGetRating_FiveStars() + { + $book = Book::getBookById(2); + + $this->assertEquals("★★★★★", $book->getRating()); + } + + public function testGetRating_FourStars() + { + $book = Book::getBookById(2); + $book->rating = 8; + + // 4 filled stars and one empty + $this->assertEquals("★★★★☆", $book->getRating()); + } + + public function testGetRating_NoStars_Zero() + { + $book = Book::getBookById(2); + $book->rating = 0; + + $this->assertEquals("", $book->getRating()); + } + + public function testGetRating_NoStars_Null() + { + $book = Book::getBookById(2); + $book->rating = null; + + $this->assertEquals("", $book->getRating()); + } + + public function testBookGetLinkArrayWithUrlRewriting() + { + global $config; + + $book = Book::getBookById(2); + $config['cops_use_url_rewriting'] = "1"; + + $linkArray = $book->getLinkArray(); + foreach ($linkArray as $link) { + if ($link->rel == Link::OPDS_ACQUISITION_TYPE && $link->title == "EPUB") { + $this->assertEquals("download/1/The%20Return%20of%20Sherlock%20Holmes%20-%20Arthur%20Conan%20Doyle.epub", $link->href); + return; + } + } + $this->fail(); + } + + public function testBookGetLinkArrayWithoutUrlRewriting() + { + global $config; + + $book = Book::getBookById(2); + $config['cops_use_url_rewriting'] = "0"; + + $linkArray = $book->getLinkArray(); + foreach ($linkArray as $link) { + if ($link->rel == Link::OPDS_ACQUISITION_TYPE && $link->title == "EPUB") { + $this->assertEquals("fetch.php?data=1&type=epub&id=2", $link->href); + return; + } + } + $this->fail(); + } + + public function testGetThumbnailNotNeeded() + { + $book = Book::getBookById(2); + + $this->assertFalse($book->getThumbnail(null, null, null)); + + // Current cover is 400*600 + $this->assertFalse($book->getThumbnail(COVER_WIDTH, null, null)); + $this->assertFalse($book->getThumbnail(COVER_WIDTH + 1, null, null)); + $this->assertFalse($book->getThumbnail(null, COVER_HEIGHT, null)); + $this->assertFalse($book->getThumbnail(null, COVER_HEIGHT + 1, null)); + } + + /** + * @dataProvider providerThumbnail + */ + public function testGetThumbnailByWidth($width, $height, $expectedWidth, $expectedHeight) + { + $book = Book::getBookById(2); + + $this->assertTrue($book->getThumbnail($width, $height, TEST_THUMBNAIL)); + + $size = GetImageSize(TEST_THUMBNAIL); + $this->assertEquals($expectedWidth, $size [0]); + $this->assertEquals($expectedHeight, $size [1]); + + unlink(TEST_THUMBNAIL); + } + + public function providerThumbnail() + { + return [ + [164, null, 164, 246], + [null, 164, 109, 164], + ]; + } + + public function testGetMostInterestingDataToSendToKindle_WithMOBI() + { + // Get Alice (available as MOBI, PDF, EPUB in that order) + $book = Book::getBookById(17); + $data = $book->GetMostInterestingDataToSendToKindle(); + $this->assertEquals("MOBI", $data->format); + } + + public function testGetMostInterestingDataToSendToKindle_WithPdf() + { + // Get Alice (available as MOBI, PDF, EPUB in that order) + $book = Book::getBookById(17); + $book->GetMostInterestingDataToSendToKindle(); + array_shift($book->datas); + $data = $book->GetMostInterestingDataToSendToKindle(); + $this->assertEquals("PDF", $data->format); + } + + public function testGetMostInterestingDataToSendToKindle_WithEPUB() + { + // Get Alice (available as MOBI, PDF, EPUB in that order) + $book = Book::getBookById(17); + $book->GetMostInterestingDataToSendToKindle(); + array_shift($book->datas); + array_shift($book->datas); + $data = $book->GetMostInterestingDataToSendToKindle(); + $this->assertEquals("EPUB", $data->format); + } + + public function testGetDataById() + { + global $config; + + // Get Alice MOBI=>17, PDF=>19, EPUB=>20 + $book = Book::getBookById(17); + $mobi = $book->getDataById(17); + $this->assertEquals("MOBI", $mobi->format); + $epub = $book->getDataById(20); + $this->assertEquals("EPUB", $epub->format); + $this->assertEquals("Carroll, Lewis - Alice's Adventures in Wonderland.epub", $epub->getUpdatedFilenameEpub()); + $this->assertEquals("Carroll, Lewis - Alice's Adventures in Wonderland.kepub.epub", $epub->getUpdatedFilenameKepub()); + $this->assertEquals(dirname(__FILE__) . "/BaseWithSomeBooks/Lewis Carroll/Alice's Adventures in Wonderland (17)/Alice's Adventures in Wonderland - Lewis Carroll.epub", $epub->getLocalPath()); + + $config['cops_use_url_rewriting'] = "1"; + $config['cops_provide_kepub'] = "1"; + $_SERVER["HTTP_USER_AGENT"] = "Kobo"; + $this->assertEquals("download/20/Carroll%2C%20Lewis%20-%20Alice%27s%20Adventures%20in%20Wonderland.kepub.epub", $epub->getHtmlLink()); + $this->assertEquals("download/17/Alice%27s%20Adventures%20in%20Wonderland%20-%20Lewis%20Carroll.mobi", $mobi->getHtmlLink()); + $config['cops_provide_kepub'] = "0"; + $_SERVER["HTTP_USER_AGENT"] = "Firefox"; + $this->assertEquals("download/20/Alice%27s%20Adventures%20in%20Wonderland%20-%20Lewis%20Carroll.epub", $epub->getHtmlLink()); + $config['cops_use_url_rewriting'] = "0"; + $this->assertEquals("fetch.php?data=20&type=epub&id=17", $epub->getHtmlLink()); + } + + public function testGetFilePath_Cover() + { + $book = Book::getBookById(17); + + $this->assertEquals(Base::getDbDirectory() . "Lewis Carroll/Alice's Adventures in Wonderland (17)/cover.jpg", $book->getFilePath("jpg", null, false)); + } + + public function testGetFilePath_Epub() + { + $book = Book::getBookById(17); + + $this->assertEquals(Base::getDbDirectory() . "Lewis Carroll/Alice's Adventures in Wonderland (17)/Alice's Adventures in Wonderland - Lewis Carroll.epub", $book->getFilePath("epub", 20, false)); + } + + public function testGetFilePath_Mobi() + { + $book = Book::getBookById(17); + + $this->assertEquals(Base::getDbDirectory() . "Lewis Carroll/Alice's Adventures in Wonderland (17)/Alice's Adventures in Wonderland - Lewis Carroll.mobi", $book->getFilePath("mobi", 17, false)); + } + + public function testGetDataFormat_EPUB() + { + $book = Book::getBookById(17); + + // Get Alice MOBI=>17, PDF=>19, EPUB=>20 + $data = $book->getDataFormat("EPUB"); + $this->assertEquals(20, $data->id); + } + + public function testGetDataFormat_MOBI() + { + $book = Book::getBookById(17); + + // Get Alice MOBI=>17, PDF=>19, EPUB=>20 + $data = $book->getDataFormat("MOBI"); + $this->assertEquals(17, $data->id); + } + + public function testGetDataFormat_PDF() + { + $book = Book::getBookById(17); + + // Get Alice MOBI=>17, PDF=>19, EPUB=>20 + $data = $book->getDataFormat("PDF"); + $this->assertEquals(19, $data->id); + } + + public function testGetDataFormat_NonAvailable() + { + $book = Book::getBookById(17); + + // Get Alice MOBI=>17, PDF=>19, EPUB=>20 + $this->assertFalse($book->getDataFormat("FB2")); + } + + public function testGetMimeType_EPUB() + { + $book = Book::getBookById(17); + + // Get Alice MOBI=>17, PDF=>19, EPUB=>20 + $data = $book->getDataFormat("EPUB"); + $this->assertEquals("application/epub+zip", $data->getMimeType()); + } + + public function testGetMimeType_MOBI() + { + $book = Book::getBookById(17); + + // Get Alice MOBI=>17, PDF=>19, EPUB=>20 + $data = $book->getDataFormat("MOBI"); + $this->assertEquals("application/x-mobipocket-ebook", $data->getMimeType()); + } + + public function testGetMimeType_PDF() + { + $book = Book::getBookById(17); + + // Get Alice MOBI=>17, PDF=>19, EPUB=>20 + $data = $book->getDataFormat("PDF"); + $this->assertEquals("application/pdf", $data->getMimeType()); + } + + public function testGetMimeType_Finfo() + { + $book = Book::getBookById(17); + + // Get Alice MOBI=>17, PDF=>19, EPUB=>20 + $data = $book->getDataFormat("PDF"); + $this->assertEquals("application/pdf", $data->getMimeType()); + + // Alter a data to make a test for finfo_file if enabled + $data->extension = "ico"; + $data->format = "ICO"; + $data->name = "favicon"; + $data->book->path = realpath(dirname(__FILE__) . "/../"); + if (function_exists('finfo_open') === true) { + //$this->assertEquals("image/x-icon", $data->getMimeType()); + $this->assertEquals("image/vnd.microsoft.icon", $data->getMimeType()); + } else { + $this->assertEquals("application/octet-stream", $data->getMimeType()); + } + } + + public function testTypeaheadSearch_Tag() + { + $page = Base::PAGE_OPENSEARCH_QUERY; + $qid = getURLParam("id"); + $query = "fic"; + $n = getURLParam("n", "1"); + setURLParam('search', 1); + + $currentPage = Page::getPage($page, $qid, $query, $n); + $currentPage->InitializeContent(); + + $this->assertCount(3, $currentPage->entryArray); + $this->assertEquals("2 tags", $currentPage->entryArray[0]->content); + $this->assertEquals("Fiction", $currentPage->entryArray[1]->title); + $this->assertEquals("Science Fiction", $currentPage->entryArray[2]->title); + + setURLParam('search', null); + } + + public function testTypeaheadSearch_BookAndAuthor() + { + $page = Base::PAGE_OPENSEARCH_QUERY; + $qid = getURLParam("id"); + $query = "car"; + $n = getURLParam("n", "1"); + setURLParam('search', 1); + + $currentPage = Page::getPage($page, $qid, $query, $n); + $currentPage->InitializeContent(); + + $this->assertCount(4, $currentPage->entryArray); + $this->assertEquals("1 book", $currentPage->entryArray[0]->content); + $this->assertEquals("A Study in Scarlet", $currentPage->entryArray[1]->title); + + $this->assertEquals("1 author", $currentPage->entryArray[2]->content); + $this->assertEquals("Carroll, Lewis", $currentPage->entryArray[3]->title); + + setURLParam('search', null); + } + + public function testTypeaheadSearch_AuthorAndSeries() + { + $page = Base::PAGE_OPENSEARCH_QUERY; + $qid = getURLParam("id"); + $query = "art"; + $n = getURLParam("n", "1"); + setURLParam('search', 1); + + $currentPage = Page::getPage($page, $qid, $query, $n); + $currentPage->InitializeContent(); + + $this->assertCount(5, $currentPage->entryArray); + $this->assertEquals("1 author", $currentPage->entryArray[0]->content); + $this->assertEquals("Doyle, Arthur Conan", $currentPage->entryArray[1]->title); + + $this->assertEquals("2 series", $currentPage->entryArray[2]->content); + $this->assertEquals("D'Artagnan Romances", $currentPage->entryArray[3]->title); + + setURLParam('search', null); + } + + public function testTypeaheadSearch_Publisher() + { + $page = Base::PAGE_OPENSEARCH_QUERY; + $qid = getURLParam("id"); + $query = "Macmillan"; + $n = getURLParam("n", "1"); + setURLParam('search', 1); + + $currentPage = Page::getPage($page, $qid, $query, $n); + $currentPage->InitializeContent(); + + $this->assertCount(3, $currentPage->entryArray); + $this->assertEquals("2 publishers", $currentPage->entryArray[0]->content); + $this->assertEquals("Macmillan and Co. London", $currentPage->entryArray[1]->title); + $this->assertEquals("Macmillan Publishers USA", $currentPage->entryArray[2]->title); + + setURLParam('search', null); + } + + public function testTypeaheadSearchWithIgnored_SingleCategory() + { + global $config; + $page = Base::PAGE_OPENSEARCH_QUERY; + $qid = getURLParam("id"); + $query = "car"; + $n = getURLParam("n", "1"); + setURLParam('search', 1); + + $config ['cops_ignored_categories'] = ["author"]; + $currentPage = Page::getPage($page, $qid, $query, $n); + $currentPage->InitializeContent(); + + $this->assertCount(2, $currentPage->entryArray); + $this->assertEquals("1 book", $currentPage->entryArray[0]->content); + $this->assertEquals("A Study in Scarlet", $currentPage->entryArray[1]->title); + + setURLParam('search', null); + $config ['cops_ignored_categories'] = []; + } + + public function testTypeaheadSearchWithIgnored_MultipleCategory() + { + global $config; + $page = Base::PAGE_OPENSEARCH_QUERY; + $qid = getURLParam("id"); + $query = "art"; + $n = getURLParam("n", "1"); + setURLParam('search', 1); + + $config ['cops_ignored_categories'] = ["series"]; + $currentPage = Page::getPage($page, $qid, $query, $n); + $currentPage->InitializeContent(); + + $this->assertCount(2, $currentPage->entryArray); + $this->assertEquals("1 author", $currentPage->entryArray[0]->content); + $this->assertEquals("Doyle, Arthur Conan", $currentPage->entryArray[1]->title); + + setURLParam('search', null); + $config ['cops_ignored_categories'] = []; + } + + public function testTypeaheadSearchMultiDatabase() + { + global $config; + $page = Base::PAGE_OPENSEARCH_QUERY; + $qid = getURLParam("id"); + $query = "art"; + $n = getURLParam("n", "1"); + setURLParam('search', 1); + setURLParam('multi', 1); + + $config['calibre_directory'] = ["Some books" => dirname(__FILE__) . "/BaseWithSomeBooks/", + "One book" => dirname(__FILE__) . "/BaseWithOneBook/"]; + $currentPage = Page::getPage($page, $qid, $query, $n); + $currentPage->InitializeContent(); + + $this->assertCount(5, $currentPage->entryArray); + $this->assertEquals("Some books", $currentPage->entryArray[0]->title); + $this->assertEquals("1 author", $currentPage->entryArray[1]->content); + $this->assertEquals("2 series", $currentPage->entryArray[2]->content); + $this->assertEquals("One book", $currentPage->entryArray[3]->title); + $this->assertEquals("1 book", $currentPage->entryArray[4]->content); + + setURLParam('search', null); + setURLParam('multi', null); + $config['calibre_directory'] = dirname(__FILE__) . "/BaseWithSomeBooks/"; + Base::clearDb(); + } + + public function tearDown(): void + { + Base::clearDb(); + } +} diff --git a/test/configTest.php b/test/configTest.php new file mode 100644 index 000000000..c108f053a --- /dev/null +++ b/test/configTest.php @@ -0,0 +1,146 @@ + + */ +use PHPUnit\Framework\TestCase; + +class ConfigTest extends TestCase +{ + public function testCheckConfigurationCalibreDirectory() + { + global $config; + $this->assertTrue(is_string($config["calibre_directory"])); + } + + public function testCheckConfigurationOPDSTHumbnailHeight() + { + global $config; + $this->assertTrue(is_int((int)$config['cops_opds_thumbnail_height'])); + } + + public function testCheckConfigurationHTMLTHumbnailHeight() + { + global $config; + $this->assertTrue(is_int((int)$config['cops_html_thumbnail_height'])); + } + + public function testCheckConfigurationPreferedFormat() + { + global $config; + $this->assertTrue(is_array($config["cops_prefered_format"])); + } + + public function testCheckConfigurationUseUrlRewiting() + { + global $config; + $this->assertTrue(is_int((int)$config['cops_use_url_rewriting'])); + } + + public function testCheckConfigurationGenerateInvalidOPDSStream() + { + global $config; + $this->assertTrue(is_int((int)$config['cops_generate_invalid_opds_stream'])); + } + + public function testCheckConfigurationMaxItemPerPage() + { + global $config; + $this->assertTrue(is_int((int)$config['cops_max_item_per_page'])); + } + + public function testCheckConfigurationAuthorSplitFirstLetter() + { + global $config; + $this->assertTrue(is_int((int)$config['cops_author_split_first_letter'])); + } + + public function estCheckConfigurationTitlesSplitFirstLetter() + { + global $config; + $this->assertTrue(is_int((int)$config['cops_titles_split_first_letter'])); + } + + public function testCheckConfigurationCopsUseFancyapps() + { + global $config; + $this->assertTrue(is_int((int)$config['cops_use_fancyapps'])); + } + + public function testCheckConfigurationCopsBooksFilter() + { + global $config; + $this->assertTrue(is_array($config["cops_books_filter"])); + } + + public function testCheckConfigurationCalibreCustomColumn() + { + global $config; + $this->assertTrue(is_array($config["cops_calibre_custom_column"])); + } + + public function testCheckConfigurationCalibreCustomColumnList() + { + global $config; + $this->assertTrue(is_array($config["cops_calibre_custom_column_list"])); + } + + public function testCheckConfigurationCalibreCustomColumnPreview() + { + global $config; + $this->assertTrue(is_array($config["cops_calibre_custom_column_preview"])); + } + + public function testCheckConfigurationProvideKepub() + { + global $config; + $this->assertTrue(is_int((int)$config['cops_provide_kepub'])); + } + + public function testCheckConfigurationMailConfig() + { + global $config; + $this->assertTrue(is_array($config["cops_mail_configuration"])); + } + + public function testCheckConfiguratioHTMLTagFilter() + { + global $config; + $this->assertTrue(is_int((int)$config["cops_html_tag_filter"])); + } + + public function testCheckConfigurationIgnoredCategories() + { + global $config; + $this->assertTrue(is_array($config["cops_ignored_categories"])); + } + + public function testCheckConfigurationTemplate() + { + $_SERVER["HTTP_USER_AGENT"] = "Firefox"; + global $config; + $style = 'bootstrap'; + + $config["cops_template"] = $style; + + $headcontent = file_get_contents(dirname(__FILE__) . '/../templates/' . $config["cops_template"] . '/file.html'); + $template = new doT(); + $tpl = $template->template($headcontent, null); + $data = ["title" => $config['cops_title_default'], + "version" => VERSION, + "opds_url" => $config['cops_full_url'] . "feed.php", + "customHeader" => "", + "template" => $config["cops_template"], + "server_side_rendering" => useServerSideRendering(), + "current_css" => getCurrentCss(), + "favico" => $config['cops_icon'], + "getjson_url" => "getJSON.php?" . addURLParameter(getQueryString(), "complete", 1)]; + + $head = $tpl($data); + + $this->assertStringContainsString($style.".min.css", $head); + $this->assertStringContainsString($style.".min.js", $head); + } +} diff --git a/test/config_local.php.sauce b/test/config_local.php.sauce new file mode 100644 index 000000000..7e3c310db --- /dev/null +++ b/test/config_local.php.sauce @@ -0,0 +1,17 @@ + "smtp.free.fr", + "smtp.username" => "", + "smtp.password" => "", + "smtp.secure" => "", + "address.from" => "cops@slucas.fr", + ]; diff --git a/test/coverage-checker.php b/test/coverage-checker.php new file mode 100644 index 000000000..e67b9d58d --- /dev/null +++ b/test/coverage-checker.php @@ -0,0 +1,43 @@ + +* +* @author Marco Pivetta +* @see http://ocramius.github.io/blog/automated-code-coverage-check-for-github-pull-requests-with-travis/ +*/ + +$inputFile = $argv[1]; +$percentage = min(100, max(0, (int) $argv[2])); + +if (!file_exists($inputFile)) { + echo 'Invalid input file provided'; + exit(0); +} + +if (!$percentage) { + throw new InvalidArgumentException('An integer checked percentage must be given as second parameter'); +} + +$xml = new SimpleXMLElement(file_get_contents($inputFile)); +$metrics = $xml->xpath('//metrics'); +$totalElements = 0; +$checkedElements = 0; + +foreach ($metrics as $metric) { + $totalElements += (int) $metric['elements']; + $checkedElements += (int) $metric['coveredelements']; +} + +$coverage = ($checkedElements / $totalElements) * 100; + +if ($coverage < $percentage) { + echo 'Code coverage is ' . $coverage . '%, which is below the accepted ' . $percentage . '%' . PHP_EOL; + exit(1); +} + +echo 'Code coverage is ' . $coverage . '% - OK!' . PHP_EOL; diff --git a/test/customColumnsTest.php b/test/customColumnsTest.php new file mode 100644 index 000000000..f5498f7c5 --- /dev/null +++ b/test/customColumnsTest.php @@ -0,0 +1,938 @@ + + */ + +require_once(dirname(__FILE__) . "/config_test.php"); +use PHPUnit\Framework\TestCase; + +class CustomColumnTest extends TestCase +{ + public function testColumnType01() + { + global $config; + + $config['calibre_directory'] = dirname(__FILE__) . "/BaseWithCustomColumns/"; + $config['cops_calibre_custom_column'] = ["custom_01"]; + Base::clearDb(); + + $coltype = CustomColumnType::createByCustomID(8); + + $this->assertEquals($coltype, CustomColumnType::createByLookup("custom_01")); + + $this->assertEquals(8, $coltype->customId); + $this->assertEquals("custom_01", $coltype->columnTitle); + $this->assertEquals("text", $coltype->datatype); + $this->assertEquals("CustomColumnTypeText", get_class($coltype)); + + $this->assertCount(3, $coltype->getAllCustomValues()); + $this->assertEquals("?page=14&custom=8", $coltype->getUriAllCustoms()); + $this->assertEquals("cops:custom:8", $coltype->getAllCustomsId()); + $this->assertEquals("custom_01", $coltype->getTitle()); + $this->assertEquals("Custom column example 01 (text)", $coltype->getDatabaseDescription()); + $this->assertEquals("Custom column example 01 (text)", $coltype->getDescription()); + $this->assertEquals(true, $coltype->isSearchable()); + } + + public function testColumnType01b() + { + global $config; + + $config['calibre_directory'] = dirname(__FILE__) . "/BaseWithCustomColumns/"; + $config['cops_calibre_custom_column'] = ["custom_01b"]; + Base::clearDb(); + + $coltype = CustomColumnType::createByCustomID(16); + + $this->assertEquals($coltype, CustomColumnType::createByLookup("custom_01b")); + + $this->assertEquals(16, $coltype->customId); + $this->assertEquals("custom_01b", $coltype->columnTitle); + $this->assertEquals("text", $coltype->datatype); + $this->assertEquals("CustomColumnTypeText", get_class($coltype)); + + $this->assertCount(3, $coltype->getAllCustomValues()); + $this->assertEquals("?page=14&custom=16", $coltype->getUriAllCustoms()); + $this->assertEquals("cops:custom:16", $coltype->getAllCustomsId()); + $this->assertEquals("custom_01b", $coltype->getTitle()); + $this->assertEquals(null, $coltype->getDatabaseDescription()); + $this->assertEquals("Custom column 'custom_01b'", $coltype->getDescription()); + $this->assertEquals(true, $coltype->isSearchable()); + } + + public function testColumnType02() + { + global $config; + + $config['calibre_directory'] = dirname(__FILE__) . "/BaseWithCustomColumns/"; + $config['cops_calibre_custom_column'] = ["custom_02"]; + Base::clearDb(); + + $coltype = CustomColumnType::createByCustomID(6); + + $this->assertEquals($coltype, CustomColumnType::createByLookup("custom_02")); + + $this->assertEquals(6, $coltype->customId); + $this->assertEquals("custom_02", $coltype->columnTitle); + $this->assertEquals("text", $coltype->datatype); + $this->assertEquals("CustomColumnTypeText", get_class($coltype)); + + $this->assertCount(3, $coltype->getAllCustomValues()); + $this->assertEquals("?page=14&custom=6", $coltype->getUriAllCustoms()); + $this->assertEquals("cops:custom:6", $coltype->getAllCustomsId()); + $this->assertEquals("custom_02", $coltype->getTitle()); + $this->assertEquals("Custom column example 02 (csv)", $coltype->getDatabaseDescription()); + $this->assertEquals("Custom column example 02 (csv)", $coltype->getDescription()); + $this->assertEquals(true, $coltype->isSearchable()); + } + + public function testColumnType03() + { + global $config; + + $config['calibre_directory'] = dirname(__FILE__) . "/BaseWithCustomColumns/"; + $config['cops_calibre_custom_column'] = ["custom_03"]; + Base::clearDb(); + + $coltype = CustomColumnType::createByCustomID(7); + + $this->assertEquals($coltype, CustomColumnType::createByLookup("custom_03")); + + $this->assertEquals(7, $coltype->customId); + $this->assertEquals("custom_03", $coltype->columnTitle); + $this->assertEquals("comments", $coltype->datatype); + $this->assertEquals("CustomColumnTypeComment", get_class($coltype)); + + $this->assertEquals("?page=14&custom=7", $coltype->getUriAllCustoms()); + $this->assertEquals("cops:custom:7", $coltype->getAllCustomsId()); + $this->assertEquals("custom_03", $coltype->getTitle()); + $this->assertEquals("Custom column example 03 (long_text)", $coltype->getDatabaseDescription()); + $this->assertEquals("Custom column example 03 (long_text)", $coltype->getDescription()); + $this->assertEquals(false, $coltype->isSearchable()); + } + + public function testColumnType04() + { + global $config; + + $config['calibre_directory'] = dirname(__FILE__) . "/BaseWithCustomColumns/"; + $config['cops_calibre_custom_column'] = ["custom_04"]; + Base::clearDb(); + + $coltype = CustomColumnType::createByCustomID(4); + + $this->assertEquals($coltype, CustomColumnType::createByLookup("custom_04")); + + $this->assertEquals(4, $coltype->customId); + $this->assertEquals("custom_04", $coltype->columnTitle); + $this->assertEquals("series", $coltype->datatype); + $this->assertEquals("CustomColumnTypeSeries", get_class($coltype)); + + $this->assertCount(3, $coltype->getAllCustomValues()); + $this->assertEquals("?page=14&custom=4", $coltype->getUriAllCustoms()); + $this->assertEquals("cops:custom:4", $coltype->getAllCustomsId()); + $this->assertEquals("custom_04", $coltype->getTitle()); + $this->assertEquals("Custom column example 04 (series_text)", $coltype->getDatabaseDescription()); + $this->assertEquals("Alphabetical index of the 3 series", $coltype->getDescription()); + $this->assertEquals(true, $coltype->isSearchable()); + } + + public function testColumnType05() + { + global $config; + + $config['calibre_directory'] = dirname(__FILE__) . "/BaseWithCustomColumns/"; + $config['cops_calibre_custom_column'] = ["custom_05"]; + Base::clearDb(); + + $coltype = CustomColumnType::createByCustomID(5); + + $this->assertEquals($coltype, CustomColumnType::createByLookup("custom_05")); + + $this->assertEquals(5, $coltype->customId); + $this->assertEquals("custom_05", $coltype->columnTitle); + $this->assertEquals("enumeration", $coltype->datatype); + $this->assertEquals("CustomColumnTypeEnumeration", get_class($coltype)); + + $this->assertCount(4, $coltype->getAllCustomValues()); + $this->assertEquals("?page=14&custom=5", $coltype->getUriAllCustoms()); + $this->assertEquals("cops:custom:5", $coltype->getAllCustomsId()); + $this->assertEquals("custom_05", $coltype->getTitle()); + $this->assertEquals("Custom column example 05 (enum)", $coltype->getDatabaseDescription()); + $this->assertEquals("Alphabetical index of the 4 values", $coltype->getDescription()); + $this->assertEquals(true, $coltype->isSearchable()); + } + + public function testColumnType06() + { + global $config; + + $config['calibre_directory'] = dirname(__FILE__) . "/BaseWithCustomColumns/"; + $config['cops_calibre_custom_column'] = ["custom_06"]; + Base::clearDb(); + + $coltype = CustomColumnType::createByCustomID(12); + + $this->assertEquals($coltype, CustomColumnType::createByLookup("custom_06")); + + $this->assertEquals(12, $coltype->customId); + $this->assertEquals("custom_06", $coltype->columnTitle); + $this->assertEquals("datetime", $coltype->datatype); + $this->assertEquals("CustomColumnTypeDate", get_class($coltype)); + + $this->assertCount(5, $coltype->getAllCustomValues()); + $this->assertEquals("?page=14&custom=12", $coltype->getUriAllCustoms()); + $this->assertEquals("cops:custom:12", $coltype->getAllCustomsId()); + $this->assertEquals("custom_06", $coltype->getTitle()); + $this->assertEquals("Custom column example 06 (date)", $coltype->getDatabaseDescription()); + $this->assertEquals("Custom column example 06 (date)", $coltype->getDescription()); + $this->assertEquals(true, $coltype->isSearchable()); + } + + public function testColumnType07() + { + global $config; + + $config['calibre_directory'] = dirname(__FILE__) . "/BaseWithCustomColumns/"; + $config['cops_calibre_custom_column'] = ["custom_07"]; + Base::clearDb(); + + $coltype = CustomColumnType::createByCustomID(14); + + $this->assertEquals($coltype, CustomColumnType::createByLookup("custom_07")); + + $this->assertEquals(14, $coltype->customId); + $this->assertEquals("custom_07", $coltype->columnTitle); + $this->assertEquals("float", $coltype->datatype); + $this->assertEquals("CustomColumnTypeFloat", get_class($coltype)); + + $this->assertCount(6, $coltype->getAllCustomValues()); + $this->assertEquals("?page=14&custom=14", $coltype->getUriAllCustoms()); + $this->assertEquals("cops:custom:14", $coltype->getAllCustomsId()); + $this->assertEquals("custom_07", $coltype->getTitle()); + $this->assertEquals("Custom column example 07 (float)", $coltype->getDatabaseDescription()); + $this->assertEquals("Custom column example 07 (float)", $coltype->getDescription()); + $this->assertEquals(true, $coltype->isSearchable()); + } + + public function testColumnType08() + { + global $config; + + $config['calibre_directory'] = dirname(__FILE__) . "/BaseWithCustomColumns/"; + $config['cops_calibre_custom_column'] = ["custom_08"]; + Base::clearDb(); + + $coltype = CustomColumnType::createByCustomID(10); + + $this->assertEquals($coltype, CustomColumnType::createByLookup("custom_08")); + + $this->assertEquals(10, $coltype->customId); + $this->assertEquals("custom_08", $coltype->columnTitle); + $this->assertEquals("int", $coltype->datatype); + $this->assertEquals("CustomColumnTypeInteger", get_class($coltype)); + + $this->assertCount(4, $coltype->getAllCustomValues()); + $this->assertEquals("?page=14&custom=10", $coltype->getUriAllCustoms()); + $this->assertEquals("cops:custom:10", $coltype->getAllCustomsId()); + $this->assertEquals("custom_08", $coltype->getTitle()); + $this->assertEquals("Custom column example 08 (int)", $coltype->getDatabaseDescription()); + $this->assertEquals("Custom column example 08 (int)", $coltype->getDescription()); + $this->assertEquals(true, $coltype->isSearchable()); + } + + public function testColumnType09() + { + global $config; + + $config['calibre_directory'] = dirname(__FILE__) . "/BaseWithCustomColumns/"; + $config['cops_calibre_custom_column'] = ["custom_09"]; + Base::clearDb(); + + $coltype = CustomColumnType::createByCustomID(9); + + $this->assertEquals($coltype, CustomColumnType::createByLookup("custom_09")); + + $this->assertEquals(9, $coltype->customId); + $this->assertEquals("custom_09", $coltype->columnTitle); + $this->assertEquals("rating", $coltype->datatype); + $this->assertEquals("CustomColumnTypeRating", get_class($coltype)); + + $this->assertCount(6, $coltype->getAllCustomValues()); + $this->assertEquals("?page=14&custom=9", $coltype->getUriAllCustoms()); + $this->assertEquals("cops:custom:9", $coltype->getAllCustomsId()); + $this->assertEquals("custom_09", $coltype->getTitle()); + $this->assertEquals("Custom column example 09 (rating)", $coltype->getDatabaseDescription()); + $this->assertEquals("Index of ratings", $coltype->getDescription()); + $this->assertEquals(true, $coltype->isSearchable()); + } + + public function testColumnType10() + { + global $config; + + $config['calibre_directory'] = dirname(__FILE__) . "/BaseWithCustomColumns/"; + $config['cops_calibre_custom_column'] = ["custom_10"]; + Base::clearDb(); + + $coltype = CustomColumnType::createByCustomID(11); + + $this->assertEquals($coltype, CustomColumnType::createByLookup("custom_10")); + + $this->assertEquals(11, $coltype->customId); + $this->assertEquals("custom_10", $coltype->columnTitle); + $this->assertEquals("bool", $coltype->datatype); + $this->assertEquals("CustomColumnTypeBool", get_class($coltype)); + + $this->assertCount(3, $coltype->getAllCustomValues()); + $this->assertEquals("?page=14&custom=11", $coltype->getUriAllCustoms()); + $this->assertEquals("cops:custom:11", $coltype->getAllCustomsId()); + $this->assertEquals("custom_10", $coltype->getTitle()); + $this->assertEquals("Custom column example 10 (bool)", $coltype->getDatabaseDescription()); + $this->assertEquals("Index of a boolean value", $coltype->getDescription()); + $this->assertEquals(true, $coltype->isSearchable()); + } + + public function testColumnType11() + { + global $config; + + $config['calibre_directory'] = dirname(__FILE__) . "/BaseWithCustomColumns/"; + $config['cops_calibre_custom_column'] = ["custom_11"]; + Base::clearDb(); + + $coltype = CustomColumnType::createByCustomID(15); + + $this->assertEquals($coltype, CustomColumnType::createByLookup("custom_11")); + + $this->assertEquals(null, $coltype); + } + + public function testColumnType12() + { + global $config; + + $config['calibre_directory'] = dirname(__FILE__) . "/BaseWithCustomColumns/"; + $config['cops_calibre_custom_column'] = ["custom_12"]; + Base::clearDb(); + + $coltype = CustomColumnType::createByCustomID(13); + + $this->assertEquals($coltype, CustomColumnType::createByLookup("custom_12")); + + $this->assertEquals(null, $coltype); + } + + public function testInvalidColumn1() + { + global $config; + + $config['calibre_directory'] = dirname(__FILE__) . "/BaseWithCustomColumns/"; + $config['cops_calibre_custom_column'] = ["custom_12"]; + Base::clearDb(); + + $catch = false; + try { + CustomColumnType::createByCustomID(999); + } catch (Exception $e) { + $catch = true; + } + + $this->assertTrue($catch); + } + + public function testInvalidColumn2() + { + global $config; + + $config['calibre_directory'] = dirname(__FILE__) . "/BaseWithCustomColumns/"; + $config['cops_calibre_custom_column'] = ["custom_12"]; + Base::clearDb(); + + $coltype = CustomColumnType::createByLookup("__ERR__"); + + $this->assertEquals(null, $coltype); + } + + public function testIndexTypeAll() + { + global $config; + + $config['calibre_directory'] = dirname(__FILE__) . "/BaseWithCustomColumns/"; + $config['cops_calibre_custom_column'] = ["custom_01", "custom_02", "custom_03", "custom_04", "custom_05", "custom_06", "custom_07", "custom_08", "custom_09", "custom_10"]; + Base::clearDb(); + + $currentPage = Page::getPage(Base::PAGE_INDEX, null, null, "1"); + $currentPage->InitializeContent(); + + $this->assertCount(15, $currentPage->entryArray); // Authors, Series, Publishers, Languages, custom, All, Recent + $this->assertEquals("custom_01", $currentPage->entryArray[ 4]->title); + $this->assertEquals("custom_02", $currentPage->entryArray[ 5]->title); + $this->assertEquals("custom_04", $currentPage->entryArray[ 6]->title); + $this->assertEquals("custom_05", $currentPage->entryArray[ 7]->title); + $this->assertEquals("custom_06", $currentPage->entryArray[ 8]->title); + $this->assertEquals("custom_07", $currentPage->entryArray[ 9]->title); + $this->assertEquals("custom_08", $currentPage->entryArray[10]->title); + $this->assertEquals("custom_09", $currentPage->entryArray[11]->title); + $this->assertEquals("custom_10", $currentPage->entryArray[12]->title); + } + + public function testIndexType01() + { + global $config; + + $config['calibre_directory'] = dirname(__FILE__) . "/BaseWithCustomColumns/"; + $config['cops_calibre_custom_column'] = ["custom_01"]; + Base::clearDb(); + + $currentPage = Page::getPage(Base::PAGE_INDEX, null, null, "1"); + $currentPage->InitializeContent(); + + $this->assertCount(7, $currentPage->entryArray); // Authors, Series, Publishers, Languages, custom, All, Recent + $this->assertEquals("custom_01", $currentPage->entryArray[4]->title); + $this->assertEquals("cops:custom:8", $currentPage->entryArray[4]->id); + $this->assertEquals("Custom column example 01 (text)", $currentPage->entryArray[4]->content); + $this->assertEquals(3, $currentPage->entryArray[4]->numberOfElement); + $this->assertEquals("text", $currentPage->entryArray[4]->contentType); + $this->assertEquals($currentPage->entryArray[4], CustomColumnType::createByCustomID(8)->getCount()); + } + + public function testIndexType02() + { + global $config; + + $config['calibre_directory'] = dirname(__FILE__) . "/BaseWithCustomColumns/"; + $config['cops_calibre_custom_column'] = ["custom_02"]; + Base::clearDb(); + + $currentPage = Page::getPage(Base::PAGE_INDEX, null, null, "1"); + $currentPage->InitializeContent(); + + $this->assertCount(7, $currentPage->entryArray); // Authors, Series, Publishers, Languages, custom, All, Recent + $this->assertEquals("custom_02", $currentPage->entryArray[4]->title); + $this->assertEquals("cops:custom:6", $currentPage->entryArray[4]->id); + $this->assertEquals("Custom column example 02 (csv)", $currentPage->entryArray[4]->content); + $this->assertEquals(3, $currentPage->entryArray[4]->numberOfElement); + $this->assertEquals("text", $currentPage->entryArray[4]->contentType); + $this->assertEquals($currentPage->entryArray[4], CustomColumnType::createByCustomID(6)->getCount()); + } + + public function testIndexType03() + { + global $config; + + $config['calibre_directory'] = dirname(__FILE__) . "/BaseWithCustomColumns/"; + $config['cops_calibre_custom_column'] = ["custom_03"]; + Base::clearDb(); + + $currentPage = Page::getPage(Base::PAGE_INDEX, null, null, "1"); + $currentPage->InitializeContent(); + + $this->assertCount(6, $currentPage->entryArray); // Authors, Series, Publishers, Languages, All, Recent + } + + public function testIndexType04() + { + global $config; + + $config['calibre_directory'] = dirname(__FILE__) . "/BaseWithCustomColumns/"; + $config['cops_calibre_custom_column'] = ["custom_04"]; + Base::clearDb(); + + $currentPage = Page::getPage(Base::PAGE_INDEX, null, null, "1"); + $currentPage->InitializeContent(); + + $this->assertCount(7, $currentPage->entryArray); // Authors, Series, Publishers, Languages, custom, All, Recent + $this->assertEquals("custom_04", $currentPage->entryArray[4]->title); + $this->assertEquals("cops:custom:4", $currentPage->entryArray[4]->id); + $this->assertEquals("Alphabetical index of the 3 series", $currentPage->entryArray[4]->content); + $this->assertEquals(3, $currentPage->entryArray[4]->numberOfElement); + $this->assertEquals("series", $currentPage->entryArray[4]->contentType); + $this->assertEquals($currentPage->entryArray[4], CustomColumnType::createByCustomID(4)->getCount()); + } + + public function testIndexType05() + { + global $config; + + $config['calibre_directory'] = dirname(__FILE__) . "/BaseWithCustomColumns/"; + $config['cops_calibre_custom_column'] = ["custom_05"]; + Base::clearDb(); + + $currentPage = Page::getPage(Base::PAGE_INDEX, null, null, "1"); + $currentPage->InitializeContent(); + + $this->assertCount(7, $currentPage->entryArray); // Authors, Series, Publishers, Languages, custom, All, Recent + $this->assertEquals("custom_05", $currentPage->entryArray[4]->title); + $this->assertEquals("cops:custom:5", $currentPage->entryArray[4]->id); + $this->assertEquals("Alphabetical index of the 4 values", $currentPage->entryArray[4]->content); + $this->assertEquals(4, $currentPage->entryArray[4]->numberOfElement); + $this->assertEquals("enumeration", $currentPage->entryArray[4]->contentType); + $this->assertEquals($currentPage->entryArray[4], CustomColumnType::createByCustomID(5)->getCount()); + } + + public function testIndexType06() + { + global $config; + + $config['calibre_directory'] = dirname(__FILE__) . "/BaseWithCustomColumns/"; + $config['cops_calibre_custom_column'] = ["custom_06"]; + Base::clearDb(); + + $currentPage = Page::getPage(Base::PAGE_INDEX, null, null, "1"); + $currentPage->InitializeContent(); + + $this->assertCount(7, $currentPage->entryArray); // Authors, Series, Publishers, Languages, custom, All, Recent + $this->assertEquals("custom_06", $currentPage->entryArray[4]->title); + $this->assertEquals("cops:custom:12", $currentPage->entryArray[4]->id); + $this->assertEquals("Custom column example 06 (date)", $currentPage->entryArray[4]->content); + $this->assertEquals(5, $currentPage->entryArray[4]->numberOfElement); + $this->assertEquals("datetime", $currentPage->entryArray[4]->contentType); + $this->assertEquals($currentPage->entryArray[4], CustomColumnType::createByCustomID(12)->getCount()); + } + + public function testIndexType07() + { + global $config; + + $config['calibre_directory'] = dirname(__FILE__) . "/BaseWithCustomColumns/"; + $config['cops_calibre_custom_column'] = ["custom_07"]; + Base::clearDb(); + + $currentPage = Page::getPage(Base::PAGE_INDEX, null, null, "1"); + $currentPage->InitializeContent(); + + $this->assertCount(7, $currentPage->entryArray); // Authors, Series, Publishers, Languages, custom, All, Recent + $this->assertEquals("custom_07", $currentPage->entryArray[4]->title); + $this->assertEquals("cops:custom:14", $currentPage->entryArray[4]->id); + $this->assertEquals("Custom column example 07 (float)", $currentPage->entryArray[4]->content); + $this->assertEquals(6, $currentPage->entryArray[4]->numberOfElement); + $this->assertEquals("float", $currentPage->entryArray[4]->contentType); + $this->assertEquals($currentPage->entryArray[4], CustomColumnType::createByCustomID(14)->getCount()); + } + + public function testIndexType08() + { + global $config; + + $config['calibre_directory'] = dirname(__FILE__) . "/BaseWithCustomColumns/"; + $config['cops_calibre_custom_column'] = ["custom_08"]; + Base::clearDb(); + + $currentPage = Page::getPage(Base::PAGE_INDEX, null, null, "1"); + $currentPage->InitializeContent(); + + $this->assertCount(7, $currentPage->entryArray); // Authors, Series, Publishers, Languages, custom, All, Recent + $this->assertEquals("custom_08", $currentPage->entryArray[4]->title); + $this->assertEquals("cops:custom:10", $currentPage->entryArray[4]->id); + $this->assertEquals("Custom column example 08 (int)", $currentPage->entryArray[4]->content); + $this->assertEquals(4, $currentPage->entryArray[4]->numberOfElement); + $this->assertEquals("int", $currentPage->entryArray[4]->contentType); + $this->assertEquals($currentPage->entryArray[4], CustomColumnType::createByCustomID(10)->getCount()); + } + + public function testIndexType09() + { + global $config; + + $config['calibre_directory'] = dirname(__FILE__) . "/BaseWithCustomColumns/"; + $config['cops_calibre_custom_column'] = ["custom_09"]; + Base::clearDb(); + + $currentPage = Page::getPage(Base::PAGE_INDEX, null, null, "1"); + $currentPage->InitializeContent(); + + $this->assertCount(7, $currentPage->entryArray); // Authors, Series, Publishers, Languages, custom, All, Recent + $this->assertEquals("custom_09", $currentPage->entryArray[4]->title); + $this->assertEquals("cops:custom:9", $currentPage->entryArray[4]->id); + $this->assertEquals("Index of ratings", $currentPage->entryArray[4]->content); + $this->assertEquals(6, $currentPage->entryArray[4]->numberOfElement); + $this->assertEquals("rating", $currentPage->entryArray[4]->contentType); + $this->assertEquals($currentPage->entryArray[4], CustomColumnType::createByCustomID(9)->getCount()); + } + + public function testIndexType10() + { + global $config; + + $config['calibre_directory'] = dirname(__FILE__) . "/BaseWithCustomColumns/"; + $config['cops_calibre_custom_column'] = ["custom_10"]; + Base::clearDb(); + + $currentPage = Page::getPage(Base::PAGE_INDEX, null, null, "1"); + $currentPage->InitializeContent(); + + $this->assertCount(7, $currentPage->entryArray); // Authors, Series, Publishers, Languages, custom, All, Recent + $this->assertEquals("custom_10", $currentPage->entryArray[4]->title); + $this->assertEquals("cops:custom:11", $currentPage->entryArray[4]->id); + $this->assertEquals("Index of a boolean value", $currentPage->entryArray[4]->content); + $this->assertEquals(3, $currentPage->entryArray[4]->numberOfElement); + $this->assertEquals("bool", $currentPage->entryArray[4]->contentType); + $this->assertEquals($currentPage->entryArray[4], CustomColumnType::createByCustomID(11)->getCount()); + } + + public function testAllCustomsType01() + { + global $config; + + $config['calibre_directory'] = dirname(__FILE__) . "/BaseWithCustomColumns/"; + setURLParam('custom', 8); + Base::clearDb(); + $currentPage = Page::getPage(Base::PAGE_ALL_CUSTOMS, null, null, "1"); + $currentPage->InitializeContent(); + + $this->assertEquals("custom_01", $currentPage->title); + $this->assertCount(3, $currentPage->entryArray); + $this->assertEquals("cops:custom:8:3", $currentPage->entryArray[0]->id); + $this->assertEquals("cops:custom:8:1", $currentPage->entryArray[1]->id); + $this->assertEquals("cops:custom:8:2", $currentPage->entryArray[2]->id); + } + + public function testAllCustomsType02() + { + global $config; + + $config['calibre_directory'] = dirname(__FILE__) . "/BaseWithCustomColumns/"; + setURLParam('custom', 6); + Base::clearDb(); + $currentPage = Page::getPage(Base::PAGE_ALL_CUSTOMS, null, null, "1"); + $currentPage->InitializeContent(); + + $this->assertEquals("custom_02", $currentPage->title); + $this->assertCount(3, $currentPage->entryArray); + $this->assertEquals("cops:custom:6:1", $currentPage->entryArray[0]->id); + $this->assertEquals("cops:custom:6:2", $currentPage->entryArray[1]->id); + $this->assertEquals("cops:custom:6:3", $currentPage->entryArray[2]->id); + } + + public function testAllCustomsType04() + { + global $config; + + $config['calibre_directory'] = dirname(__FILE__) . "/BaseWithCustomColumns/"; + setURLParam('custom', 4); + Base::clearDb(); + $currentPage = Page::getPage(Base::PAGE_ALL_CUSTOMS, null, null, "1"); + $currentPage->InitializeContent(); + + $this->assertEquals("custom_04", $currentPage->title); + $this->assertCount(3, $currentPage->entryArray); + $this->assertEquals("cops:custom:4:4", $currentPage->entryArray[0]->id); + $this->assertEquals("cops:custom:4:5", $currentPage->entryArray[1]->id); + $this->assertEquals("cops:custom:4:6", $currentPage->entryArray[2]->id); + } + + public function testAllCustomsType05() + { + global $config; + + $config['calibre_directory'] = dirname(__FILE__) . "/BaseWithCustomColumns/"; + setURLParam('custom', 5); + Base::clearDb(); + $currentPage = Page::getPage(Base::PAGE_ALL_CUSTOMS, null, null, "1"); + $currentPage->InitializeContent(); + + $this->assertEquals("custom_05", $currentPage->title); + $this->assertCount(4, $currentPage->entryArray); + $this->assertEquals("cops:custom:5:3", $currentPage->entryArray[0]->id); + $this->assertEquals("cops:custom:5:4", $currentPage->entryArray[1]->id); + $this->assertEquals("cops:custom:5:5", $currentPage->entryArray[2]->id); + $this->assertEquals("cops:custom:5:6", $currentPage->entryArray[3]->id); + } + + public function testAllCustomsType06() + { + global $config; + + $config['calibre_directory'] = dirname(__FILE__) . "/BaseWithCustomColumns/"; + setURLParam('custom', 12); + Base::clearDb(); + $currentPage = Page::getPage(Base::PAGE_ALL_CUSTOMS, null, null, "1"); + $currentPage->InitializeContent(); + + $this->assertEquals("custom_06", $currentPage->title); + $this->assertCount(5, $currentPage->entryArray); + $this->assertEquals("cops:custom:12:2000-01-01", $currentPage->entryArray[0]->id); + $this->assertEquals("cops:custom:12:2000-01-02", $currentPage->entryArray[1]->id); + $this->assertEquals("cops:custom:12:2000-01-03", $currentPage->entryArray[2]->id); + $this->assertEquals("cops:custom:12:2016-04-20", $currentPage->entryArray[3]->id); + $this->assertEquals("cops:custom:12:2016-04-24", $currentPage->entryArray[4]->id); + } + + public function testAllCustomsType07() + { + global $config; + + $config['calibre_directory'] = dirname(__FILE__) . "/BaseWithCustomColumns/"; + setURLParam('custom', 14); + Base::clearDb(); + $currentPage = Page::getPage(Base::PAGE_ALL_CUSTOMS, null, null, "1"); + $currentPage->InitializeContent(); + + $this->assertEquals("custom_07", $currentPage->title); + $this->assertCount(6, $currentPage->entryArray); + $this->assertEquals("cops:custom:14:-99", $currentPage->entryArray[0]->id); + $this->assertEquals("cops:custom:14:0", $currentPage->entryArray[1]->id); + $this->assertEquals("cops:custom:14:0.1", $currentPage->entryArray[2]->id); + $this->assertEquals("cops:custom:14:0.2", $currentPage->entryArray[3]->id); + $this->assertEquals("cops:custom:14:11", $currentPage->entryArray[4]->id); + $this->assertEquals("cops:custom:14:100000", $currentPage->entryArray[5]->id); + } + + public function testAllCustomsType08() + { + global $config; + + $config['calibre_directory'] = dirname(__FILE__) . "/BaseWithCustomColumns/"; + setURLParam('custom', 10); + Base::clearDb(); + $currentPage = Page::getPage(Base::PAGE_ALL_CUSTOMS, null, null, "1"); + $currentPage->InitializeContent(); + + $this->assertEquals("custom_08", $currentPage->title); + $this->assertCount(4, $currentPage->entryArray); + $this->assertEquals("cops:custom:10:-2", $currentPage->entryArray[0]->id); + $this->assertEquals("cops:custom:10:-1", $currentPage->entryArray[1]->id); + $this->assertEquals("cops:custom:10:1", $currentPage->entryArray[2]->id); + $this->assertEquals("cops:custom:10:2", $currentPage->entryArray[3]->id); + } + + public function testAllCustomsType09() + { + global $config; + + $config['calibre_directory'] = dirname(__FILE__) . "/BaseWithCustomColumns/"; + setURLParam('custom', 9); + Base::clearDb(); + $currentPage = Page::getPage(Base::PAGE_ALL_CUSTOMS, null, null, "1"); + $currentPage->InitializeContent(); + + $this->assertEquals("custom_09", $currentPage->title); + $this->assertCount(6, $currentPage->entryArray); + $this->assertEquals("cops:custom:9:0", $currentPage->entryArray[0]->id); + $this->assertEquals("cops:custom:9:2", $currentPage->entryArray[1]->id); + $this->assertEquals("cops:custom:9:4", $currentPage->entryArray[2]->id); + $this->assertEquals("cops:custom:9:6", $currentPage->entryArray[3]->id); + $this->assertEquals("cops:custom:9:8", $currentPage->entryArray[4]->id); + $this->assertEquals("cops:custom:9:10", $currentPage->entryArray[5]->id); + } + + public function testAllCustomsType10() + { + global $config; + + $config['calibre_directory'] = dirname(__FILE__) . "/BaseWithCustomColumns/"; + setURLParam('custom', 11); + Base::clearDb(); + $currentPage = Page::getPage(Base::PAGE_ALL_CUSTOMS, null, null, "1"); + $currentPage->InitializeContent(); + + $this->assertEquals("custom_10", $currentPage->title); + $this->assertCount(3, $currentPage->entryArray); + $this->assertEquals("cops:custom:11:-1", $currentPage->entryArray[0]->id); + $this->assertEquals("cops:custom:11:0", $currentPage->entryArray[1]->id); + $this->assertEquals("cops:custom:11:1", $currentPage->entryArray[2]->id); + } + + public function testDetailTypeAllEntryIDs() + { + global $config; + + $config['calibre_directory'] = dirname(__FILE__) . "/BaseWithCustomColumns/"; + setURLParam('custom', 11); + $config['cops_calibre_custom_column'] = ["custom_01", "custom_02", "custom_03", "custom_04", "custom_05", "custom_06", "custom_07", "custom_08", "custom_09", "custom_10", "custom_11"]; + Base::clearDb(); + + $currentPage = Page::getPage(Base::PAGE_CUSTOM_DETAIL, "0", null, "1"); + $currentPage->InitializeContent(); + + /* @var EntryBook[] $entries */ + $entries = $currentPage->entryArray; + + $this->assertCount(6, $entries); + + $customcolumnValues = $entries[0]->book->getCustomColumnValues($config['cops_calibre_custom_column']); + + $this->assertCount(10, $customcolumnValues); + + $this->assertEquals("cops:custom:8:1", $customcolumnValues[0]->getEntryId()); + $this->assertEquals("cops:custom:6:3", $customcolumnValues[1]->getEntryId()); + $this->assertEquals("cops:custom:7:3", $customcolumnValues[2]->getEntryId()); + $this->assertEquals("cops:custom:4:4", $customcolumnValues[3]->getEntryId()); + $this->assertEquals("cops:custom:5:6", $customcolumnValues[4]->getEntryId()); + $this->assertEquals("cops:custom:12:2016-04-24", $customcolumnValues[5]->getEntryId()); + $this->assertEquals("cops:custom:14:11", $customcolumnValues[6]->getEntryId()); + $this->assertEquals("cops:custom:10:-2", $customcolumnValues[7]->getEntryId()); + $this->assertEquals("cops:custom:9:2", $customcolumnValues[8]->getEntryId()); + $this->assertEquals("cops:custom:11:0", $customcolumnValues[9]->getEntryId()); + + setURLParam('custom', null); + $config['cops_calibre_custom_column'] = []; + $config['calibre_directory'] = dirname(__FILE__) . "/BaseWithSomeBooks/"; + Base::clearDb(); + } + + public function testRenderCustomColumns() + { + global $config; + + $_SERVER["HTTP_USER_AGENT"] = "Firefox"; + $config['calibre_directory'] = dirname(__FILE__) . "/BaseWithCustomColumns/"; + setURLParam('custom', 11); + $config['cops_calibre_custom_column'] = ["custom_01", "custom_02", "custom_03", "custom_04", "custom_05", "custom_06", "custom_07", "custom_08", "custom_09", "custom_10", "custom_11"]; + $config['cops_calibre_custom_column_list'] = ["custom_01", "custom_02", "custom_03", "custom_04", "custom_05", "custom_06", "custom_07", "custom_08", "custom_09", "custom_10", "custom_11"]; + $config['cops_calibre_custom_column_preview'] = ["custom_01", "custom_02", "custom_03", "custom_04", "custom_05", "custom_06", "custom_07", "custom_08", "custom_09", "custom_10", "custom_11"]; + Base::clearDb(); + + $book = Book::getBookById(223); + $json = JSONRenderer::getBookContentArray($book); + + /* @var CustomColumn[] $custom */ + $custom = $json["customcolumns_list"]; + + $this->assertEquals("custom_01", $custom[0]['customColumnType']['columnTitle']); + $this->assertEquals("text_2", $custom[0]['htmlvalue']); + + $this->assertEquals("custom_02", $custom[1]['customColumnType']['columnTitle']); + $this->assertEquals("a", $custom[1]['htmlvalue']); + + $this->assertEquals("custom_03", $custom[2]['customColumnType']['columnTitle']); + $this->assertEquals("
    Not Set
    ", $custom[2]['htmlvalue']); + + $this->assertEquals("custom_04", $custom[3]['customColumnType']['columnTitle']); + $this->assertEquals("", $custom[3]['htmlvalue']); + + $this->assertEquals("custom_05", $custom[4]['customColumnType']['columnTitle']); + $this->assertEquals("val05", $custom[4]['htmlvalue']); + + $this->assertEquals("custom_06", $custom[5]['customColumnType']['columnTitle']); + $this->assertEquals("Not Set", $custom[5]['htmlvalue']); + + $this->assertEquals("custom_07", $custom[6]['customColumnType']['columnTitle']); + $this->assertEquals("100000", $custom[6]['htmlvalue']); + + $this->assertEquals("custom_08", $custom[7]['customColumnType']['columnTitle']); + $this->assertEquals("Not Set", $custom[7]['htmlvalue']); + + $this->assertEquals("custom_09", $custom[8]['customColumnType']['columnTitle']); + $this->assertEquals("Not Set", $custom[8]['htmlvalue']); + + $this->assertEquals("custom_10", $custom[9]['customColumnType']['columnTitle']); + $this->assertEquals("No", $custom[9]['htmlvalue']); + + $_SERVER["HTTP_USER_AGENT"] = ""; + $config['cops_calibre_custom_column_list'] = []; + $config['cops_calibre_custom_column_preview'] = []; + } + + public function testQueries() + { + global $config; + + $config['calibre_directory'] = dirname(__FILE__) . "/BaseWithCustomColumns/"; + setURLParam('custom', 11); + $config['cops_calibre_custom_column'] = ["custom_01", "custom_02", "custom_03", "custom_04", "custom_05", "custom_06", "custom_07", "custom_08", "custom_09", "custom_10", "custom_11"]; + Base::clearDb(); + + [$query, $params] = CustomColumnType::createByLookup("custom_01")->getCustom("1")->getQuery(); + Book::getEntryArray($query, $params, 1); + + [$query, $params] = CustomColumnType::createByLookup("custom_02")->getCustom("3")->getQuery(); + Book::getEntryArray($query, $params, 1); + + [$query, $params] = CustomColumnType::createByLookup("custom_03")->getCustom("3")->getQuery(); + Book::getEntryArray($query, $params, 1); + + [$query, $params] = CustomColumnType::createByLookup("custom_04")->getCustom("4")->getQuery(); + Book::getEntryArray($query, $params, 1); + + [$query, $params] = CustomColumnType::createByLookup("custom_05")->getCustom("6")->getQuery(); + Book::getEntryArray($query, $params, 1); + + [$query, $params] = CustomColumnType::createByLookup("custom_06")->getCustom("2016-04-24")->getQuery(); + Book::getEntryArray($query, $params, 1); + + [$query, $params] = CustomColumnType::createByLookup("custom_07")->getCustom("11.0")->getQuery(); + Book::getEntryArray($query, $params, 1); + + [$query, $params] = CustomColumnType::createByLookup("custom_08")->getCustom("-2")->getQuery(); + Book::getEntryArray($query, $params, 1); + + [$query, $params] = CustomColumnType::createByLookup("custom_09")->getCustom("0")->getQuery(); + Book::getEntryArray($query, $params, 1); + + [$query, $params] = CustomColumnType::createByLookup("custom_09")->getCustom("1")->getQuery(); + Book::getEntryArray($query, $params, 1); + + [$query, $params] = CustomColumnType::createByLookup("custom_10")->getCustom("-1")->getQuery(); + Book::getEntryArray($query, $params, 1); + + [$query, $params] = CustomColumnType::createByLookup("custom_10")->getCustom("0")->getQuery(); + Book::getEntryArray($query, $params, 1); + + [$query, $params] = CustomColumnType::createByLookup("custom_10")->getCustom("1")->getQuery(); + Book::getEntryArray($query, $params, 1); + } + + public function testGetURI() + { + global $config; + + $config['calibre_directory'] = dirname(__FILE__) . "/BaseWithCustomColumns/"; + setURLParam('custom', 11); + $config['cops_calibre_custom_column'] = ["custom_01", "custom_02", "custom_03", "custom_04", "custom_05", "custom_06", "custom_07", "custom_08", "custom_09", "custom_10", "custom_11"]; + Base::clearDb(); + + $custom = CustomColumnType::createByLookup("custom_01")->getCustom("1"); + $this->assertEquals($custom->customColumnType->getQuery("1"), $custom->getQuery()); + + $custom = CustomColumnType::createByLookup("custom_02")->getCustom("3"); + $this->assertEquals($custom->customColumnType->getQuery("3"), $custom->getQuery()); + + $custom = CustomColumnType::createByLookup("custom_03")->getCustom("3"); + $this->assertEquals($custom->customColumnType->getQuery("3"), $custom->getQuery()); + + $custom = CustomColumnType::createByLookup("custom_04")->getCustom("4"); + $this->assertEquals($custom->customColumnType->getQuery("4"), $custom->getQuery()); + + $custom = CustomColumnType::createByLookup("custom_05")->getCustom("6"); + $this->assertEquals($custom->customColumnType->getQuery("6"), $custom->getQuery()); + + $custom = CustomColumnType::createByLookup("custom_06")->getCustom("2016-04-24"); + $this->assertEquals($custom->customColumnType->getQuery("2016-04-24"), $custom->getQuery()); + + $custom = CustomColumnType::createByLookup("custom_07")->getCustom("11.0"); + $this->assertEquals($custom->customColumnType->getQuery("11.0"), $custom->getQuery()); + + $custom = CustomColumnType::createByLookup("custom_08")->getCustom("-2"); + $this->assertEquals($custom->customColumnType->getQuery("-2"), $custom->getQuery()); + + $custom = CustomColumnType::createByLookup("custom_09")->getCustom("0"); + $this->assertEquals($custom->customColumnType->getQuery("0"), $custom->getQuery()); + + $custom = CustomColumnType::createByLookup("custom_09")->getCustom("1"); + $this->assertEquals($custom->customColumnType->getQuery("1"), $custom->getQuery()); + + $custom = CustomColumnType::createByLookup("custom_10")->getCustom("-1"); + $this->assertEquals($custom->customColumnType->getQuery("-1"), $custom->getQuery()); + + $custom = CustomColumnType::createByLookup("custom_10")->getCustom("0"); + $this->assertEquals($custom->customColumnType->getQuery("0"), $custom->getQuery()); + + $custom = CustomColumnType::createByLookup("custom_10")->getCustom("1"); + $this->assertEquals($custom->customColumnType->getQuery("1"), $custom->getQuery()); + } + + public function tearDown(): void + { + global $config; + + setURLParam('custom', null); + $config['cops_calibre_custom_column'] = []; + $config['calibre_directory'] = dirname(__FILE__) . "/BaseWithSomeBooks/"; + Base::clearDb(); + } +} diff --git a/test/jing.jar b/test/jing.jar new file mode 100644 index 000000000..fe01514e8 Binary files /dev/null and b/test/jing.jar differ diff --git a/test/jsonTest.php b/test/jsonTest.php new file mode 100644 index 000000000..024f1684a --- /dev/null +++ b/test/jsonTest.php @@ -0,0 +1,87 @@ + + */ + +require_once(dirname(__FILE__) . "/config_test.php"); +use PHPUnit\Framework\TestCase; + +class JsonTest extends TestCase +{ + public static function setUpBeforeClass(): void + { + global $config; + $config['calibre_directory'] = dirname(__FILE__) . "/BaseWithSomeBooks/"; + $config['cops_calibre_custom_column'] = []; + $config['cops_calibre_custom_column_list'] = []; + $config['cops_calibre_custom_column_preview'] = []; + Base::clearDb(); + } + + public function testCompleteArray() + { + global $config; + + $_SERVER["HTTP_USER_AGENT"] = "Firefox"; + $test = []; + $test = JSONRenderer::addCompleteArray($test); + $this->assertArrayHasKey("c", $test); + $this->assertArrayHasKey("version", $test ["c"]); + $this->assertArrayHasKey("i18n", $test ["c"]); + $this->assertArrayHasKey("url", $test ["c"]); + $this->assertArrayHasKey("config", $test ["c"]); + + $this->assertFalse($test ["c"]["url"]["thumbnailUrl"] == $test ["c"]["url"]["coverUrl"]); + + // The thumbnails should be the same as the covers + $config['cops_thumbnail_handling'] = "1"; + $test = []; + $test = JSONRenderer::addCompleteArray($test); + + $this->assertTrue($test ["c"]["url"]["thumbnailUrl"] == $test ["c"]["url"]["coverUrl"]); + + // The thumbnails should be the same as the covers + $config['cops_thumbnail_handling'] = "/images.png"; + $test = []; + $test = JSONRenderer::addCompleteArray($test); + + $this->assertEquals("/images.png", $test ["c"]["url"]["thumbnailUrl"]); + } + + public function testGetBookContentArrayWithoutSeries() + { + $book = Book::getBookById(17); + $test = JSONRenderer::getBookContentArray($book); + + $this->assertEquals("", $test ["seriesName"]); + $this->assertEquals("1.0", $test ["seriesIndex"]); + $this->assertEquals("", $test ["seriesCompleteName"]); + $this->assertEquals("", $test ["seriesurl"]); + } + + public function testGetBookContentArrayWithSeries() + { + $book = Book::getBookById(2); + + $test = JSONRenderer::getBookContentArray($book); + + $this->assertEquals("Sherlock Holmes", $test ["seriesName"]); + $this->assertEquals("6.0", $test ["seriesIndex"]); + $this->assertEquals("Book 6 in the Sherlock Holmes series", $test ["seriesCompleteName"]); + $this->assertStringEndsWith("?page=7&id=1", $test ["seriesurl"]); + } + + public function testGetFullBookContentArray() + { + $book = Book::getBookById(17); + + $test = JSONRenderer::getFullBookContentArray($book); + + $this->assertCount(1, $test ["authors"]); + $this->assertCount(3, $test ["tags"]); + $this->assertCount(3, $test ["datas"]); + } +} diff --git a/test/mailTest.php b/test/mailTest.php new file mode 100644 index 000000000..bede12215 --- /dev/null +++ b/test/mailTest.php @@ -0,0 +1,91 @@ + + */ + +require_once(dirname(__FILE__) . "/config_test.php"); +require_once(dirname(__FILE__) . "/../sendtomail.php"); +use PHPUnit\Framework\TestCase; + +class MailTest extends TestCase +{ + public function testCheckConfigurationOk() + { + $this->assertFalse(checkConfiguration()); + } + + public function testCheckConfigurationNull() + { + global $config; + $config['cops_mail_configuration'] = null; + + $this->assertStringStartsWith("NOK", checkConfiguration()); + } + + public function testCheckConfigurationNotArray() + { + global $config; + $config['cops_mail_configuration'] = "Test"; + + $this->assertStringStartsWith("NOK", checkConfiguration()); + } + + public function testCheckConfigurationSmtpEmpty() + { + global $config; + require(dirname(__FILE__) . "/config_test.php"); + $config['cops_mail_configuration']["smtp.host"] = ""; + + $this->assertStringStartsWith("NOK", checkConfiguration()); + } + + public function testCheckConfigurationEmailEmpty() + { + global $config; + require(dirname(__FILE__) . "/config_test.php"); + $config['cops_mail_configuration']["address.from"] = ""; + + $this->assertStringStartsWith("NOK", checkConfiguration()); + } + + public function testCheckConfigurationEmailNotEmpty() + { + global $config; + $email = "a"; + $config['cops_mail_configuration']["address.from"] = $email; + + $this->assertStringContainsString($email, $config['cops_mail_configuration']["address.from"]); + } + + public function testCheckConfigurationEmailNotValid() + { + global $config; + $email = "a"; + $this->assertDoesNotMatchRegularExpression('/^.+\@\S+\.\S+$/', $email); + } + + public function testCheckConfigurationEmailValid() + { + global $config; + $email = "a@a.com"; + $this->assertMatchesRegularExpression('/^.+\@\S+\.\S+$/', $email); + } + + public function testCheckRequest() + { + $this->assertFalse(checkRequest(12, "a@a.com")); + } + + public function testCheckRequestNoData() + { + $this->assertStringStartsWith("No", checkRequest(null, "a@a.com")); + } + + public function testCheckRequestNoEmail() + { + $this->assertStringStartsWith("No", checkRequest(12, null)); + } +} diff --git a/test/opds-relax-ng/atom.rng b/test/opds-relax-ng/atom.rng new file mode 100644 index 000000000..f1407fc4d --- /dev/null +++ b/test/opds-relax-ng/atom.rng @@ -0,0 +1,598 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text + html + + + + + + + + + xhtml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + An atom:feed must have an atom:author unless all of its atom:entry children have an atom:author. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + An atom:entry must have at least one atom:link element with a rel attribute of 'alternate' or an atom:content. + + + An atom:entry must have an atom:author if its feed does not. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text + html + + + + + + + + + + + + + xhtml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + [^:]* + + + + + + .+/.+ + + + + + + [A-Za-z]{1,8}(-[A-Za-z0-9]{1,8})* + + + + + + + + + + .+@.+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + xml:base + xml:lang + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/opds-relax-ng/opds_catalog_1_1.rng b/test/opds-relax-ng/opds_catalog_1_1.rng new file mode 100644 index 000000000..e4ed2fb2e --- /dev/null +++ b/test/opds-relax-ng/opds_catalog_1_1.rng @@ -0,0 +1,599 @@ + + + + + + + + http://opds-spec.org/acquisition/buy + http://opds-spec.org/acquisition/borrow + http://opds-spec.org/acquisition/subscribe + http://opds-spec.org/acquisition/sample + + + + + + + http://opds-spec.org/acquisition/borrow + http://opds-spec.org/acquisition/subscribe + http://opds-spec.org/acquisition/sample + + + + + + + + + + xml:base + xml:lang + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + http://opds-spec.org/facet + + + + + + + + true + + + + + + + http://opds-spec.org/acquisition/buy + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + .*[ <>{}|^`"\\\n\r\t].* + + + + + + + + + + + text + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0.0 + + + + + + + AED + AFN + ALL + AMD + ANG + AOA + ARS + AUD + AWG + AZN + BAM + BBD + BDT + BGN + BHD + BIF + BMD + BND + BOB + BOV + BRL + BSD + BTN + BWP + BYR + BZD + CAD + CDF + CHE + CHF + CHW + CLF + CLP + CNY + COP + COU + CRC + CUC + CUP + CVE + CZK + DJF + DKK + DOP + DZD + EEK + EGP + ERN + ETB + EUR + FJD + FKP + GBP + GEL + GHS + GIP + GMD + GNF + GTQ + GYD + HKD + HNL + HRK + HTG + HUF + IDR + ILS + INR + IQD + IRR + ISK + JMD + JOD + JPY + KES + KGS + KHR + KMF + KPW + KRW + KWD + KYD + KZT + LAK + LBP + LKR + LRD + LSL + LTL + LVL + LYD + MAD + MDL + MGA + MKD + MMK + MNT + MOP + MRO + MUR + MVR + MWK + MXN + MXV + MYR + MZN + NAD + NGN + NIO + NOK + NPR + NZD + OMR + PAB + PEN + PGK + PHP + PKR + PLN + PYG + QAR + RON + RSD + RUB + RWF + SAR + SBD + SCR + SDG + SEK + SGD + SHP + SLL + SOS + SRD + STD + SVC + SYP + SZL + THB + TJS + TMT + TND + TOP + TRY + TTD + TWD + TZS + UAH + UGX + USD + USN + USS + UYI + UYU + UZS + VEF + VND + VUV + WST + XAF + XAG + XAU + XBA + XBB + XBC + XBD + XCD + XDR + XFU + XOF + XPD + XPF + XPT + XTS + XXX + YER + ZAR + ZMK + ZWL + 008 + 012 + 032 + 036 + 044 + 048 + 050 + 051 + 052 + 060 + 064 + 068 + 072 + 084 + 090 + 096 + 104 + 108 + 116 + 124 + 132 + 136 + 144 + 152 + 156 + 170 + 174 + 188 + 191 + 192 + 203 + 208 + 214 + 222 + 230 + 232 + 233 + 238 + 242 + 262 + 270 + 292 + 320 + 324 + 328 + 332 + 340 + 344 + 348 + 352 + 356 + 360 + 364 + 368 + 376 + 388 + 392 + 398 + 400 + 404 + 408 + 410 + 414 + 417 + 418 + 422 + 426 + 428 + 430 + 434 + 440 + 446 + 454 + 458 + 462 + 478 + 480 + 484 + 496 + 498 + 504 + 512 + 516 + 524 + 532 + 533 + 548 + 554 + 558 + 566 + 578 + 586 + 590 + 598 + 600 + 604 + 608 + 634 + 643 + 646 + 654 + 678 + 682 + 690 + 694 + 702 + 704 + 706 + 710 + 748 + 752 + 756 + 760 + 764 + 776 + 780 + 784 + 788 + 800 + 807 + 818 + 826 + 834 + 840 + 858 + 860 + 882 + 886 + 894 + 901 + 931 + 932 + 934 + 936 + 937 + 938 + 940 + 941 + 943 + 944 + 946 + 947 + 948 + 949 + 950 + 951 + 952 + 953 + 955 + 956 + 957 + 958 + 959 + 960 + 961 + 962 + 963 + 964 + 968 + 969 + 970 + 971 + 972 + 973 + 974 + 975 + 976 + 977 + 978 + 979 + 980 + 981 + 984 + 985 + 986 + 990 + 997 + 998 + 999 + + + diff --git a/test/opds-relax-ng/opensearchdescription.rng b/test/opds-relax-ng/opensearchdescription.rng new file mode 100644 index 000000000..7b71ada4e --- /dev/null +++ b/test/opds-relax-ng/opensearchdescription.rng @@ -0,0 +1,416 @@ + + + + + + + + + + + + + + + + 1024 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + get + post + GET + POST + + + + + + + + get + post + GET + POST + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 256 + + + + + + + + 48 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 256 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 64 + + + + + + + + 256 + + + + + + + + open + limited + private + closed + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/pageMultidatabaseTest.php b/test/pageMultidatabaseTest.php new file mode 100644 index 000000000..83bb2b071 --- /dev/null +++ b/test/pageMultidatabaseTest.php @@ -0,0 +1,81 @@ + + */ + +require_once(dirname(__FILE__) . "/config_test.php"); +use PHPUnit\Framework\TestCase; + +class PageMultiDatabaseTest extends TestCase +{ + public function testPageIndex() + { + global $config; + $config['calibre_directory'] = ["Some books" => dirname(__FILE__) . "/BaseWithSomeBooks/", + "One book" => dirname(__FILE__) . "/BaseWithOneBook/"]; + Base::clearDb(); + $page = Base::PAGE_INDEX; + $query = null; + $qid = null; + $n = "1"; + + $currentPage = Page::getPage($page, $qid, $query, $n); + $currentPage->InitializeContent(); + + $this->assertEquals($config['cops_title_default'], $currentPage->title); + $this->assertCount(2, $currentPage->entryArray); + $this->assertEquals("Some books", $currentPage->entryArray [0]->title); + $this->assertEquals("15 books", $currentPage->entryArray [0]->content); + $this->assertEquals(15, $currentPage->entryArray [0]->numberOfElement); + $this->assertEquals("One book", $currentPage->entryArray [1]->title); + $this->assertEquals("1 book", $currentPage->entryArray [1]->content); + $this->assertEquals(1, $currentPage->entryArray [1]->numberOfElement); + $this->assertFalse($currentPage->ContainsBook()); + } + + /** + * @dataProvider providerSearch + */ + public function testPageSearchXXX($maxItem) + { + global $config; + $config['calibre_directory'] = ["Some books" => dirname(__FILE__) . "/BaseWithSomeBooks/", + "One book" => dirname(__FILE__) . "/BaseWithOneBook/"]; + Base::clearDb(); + $page = Base::PAGE_OPENSEARCH_QUERY; + $query = "art"; + $qid = null; + $n = "1"; + + // Issue 124 + $config['cops_max_item_per_page'] = $maxItem; + $currentPage = Page::getPage($page, $qid, $query, $n); + $currentPage->InitializeContent(); + + $this->assertEquals("Search result for *art*", $currentPage->title); + $this->assertCount(2, $currentPage->entryArray); + $this->assertEquals("Some books", $currentPage->entryArray [0]->title); + $this->assertEquals("11 books", $currentPage->entryArray [0]->content); + $this->assertEquals("One book", $currentPage->entryArray [1]->title); + $this->assertEquals("1 book", $currentPage->entryArray [1]->content); + $this->assertFalse($currentPage->ContainsBook()); + + $config['cops_max_item_per_page'] = -1; + } + + public function providerSearch() + { + return [ + [2], + [-1], + ]; + } + + public static function tearDownAfterClass(): void + { + Base::clearDb(); + } +} diff --git a/test/pageTest.php b/test/pageTest.php new file mode 100644 index 000000000..105b279c4 --- /dev/null +++ b/test/pageTest.php @@ -0,0 +1,982 @@ + + */ + +require_once(dirname(__FILE__) . "/config_test.php"); +use PHPUnit\Framework\TestCase; + +class PageTest extends TestCase +{ + public static function setUpBeforeClass(): void + { + global $config; + $config['calibre_directory'] = dirname(__FILE__) . "/BaseWithSomeBooks/"; + Base::clearDb(); + } + + public function testPageIndex() + { + global $config; + $page = Base::PAGE_INDEX; + $query = null; + $qid = null; + $n = "1"; + + $currentPage = Page::getPage($page, $qid, $query, $n); + $currentPage->InitializeContent(); + + $this->assertEquals($config['cops_title_default'], $currentPage->title); + $this->assertCount(8, $currentPage->entryArray); + $this->assertEquals("Authors", $currentPage->entryArray [0]->title); + $this->assertEquals("Alphabetical index of the 6 authors", $currentPage->entryArray [0]->content); + $this->assertEquals(6, $currentPage->entryArray [0]->numberOfElement); + $this->assertEquals("Series", $currentPage->entryArray [1]->title); + $this->assertEquals("Alphabetical index of the 4 series", $currentPage->entryArray [1]->content); + $this->assertEquals(4, $currentPage->entryArray [1]->numberOfElement); + $this->assertEquals("Publishers", $currentPage->entryArray [2]->title); + $this->assertEquals("Alphabetical index of the 6 publishers", $currentPage->entryArray [2]->content); + $this->assertEquals(6, $currentPage->entryArray [2]->numberOfElement); + $this->assertEquals("Tags", $currentPage->entryArray [3]->title); + $this->assertEquals("Alphabetical index of the 11 tags", $currentPage->entryArray [3]->content); + $this->assertEquals(11, $currentPage->entryArray [3]->numberOfElement); + $this->assertEquals("Ratings", $currentPage->entryArray [4]->title); + $this->assertEquals("3 ratings", $currentPage->entryArray [4]->content); + $this->assertEquals(3, $currentPage->entryArray [4]->numberOfElement); + $this->assertEquals("Languages", $currentPage->entryArray [5]->title); + $this->assertEquals("Alphabetical index of the 2 languages", $currentPage->entryArray [5]->content); + $this->assertEquals(2, $currentPage->entryArray [5]->numberOfElement); + $this->assertEquals("All books", $currentPage->entryArray [6]->title); + $this->assertEquals("Alphabetical index of the 15 books", $currentPage->entryArray [6]->content); + $this->assertEquals(15, $currentPage->entryArray [6]->numberOfElement); + $this->assertEquals("Recent additions", $currentPage->entryArray [7]->title); + $this->assertEquals("50 most recent books", $currentPage->entryArray [7]->content); + $this->assertEquals(50, $currentPage->entryArray [7]->numberOfElement); + $this->assertFalse($currentPage->ContainsBook()); + } + + public function testPageIndexWithIgnored() + { + global $config; + $page = Base::PAGE_INDEX; + $query = null; + $qid = null; + $n = "1"; + + $config ['cops_ignored_categories'] = ["author", "series", "tag", "publisher", "language"]; + + $currentPage = Page::getPage($page, $qid, $query, $n); + $currentPage->InitializeContent(); + + $this->assertEquals($config['cops_title_default'], $currentPage->title); + $this->assertCount(3, $currentPage->entryArray); + $this->assertEquals("Ratings", $currentPage->entryArray [0]->title); + $this->assertEquals("All books", $currentPage->entryArray [1]->title); + $this->assertEquals("Alphabetical index of the 15 books", $currentPage->entryArray [1]->content); + $this->assertEquals("Recent additions", $currentPage->entryArray [2]->title); + $this->assertEquals("50 most recent books", $currentPage->entryArray [2]->content); + $this->assertFalse($currentPage->ContainsBook()); + + $config ['cops_ignored_categories'] = []; + } + + public function testPageIndexWithCustomColumn_Type1() + { + global $config; + $page = Base::PAGE_INDEX; + $query = null; + $qid = null; + $n = "1"; + + $config['cops_calibre_custom_column'] = ["type1"]; + + $currentPage = Page::getPage($page, $qid, $query, $n); + $currentPage->InitializeContent(); + + $this->assertCount(9, $currentPage->entryArray); + $this->assertEquals("Type1", $currentPage->entryArray [6]->title); + $this->assertEquals("Custom column 'Type1'", $currentPage->entryArray [6]->content); + $this->assertEquals(2, $currentPage->entryArray [6]->numberOfElement); + + $config['cops_calibre_custom_column'] = []; + } + + public function testPageIndexWithCustomColumn_Type2() + { + global $config; + $page = Base::PAGE_INDEX; + $query = null; + $qid = null; + $n = "1"; + + $config['cops_calibre_custom_column'] = ["type2"]; + + $currentPage = Page::getPage($page, $qid, $query, $n); + $currentPage->InitializeContent(); + + $this->assertCount(9, $currentPage->entryArray); + $this->assertEquals("Type2", $currentPage->entryArray [6]->title); + $this->assertEquals("Custom column 'Type2'", $currentPage->entryArray [6]->content); + $this->assertEquals(3, $currentPage->entryArray [6]->numberOfElement); + + $config['cops_calibre_custom_column'] = []; + } + + public function testPageIndexWithCustomColumn_Type4() + { + global $config; + $page = Base::PAGE_INDEX; + $query = null; + $qid = null; + $n = "1"; + + $config['cops_calibre_custom_column'] = ["type4"]; + + $currentPage = Page::getPage($page, $qid, $query, $n); + $currentPage->InitializeContent(); + + $this->assertCount(9, $currentPage->entryArray); + $this->assertEquals("Type4", $currentPage->entryArray [6]->title); + $this->assertEquals("Alphabetical index of the 2 series", $currentPage->entryArray [6]->content); + $this->assertEquals(2, $currentPage->entryArray [6]->numberOfElement); + + $config['cops_calibre_custom_column'] = []; + } + + public function testPageIndexWithCustomColumn_ManyTypes() + { + global $config; + $page = Base::PAGE_INDEX; + $query = null; + $qid = null; + $n = "1"; + + $config['cops_calibre_custom_column'] = ["type1", "type2", "type4"]; + + $currentPage = Page::getPage($page, $qid, $query, $n); + $currentPage->InitializeContent(); + + $this->assertCount(11, $currentPage->entryArray); + + $config['cops_calibre_custom_column'] = []; + } + + public function testPageAllCustom_Type4() + { + $page = Base::PAGE_ALL_CUSTOMS; + $query = null; + $qid = null; + $n = "1"; + + setURLParam('custom', 1); + + $currentPage = Page::getPage($page, $qid, $query, $n); + $currentPage->InitializeContent(); + + $this->assertEquals("Type4", $currentPage->title); + $this->assertCount(2, $currentPage->entryArray); + $this->assertEquals("SeriesLike", $currentPage->entryArray [0]->title); + $this->assertEquals(2, $currentPage->entryArray [0]->numberOfElement); + $this->assertFalse($currentPage->ContainsBook()); + + setURLParam('custom', null); + } + + public function testPageAllCustom_Type2() + { + $page = Base::PAGE_ALL_CUSTOMS; + $query = null; + $qid = null; + $n = "1"; + + setURLParam('custom', 2); + + $currentPage = Page::getPage($page, $qid, $query, $n); + $currentPage->InitializeContent(); + + $this->assertEquals("Type2", $currentPage->title); + $this->assertCount(3, $currentPage->entryArray); + $this->assertEquals("tag1", $currentPage->entryArray [0]->title); + $this->assertEquals(2, $currentPage->entryArray [0]->numberOfElement); + $this->assertFalse($currentPage->ContainsBook()); + + setURLParam('custom', null); + } + + public function testPageAllCustom_Type1() + { + $page = Base::PAGE_ALL_CUSTOMS; + $query = null; + $qid = null; + $n = "1"; + + setURLParam('custom', 3); + + $currentPage = Page::getPage($page, $qid, $query, $n); + $currentPage->InitializeContent(); + + $this->assertEquals("Type1", $currentPage->title); + $this->assertCount(2, $currentPage->entryArray); + $this->assertEquals("other", $currentPage->entryArray [0]->title); + $this->assertEquals(1, $currentPage->entryArray [0]->numberOfElement); + $this->assertFalse($currentPage->ContainsBook()); + + setURLParam('custom', null); + } + + public function testPageCustomDetail_Type4() + { + $page = Base::PAGE_CUSTOM_DETAIL; + $query = null; + $qid = "1"; + $n = "1"; + + setURLParam('custom', 1); + + $currentPage = Page::getPage($page, $qid, $query, $n); + $currentPage->InitializeContent(); + + $this->assertEquals("SeriesLike", $currentPage->title); + $this->assertCount(2, $currentPage->entryArray); + $this->assertEquals("Alice's Adventures in Wonderland", $currentPage->entryArray [0]->title); + $this->assertTrue($currentPage->ContainsBook()); + + setURLParam('custom', null); + } + + public function testPageCustomDetail_Type2() + { + $page = Base::PAGE_CUSTOM_DETAIL; + $query = null; + $qid = "1"; + $n = "1"; + + setURLParam('custom', 2); + + $currentPage = Page::getPage($page, $qid, $query, $n); + $currentPage->InitializeContent(); + + $this->assertEquals("tag1", $currentPage->title); + $this->assertCount(2, $currentPage->entryArray); + $this->assertEquals("Alice's Adventures in Wonderland", $currentPage->entryArray [0]->title); + $this->assertTrue($currentPage->ContainsBook()); + + setURLParam('custom', null); + } + + public function testPageCustomDetail_Type1() + { + $page = Base::PAGE_CUSTOM_DETAIL; + $query = null; + $qid = "1"; + $n = "1"; + + setURLParam('custom', 3); + $qid = "2"; + + $currentPage = Page::getPage($page, $qid, $query, $n); + $currentPage->InitializeContent(); + + $this->assertEquals("other", $currentPage->title); + $this->assertCount(1, $currentPage->entryArray); + $this->assertEquals("A Study in Scarlet", $currentPage->entryArray [0]->title); + $this->assertTrue($currentPage->ContainsBook()); + + setURLParam('custom', null); + } + + public function testPageAllAuthors_WithFullName() + { + global $config; + $page = Base::PAGE_ALL_AUTHORS; + $query = null; + $qid = null; + $n = "1"; + + $config['cops_author_split_first_letter'] = "0"; + + $currentPage = Page::getPage($page, $qid, $query, $n); + $currentPage->InitializeContent(); + + $this->assertEquals("Authors", $currentPage->title); + $this->assertCount(6, $currentPage->entryArray); + $this->assertEquals("Carroll, Lewis", $currentPage->entryArray [0]->title); + $this->assertFalse($currentPage->ContainsBook()); + + $config['cops_author_split_first_letter'] = "1"; + } + + public function testPageAllAuthors_SplittedByFirstLetter() + { + global $config; + $page = Base::PAGE_ALL_AUTHORS; + $query = null; + $qid = null; + $n = "1"; + + $currentPage = Page::getPage($page, $qid, $query, $n); + $currentPage->InitializeContent(); + + $this->assertEquals("Authors", $currentPage->title); + $this->assertCount(5, $currentPage->entryArray); + $this->assertEquals("C", $currentPage->entryArray [0]->title); + $this->assertEquals(1, $currentPage->entryArray [0]->numberOfElement); + $this->assertFalse($currentPage->ContainsBook()); + } + + public function testPageAuthorsFirstLetter() + { + $page = Base::PAGE_AUTHORS_FIRST_LETTER; + $query = null; + $qid = "C"; + $n = "1"; + + // Author Lewis Carroll + $currentPage = Page::getPage($page, $qid, $query, $n); + $currentPage->InitializeContent(); + + $this->assertEquals("1 author starting with C", $currentPage->title); + $this->assertCount(1, $currentPage->entryArray); + $this->assertFalse($currentPage->ContainsBook()); + } + + public function testPageAuthorsDetail_FirstPage() + { + global $config; + $page = Base::PAGE_AUTHOR_DETAIL; + $query = null; + $qid = "1"; + $n = "1"; + $_SERVER['QUERY_STRING'] = "page=" . Base::PAGE_AUTHOR_DETAIL . "&id=1&n=1"; + + $config['cops_max_item_per_page'] = 2; + + // First page + + $currentPage = Page::getPage($page, $qid, $query, $n); + $currentPage->InitializeContent(); + + $this->assertEquals("Arthur Conan Doyle", $currentPage->title); + $this->assertEquals(4, $currentPage->getMaxPage()); + $this->assertCount(2, $currentPage->entryArray); + $this->assertTrue($currentPage->ContainsBook()); + $this->assertTrue($currentPage->IsPaginated()); + $this->assertNull($currentPage->getPrevLink()); + + unset($_SERVER['QUERY_STRING']); + $config['cops_max_item_per_page'] = -1; + } + + public function testPageAuthorsDetail_LastPage() + { + global $config; + $page = Base::PAGE_AUTHOR_DETAIL; + $query = null; + $qid = "1"; + $n = "1"; + $_SERVER['QUERY_STRING'] = "page=" . Base::PAGE_AUTHOR_DETAIL . "&id=1&n=1"; + + // Last page + $config['cops_max_item_per_page'] = 5; + $n = "2"; + + $currentPage = Page::getPage($page, $qid, $query, $n); + $currentPage->InitializeContent(); + + $this->assertEquals("Arthur Conan Doyle", $currentPage->title); + $this->assertEquals(2, $currentPage->getMaxPage()); + $this->assertCount(3, $currentPage->entryArray); + $this->assertTrue($currentPage->ContainsBook()); + $this->assertTrue($currentPage->IsPaginated()); + $this->assertNull($currentPage->getNextLink()); + + unset($_SERVER['QUERY_STRING']); + // No pagination + $config['cops_max_item_per_page'] = -1; + } + + public function testPageAuthorsDetail_NoPagination() + { + global $config; + $page = Base::PAGE_AUTHOR_DETAIL; + $query = null; + $qid = "1"; + $n = "1"; + $_SERVER['QUERY_STRING'] = "page=" . Base::PAGE_AUTHOR_DETAIL . "&id=1&n=1"; + + // No pagination + $config['cops_max_item_per_page'] = -1; + + $currentPage = Page::getPage($page, $qid, $query, $n); + $currentPage->InitializeContent(); + + $this->assertEquals("Arthur Conan Doyle", $currentPage->title); + $this->assertCount(8, $currentPage->entryArray); + $this->assertTrue($currentPage->ContainsBook()); + $this->assertFalse($currentPage->IsPaginated()); + + unset($_SERVER['QUERY_STRING']); + } + + public function testPageAllBooks_WithFullName() + { + global $config; + $page = Base::PAGE_ALL_BOOKS; + $query = null; + $qid = null; + $n = "1"; + + $config['cops_titles_split_first_letter'] = 0; + + $currentPage = Page::getPage($page, $qid, $query, $n); + $currentPage->InitializeContent(); + + $this->assertEquals("All books", $currentPage->title); + $this->assertCount(15, $currentPage->entryArray); + $this->assertEquals("The Adventures of Sherlock Holmes", $currentPage->entryArray [0]->title); + $this->assertEquals("Alice's Adventures in Wonderland", $currentPage->entryArray [1]->title); + $this->assertTrue($currentPage->ContainsBook()); + + $config['cops_titles_split_first_letter'] = 1; + } + + public function testPageAllBooks_SplittedByFirstLetter() + { + global $config; + $page = Base::PAGE_ALL_BOOKS; + $query = null; + $qid = null; + $n = "1"; + + $currentPage = Page::getPage($page, $qid, $query, $n); + $currentPage->InitializeContent(); + + $this->assertEquals("All books", $currentPage->title); + $this->assertCount(9, $currentPage->entryArray); + $this->assertEquals("A", $currentPage->entryArray [0]->title); + $this->assertEquals("C", $currentPage->entryArray [1]->title); + $this->assertFalse($currentPage->ContainsBook()); + } + + public function testPageAllBooksByLetter() + { + $page = Base::PAGE_ALL_BOOKS_LETTER; + $query = null; + $qid = "C"; + $n = "1"; + + $currentPage = Page::getPage($page, $qid, $query, $n); + $currentPage->InitializeContent(); + + $this->assertEquals("3 books starting with C", $currentPage->title); + $this->assertCount(3, $currentPage->entryArray); + $this->assertEquals("The Call of the Wild", $currentPage->entryArray [0]->title); + $this->assertTrue($currentPage->ContainsBook()); + } + + public function testPageAllSeries() + { + $page = Base::PAGE_ALL_SERIES; + $query = null; + $qid = null; + $n = "1"; + + $currentPage = Page::getPage($page, $qid, $query, $n); + $currentPage->InitializeContent(); + + $this->assertEquals("Series", $currentPage->title); + $this->assertCount(4, $currentPage->entryArray); + $this->assertEquals("D'Artagnan Romances", $currentPage->entryArray [0]->title); + $this->assertFalse($currentPage->ContainsBook()); + } + + public function testPageSeriesDetail() + { + $page = Base::PAGE_SERIE_DETAIL; + $query = null; + $qid = "1"; + $n = "1"; + $currentPage = Page::getPage($page, $qid, $query, $n); + $currentPage->InitializeContent(); + + $this->assertEquals("Sherlock Holmes", $currentPage->title); + $this->assertCount(7, $currentPage->entryArray); + $this->assertEquals("A Study in Scarlet", $currentPage->entryArray [0]->title); + $this->assertTrue($currentPage->ContainsBook()); + } + + public function testPageAllPublishers() + { + $page = Base::PAGE_ALL_PUBLISHERS; + $query = null; + $qid = null; + $n = "1"; + + $currentPage = Page::getPage($page, $qid, $query, $n); + $currentPage->InitializeContent(); + + $this->assertEquals("Publishers", $currentPage->title); + $this->assertCount(6, $currentPage->entryArray); + $this->assertEquals("D. Appleton and Company", $currentPage->entryArray [0]->title); + $this->assertFalse($currentPage->ContainsBook()); + } + + public function testPagePublishersDetail() + { + $page = Base::PAGE_PUBLISHER_DETAIL; + $query = null; + $qid = "6"; + $n = "1"; + + $currentPage = Page::getPage($page, $qid, $query, $n); + $currentPage->InitializeContent(); + + $this->assertEquals("Strand Magazine", $currentPage->title); + $this->assertCount(8, $currentPage->entryArray); + $this->assertEquals("The Return of Sherlock Holmes", $currentPage->entryArray [0]->title); + $this->assertTrue($currentPage->ContainsBook()); + } + + public function testPageAllTags() + { + $page = Base::PAGE_ALL_TAGS; + $query = null; + $qid = null; + $n = "1"; + + $currentPage = Page::getPage($page, $qid, $query, $n); + $currentPage->InitializeContent(); + + $this->assertEquals("Tags", $currentPage->title); + $this->assertCount(11, $currentPage->entryArray); + $this->assertEquals("Action & Adventure", $currentPage->entryArray [0]->title); + $this->assertFalse($currentPage->ContainsBook()); + } + + public function testPageTagDetail() + { + $page = Base::PAGE_TAG_DETAIL; + $query = null; + $qid = "1"; + $n = "1"; + + $currentPage = Page::getPage($page, $qid, $query, $n); + $currentPage->InitializeContent(); + + $this->assertEquals("Fiction", $currentPage->title); + $this->assertCount(14, $currentPage->entryArray); + $this->assertEquals("The Adventures of Sherlock Holmes", $currentPage->entryArray [0]->title); + $this->assertTrue($currentPage->ContainsBook()); + } + + public function testPageAllLanguages() + { + $page = Base::PAGE_ALL_LANGUAGES; + $query = null; + $qid = null; + $n = "1"; + + $currentPage = Page::getPage($page, $qid, $query, $n); + $currentPage->InitializeContent(); + + $this->assertEquals("Languages", $currentPage->title); + $this->assertCount(2, $currentPage->entryArray); + $this->assertEquals("English", $currentPage->entryArray [0]->title); + $this->assertEquals("French", $currentPage->entryArray [1]->title); + $this->assertFalse($currentPage->ContainsBook()); + } + + public function testPageLanguageDetail() + { + $page = Base::PAGE_LANGUAGE_DETAIL; + $query = null; + $qid = "1"; + $n = "1"; + + $currentPage = Page::getPage($page, $qid, $query, $n); + $currentPage->InitializeContent(); + + $this->assertEquals("English", $currentPage->title); + $this->assertCount(14, $currentPage->entryArray); + $this->assertEquals("The Adventures of Sherlock Holmes", $currentPage->entryArray [0]->title); + $this->assertTrue($currentPage->ContainsBook()); + } + + public function testPageAllRatings() + { + $page = Base::PAGE_ALL_RATINGS; + $query = null; + $qid = null; + $n = "1"; + + $currentPage = Page::getPage($page, $qid, $query, $n); + $currentPage->InitializeContent(); + + $this->assertEquals("Ratings", $currentPage->title); + $this->assertCount(3, $currentPage->entryArray); + $this->assertEquals("2 stars", $currentPage->entryArray [0]->title); + $this->assertFalse($currentPage->ContainsBook()); + } + + public function testPageRatingDetail() + { + $page = Base::PAGE_RATING_DETAIL; + $query = null; + $qid = "1"; + $n = "1"; + + $currentPage = Page::getPage($page, $qid, $query, $n); + $currentPage->InitializeContent(); + + $this->assertEquals("5 stars", $currentPage->title); + $this->assertCount(4, $currentPage->entryArray); + $this->assertEquals("The Adventures of Sherlock Holmes", $currentPage->entryArray [0]->title); + $this->assertTrue($currentPage->ContainsBook()); + } + + public function testPageRecent() + { + $page = Base::PAGE_ALL_RECENT_BOOKS; + $query = null; + $qid = null; + $n = "1"; + + $currentPage = Page::getPage($page, $qid, $query, $n); + $currentPage->InitializeContent(); + + $this->assertEquals("Recent additions", $currentPage->title); + $this->assertCount(15, $currentPage->entryArray); + $this->assertEquals("La curée", $currentPage->entryArray [0]->title); + $this->assertTrue($currentPage->ContainsBook()); + } + + public function testPageRecent_WithFacets_IncludedTag() + { + $page = Base::PAGE_ALL_RECENT_BOOKS; + $query = null; + $qid = null; + $n = "1"; + + setURLParam('tag', "Historical"); + $currentPage = Page::getPage($page, $qid, $query, $n); + $currentPage->InitializeContent(); + + $this->assertEquals("Recent additions", $currentPage->title); + $this->assertCount(2, $currentPage->entryArray); + $this->assertEquals("Twenty Years After", $currentPage->entryArray [0]->title); + $this->assertTrue($currentPage->ContainsBook()); + + setURLParam('tag', null); + } + + public function testPageRecent_WithFacets_ExcludedTag() + { + $page = Base::PAGE_ALL_RECENT_BOOKS; + $query = null; + $qid = null; + $n = "1"; + + setURLParam('tag', "!Romance"); + $currentPage = Page::getPage($page, $qid, $query, $n); + $currentPage->InitializeContent(); + + $this->assertEquals("Recent additions", $currentPage->title); + $this->assertCount(13, $currentPage->entryArray); + $this->assertEquals("La curée", $currentPage->entryArray [0]->title); + $this->assertTrue($currentPage->ContainsBook()); + + setURLParam('tag', null); + } + + public function testPageBookDetail() + { + $page = Base::PAGE_BOOK_DETAIL; + $query = null; + $qid = "2"; + $n = "1"; + + $currentPage = Page::getPage($page, $qid, $query, $n); + $currentPage->InitializeContent(); + + $this->assertEquals("The Return of Sherlock Holmes", $currentPage->title); + $this->assertCount(0, $currentPage->entryArray); + $this->assertFalse($currentPage->ContainsBook()); + } + + public function testPageSearch_WithOnlyBooksReturned() + { + global $config; + $page = Base::PAGE_OPENSEARCH_QUERY; + $query = "alice"; + $qid = null; + $n = "1"; + + // Only books returned + $currentPage = Page::getPage($page, $qid, $query, $n); + $currentPage->InitializeContent(); + + $this->assertEquals("Search result for *alice*", $currentPage->title); + $this->assertCount(1, $currentPage->entryArray); + $this->assertEquals("Search result for *alice* in books", $currentPage->entryArray [0]->title); + $this->assertEquals("2 books", $currentPage->entryArray [0]->content); + $this->assertFalse($currentPage->ContainsBook()); + } + + public function testPageSearch_WithAuthorsIgnored() + { + global $config; + $page = Base::PAGE_OPENSEARCH_QUERY; + // Match Lewis Caroll & Scarlet + $query = "car"; + $qid = null; + $n = "1"; + + $config ['cops_ignored_categories'] = ["author"]; + $currentPage = Page::getPage($page, $qid, $query, $n); + $currentPage->InitializeContent(); + + $this->assertEquals("Search result for *car*", $currentPage->title); + $this->assertCount(1, $currentPage->entryArray); + $this->assertEquals("Search result for *car* in books", $currentPage->entryArray [0]->title); + $this->assertEquals("1 book", $currentPage->entryArray [0]->content); + $this->assertFalse($currentPage->ContainsBook()); + + $config ['cops_ignored_categories'] = []; + } + + public function testPageSearch_WithTwoCategories() + { + global $config; + $page = Base::PAGE_OPENSEARCH_QUERY; + // Match Lewis Caroll & Scarlet + $query = "car"; + $qid = null; + $n = "1"; + + $currentPage = Page::getPage($page, $qid, $query, $n); + $currentPage->InitializeContent(); + + $this->assertEquals("Search result for *car*", $currentPage->title); + $this->assertCount(2, $currentPage->entryArray); + $this->assertEquals("Search result for *car* in books", $currentPage->entryArray [0]->title); + $this->assertEquals("1 book", $currentPage->entryArray [0]->content); + $this->assertEquals("Search result for *car* in authors", $currentPage->entryArray [1]->title); + $this->assertEquals("1 author", $currentPage->entryArray [1]->content); + $this->assertFalse($currentPage->ContainsBook()); + } + + /** + * @dataProvider providerAccentuatedCharacters + */ + public function testPageSearch_WithAccentuatedCharacters($query, $count, $content) + { + global $config; + $page = Base::PAGE_OPENSEARCH_QUERY; + $qid = null; + $n = "1"; + + $currentPage = Page::getPage($page, $qid, $query, $n); + $currentPage->InitializeContent(); + + $this->assertEquals("Search result for *$query*", $currentPage->title); + $this->assertCount($count, $currentPage->entryArray); + if ($count > 0) { + $this->assertEquals($content, $currentPage->entryArray [0]->content); + } + $this->assertFalse($currentPage->ContainsBook()); + } + + public function providerAccentuatedCharacters() + { + return [ + ["curée", 1, "1 book"], + ["Émile zola", 1, "1 author"], + ["émile zola", 0, null], // With standard search upper does not work with diacritics + ["Littérature", 1, "1 tag"], + ["Eugène Fasquelle", 1, "1 publisher"], + ]; + } + + /** + * @dataProvider providerNormalizedSearch + */ + public function testPageSearch_WithNormalizedSearch_Book($query, $count, $content) + { + global $config; + $page = Base::PAGE_OPENSEARCH_QUERY; + $qid = null; + $n = "1"; + $config ['cops_normalized_search'] = "1"; + Base::clearDb(); + if (!useNormAndUp()) { + $this->markTestIncomplete(); + } + + $currentPage = Page::getPage($page, $qid, $query, $n); + $currentPage->InitializeContent(); + + $this->assertEquals("Search result for *$query*", $currentPage->title); + $this->assertCount($count, $currentPage->entryArray); + if ($count > 0) { + $this->assertEquals($content, $currentPage->entryArray [0]->content); + } + $this->assertFalse($currentPage->ContainsBook()); + + $config ['cops_normalized_search'] = "0"; + Base::clearDb(); + } + + public function providerNormalizedSearch() + { + return [ + ["curee", 1, "1 book"], + ["emile zola", 1, "1 author"], + ["émile zola", 1, "1 author"], + ["Litterature", 1, "1 tag"], + ["Litterâture", 1, "1 tag"], + ["Serie des Rougon", 1, "1 series"], + ["Eugene Fasquelle", 1, "1 publisher"], + ]; + } + + public function testAuthorSearch_ByName() + { + global $config; + $page = Base::PAGE_OPENSEARCH_QUERY; + $query = "Lewis Carroll"; + setURLParam('scope', "author"); + $qid = null; + $n = "1"; + + $currentPage = Page::getPage($page, $qid, $query, $n); + $currentPage->InitializeContent(); + + $this->assertEquals("Search result for *Lewis Carroll* in authors", $currentPage->title); + $this->assertCount(1, $currentPage->entryArray); + $this->assertEquals("Carroll, Lewis", $currentPage->entryArray [0]->title); + $this->assertFalse($currentPage->ContainsBook()); + + setURLParam('scope', null); + } + + public function testAuthorSearch_BySort() + { + global $config; + $page = Base::PAGE_OPENSEARCH_QUERY; + $query = "Carroll, Lewis"; + setURLParam('scope', "author"); + $qid = null; + $n = "1"; + + $currentPage = Page::getPage($page, $qid, $query, $n); + $currentPage->InitializeContent(); + + $this->assertEquals("Search result for *Carroll, Lewis* in authors", $currentPage->title); + $this->assertCount(1, $currentPage->entryArray); + $this->assertEquals("Carroll, Lewis", $currentPage->entryArray [0]->title); + $this->assertFalse($currentPage->ContainsBook()); + + setURLParam('scope', null); + } + + public function testPageSearchScopeAuthors() + { + $page = Base::PAGE_OPENSEARCH_QUERY; + $qid = null; + $n = "1"; + setURLParam('scope', "author"); + + // Match Lewis Carroll + $query = "car"; + $currentPage = Page::getPage($page, $qid, $query, $n); + $currentPage->InitializeContent(); + + $this->assertEquals("Search result for *car* in authors", $currentPage->title); + $this->assertCount(1, $currentPage->entryArray); + $this->assertEquals("Carroll, Lewis", $currentPage->entryArray [0]->title); + $this->assertFalse($currentPage->ContainsBook()); + + setURLParam('scope', null); + } + + public function testPageSearchScopeSeries() + { + $page = Base::PAGE_OPENSEARCH_QUERY; + $qid = null; + $n = "1"; + setURLParam('scope', "series"); + + // Match Holmes + $query = "hol"; + $currentPage = Page::getPage($page, $qid, $query, $n); + $currentPage->InitializeContent(); + + $this->assertEquals("Search result for *hol* in series", $currentPage->title); + $this->assertCount(1, $currentPage->entryArray); + $this->assertEquals("Sherlock Holmes", $currentPage->entryArray [0]->title); + $this->assertFalse($currentPage->ContainsBook()); + + setURLParam('scope', null); + } + + public function testPageSearchScopeBooks() + { + $page = Base::PAGE_OPENSEARCH_QUERY; + $qid = null; + $n = "1"; + setURLParam('scope', "book"); + + // Match Holmes + $query = "hol"; + $currentPage = Page::getPage($page, $qid, $query, $n); + $currentPage->InitializeContent(); + + $this->assertEquals("Search result for *hol* in books", $currentPage->title); + $this->assertCount(4, $currentPage->entryArray); + $this->assertTrue($currentPage->ContainsBook()); + + setURLParam('scope', null); + } + + public function testPageSearchScopePublishers() + { + $page = Base::PAGE_OPENSEARCH_QUERY; + $qid = null; + $n = "1"; + setURLParam('scope', "publisher"); + + // Match Holmes + $query = "millan"; + $currentPage = Page::getPage($page, $qid, $query, $n); + $currentPage->InitializeContent(); + + $this->assertEquals("Search result for *millan* in publishers", $currentPage->title); + $this->assertCount(2, $currentPage->entryArray); + $this->assertEquals("Macmillan and Co. London", $currentPage->entryArray [0]->title); + $this->assertFalse($currentPage->ContainsBook()); + + setURLParam('scope', null); + } + + public function testPageSearchScopeTags() + { + $page = Base::PAGE_OPENSEARCH_QUERY; + $qid = null; + $n = "1"; + setURLParam('scope', "tag"); + + // Match Holmes + $query = "fic"; + $currentPage = Page::getPage($page, $qid, $query, $n); + $currentPage->InitializeContent(); + + $this->assertEquals("Search result for *fic* in tags", $currentPage->title); + $this->assertCount(2, $currentPage->entryArray); + $this->assertFalse($currentPage->ContainsBook()); + + setURLParam('scope', null); + } +} diff --git a/test/prepareSauceTest.sh b/test/prepareSauceTest.sh new file mode 100644 index 000000000..8f5358922 --- /dev/null +++ b/test/prepareSauceTest.sh @@ -0,0 +1,38 @@ +#!/usr/bin/env bash + +PHP_VERSION=`php -v|grep --only-matching --perl-regexp "PHP 5\.\\d+"` +echo $PHP_VERSION + + +if [[ $PHP_VERSION != "PHP 5.6" ]] + then + echo "Bad PHP version" + exit +fi + +echo "Good PHP version" + +# Handle scrutinizer +wget https://scrutinizer-ci.com/ocular.phar +php ocular.phar code-coverage:upload --format=php-clover clover.xml + +if [[ -z $SAUCE_ACCESS_KEY ]] + then + echo "No Sauce Api Key (Pull request)" + exit +fi + +# Install dependencies +wget http://getcomposer.org/composer.phar +php composer.phar install + +echo 'opcache.enable=1' >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini +echo 'opcache.enable_cli=1' >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini + +# Handle Sauce +# curl https://gist.githubusercontent.com/seblucas/7692094/raw/e2a090e6ea639a0d700e6d02cee048fa2f6c8617/sauce_connect_setup.sh | bash +cp -v test/config_local.php.sauce config_local.php +php -S 127.0.0.1:8080 & +vendor/bin/phpunit --no-configuration test/Sauce.php + + diff --git a/test/res/atom.rnc b/test/res/atom.rnc new file mode 100644 index 000000000..15ce28412 --- /dev/null +++ b/test/res/atom.rnc @@ -0,0 +1,338 @@ +# -*- rnc -*- +# RELAX NG Compact Syntax Grammar for the +# Atom Format Specification Version 11 + +namespace atom = "http://www.w3.org/2005/Atom" +namespace xhtml = "http://www.w3.org/1999/xhtml" +namespace s = "http://www.ascc.net/xml/schematron" +namespace local = "" + +start = atomFeed | atomEntry + +# Common attributes + +atomCommonAttributes = + attribute xml:base { atomUri }?, + attribute xml:lang { atomLanguageTag }?, + undefinedAttribute* + +# Text Constructs + +atomPlainTextConstruct = + atomCommonAttributes, + attribute type { "text" | "html" }?, + text + +atomXHTMLTextConstruct = + atomCommonAttributes, + attribute type { "xhtml" }, + xhtmlDiv + +atomTextConstruct = atomPlainTextConstruct | atomXHTMLTextConstruct + +# Person Construct + +atomPersonConstruct = + atomCommonAttributes, + (element atom:name { text } + & element atom:uri { atomUri }? + & element atom:email { atomEmailAddress }? + & extensionElement*) + +# Date Construct + +atomDateConstruct = + atomCommonAttributes, + xsd:dateTime + +# atom:feed + +atomFeed = + [ + s:rule [ + context = "atom:feed" + s:assert [ + test = "atom:author or not(atom:entry[not(atom:author)])" + "An atom:feed must have an atom:author unless all " + ~ "of its atom:entry children have an atom:author." + ] + ] + ] + element atom:feed { + atomCommonAttributes, + (atomAuthor* + & atomCategory* + & atomContributor* + & atomGenerator? + & atomIcon? + & atomId + & atomLink* + & atomLogo? + & atomRights? + & atomSubtitle? + & atomTitle + & atomUpdated + & extensionElement*), + atomEntry* + } + +# atom:entry + +atomEntry = + [ + s:rule [ + context = "atom:entry" + s:assert [ + test = "atom:link[@rel='alternate'] " + ~ "or atom:link[not(@rel)] " + ~ "or atom:content" + "An atom:entry must have at least one atom:link element " + ~ "with a rel attribute of 'alternate' " + ~ "or an atom:content." + ] + ] + s:rule [ + context = "atom:entry" + s:assert [ + test = "atom:author or " + ~ "../atom:author or atom:source/atom:author" + "An atom:entry must have an atom:author " + ~ "if its feed does not." + ] + ] + ] + element atom:entry { + atomCommonAttributes, + (atomAuthor* + & atomCategory* + & atomContent? + & atomContributor* + & atomId + & atomLink* + & atomPublished? + & atomRights? + & atomSource? + & atomSummary? + & atomTitle + & atomUpdated + & extensionElement*) + } + +# atom:content + +atomInlineTextContent = + element atom:content { + atomCommonAttributes, + attribute type { "text" | "html" }?, + (text)* + } + +atomInlineXHTMLContent = + element atom:content { + atomCommonAttributes, + attribute type { "xhtml" }, + xhtmlDiv + } + +atomInlineOtherContent = + element atom:content { + atomCommonAttributes, + attribute type { atomMediaType }?, + (text|anyElement)* + } + +atomOutOfLineContent = + element atom:content { + atomCommonAttributes, + attribute type { atomMediaType }?, + attribute src { atomUri }, + empty + } + +atomContent = atomInlineTextContent +| atomInlineXHTMLContent +| atomInlineOtherContent +| atomOutOfLineContent + +# atom:author + +atomAuthor = element atom:author { atomPersonConstruct } + +# atom:category + +atomCategory = + element atom:category { + atomCommonAttributes, + attribute term { text }, + attribute scheme { atomUri }?, + attribute label { text }?, + undefinedContent + } + +# atom:contributor + +atomContributor = element atom:contributor { atomPersonConstruct } + +# atom:generator + +atomGenerator = element atom:generator { + atomCommonAttributes, + attribute uri { atomUri }?, + attribute version { text }?, + text +} + +# atom:icon + +atomIcon = element atom:icon { + atomCommonAttributes, + (atomUri) +} + +# atom:id + +atomId = element atom:id { + atomCommonAttributes, + (atomUri) +} + +# atom:logo + +atomLogo = element atom:logo { + atomCommonAttributes, + (atomUri) +} + +# atom:link + +atomLink = + element atom:link { + atomCommonAttributes, + attribute href { atomUri }, + attribute rel { atomNCName | atomUri }?, + attribute type { atomMediaType }?, + attribute hreflang { atomLanguageTag }?, + attribute title { text }?, + attribute length { text }?, + undefinedContent + } + +# atom:published + +atomPublished = element atom:published { atomDateConstruct } + +# atom:rights + +atomRights = element atom:rights { atomTextConstruct } + +# atom:source + +atomSource = + element atom:source { + atomCommonAttributes, + (atomAuthor* + & atomCategory* + & atomContributor* + & atomGenerator? + & atomIcon? + & atomId? + & atomLink* + & atomLogo? + & atomRights? + & atomSubtitle? + & atomTitle? + & atomUpdated? + & extensionElement*) + } + +# atom:subtitle + +atomSubtitle = element atom:subtitle { atomTextConstruct } + +# atom:summary + +atomSummary = element atom:summary { atomTextConstruct } + +# atom:title + +atomTitle = element atom:title { atomTextConstruct } + +# atom:updated + +atomUpdated = element atom:updated { atomDateConstruct } + +# Low-level simple types + +atomNCName = xsd:string { minLength = "1" pattern = "[^:]*" } + +# Whatever a media type is, it contains at least one slash +atomMediaType = xsd:string { pattern = ".+/.+" } + +# As defined in RFC 3066 +atomLanguageTag = xsd:string { + pattern = "[A-Za-z]{1,8}(-[A-Za-z0-9]{1,8})*" +} + +# Unconstrained; it's not entirely clear how IRI fit into +# xsd:anyURI so let's not try to constrain it here +atomUri = text + +# Whatever an email address is, it contains at least one @ +atomEmailAddress = xsd:string { pattern = ".+@.+" } + +# Simple Extension + +simpleExtensionElement = + element * - atom:* { + text + } + +# Structured Extension + +structuredExtensionElement = + element * - atom:* { + (attribute * { text }+, + (text|anyElement)*) + | (attribute * { text }*, + (text?, anyElement+, (text|anyElement)*)) + } + +# Other Extensibility + +extensionElement = + simpleExtensionElement | structuredExtensionElement + +undefinedAttribute = + attribute * - (xml:base | xml:lang | local:*) { text } + +undefinedContent = (text|anyForeignElement)* + +anyElement = + element * { + (attribute * { text } + | text + | anyElement)* + } + +anyForeignElement = + element * - atom:* { + (attribute * { text } + | text + | anyElement)* + } + +# XHTML + +anyXHTML = element xhtml:* { + (attribute * { text } + | text + | anyXHTML)* +} + +xhtmlDiv = element xhtml:div { + (attribute * { text } + | text + | anyXHTML)* +} + +# EOF diff --git a/test/res/opds_v1.0.rnc b/test/res/opds_v1.0.rnc new file mode 100644 index 000000000..4c22e2b3b --- /dev/null +++ b/test/res/opds_v1.0.rnc @@ -0,0 +1,131 @@ +# -*- rnc -*- +# RELAX NG Compact Syntax Grammar for OPDS Catalog Feed & Entry Documents +# Version 2010-08-18 +namespace atom = "http://www.w3.org/2005/Atom" +namespace opds = "http://opds-spec.org/2010/catalog" +namespace local = "" + +# The OPDS Catalog spec extends Atom (RFC4287), and the additions require some +# patterns not used in the Atom schema. The first is atomUriExceptOPDS, which +# is used to describe an atomLink whose rel value is an atomNCName (no-colon +# name) or any URI other than these from OPDS Catalogs. In these cases, no +# opds:price element should appear. +atomUriExceptOPDS = string - ( string "http://opds-spec.org/acquisition/buy" + | string "http://opds-spec.org/acquisition/borrow" + | string "http://opds-spec.org/acquisition/subscribe" + | string "http://opds-spec.org/acquisition/sample" ) + +# Next is OPDSUrisExceptBuy, which is used to describe an atomLink whose +# rel value is from OPDS Catalogs but is not ".../acquisition/buy". In such +# cases, an opds:price element is optional. +OPDSUrisExceptBuy = string "http://opds-spec.org/acquisition/borrow" + | string "http://opds-spec.org/acquisition/subscribe" + | string "http://opds-spec.org/acquisition/sample" + +# To simplify OPDS Catalog validation, we do not use Schematron to assert that +# any atom:link with a rel value of ".../acquisition/buy" must be accompanied +# by one or more opds:price elements. +# Instead we rely on Relax NG to describe one of three situations: +# - the rel value is ".../acquisition/buy" and at least one opds:price element +# is required +# - the rel value is ".../acquisition/borrow" or ".../acquisition/subscribe" or +# ".../acquisition/sample", in case opds:price elements may be +# included; or +# - the value of the rel attribute is any other URI or an Atom-defined no-colon +# name, and no opds:price element is permitted + +# Note that this OPDS Catalog schema includes atom.rnc, so that schema must be +# present for validation. +# +# Note also that atom.rnc defines atomUri as text and not as xsd:anyURI, and so +# wherever the Atom spec requires an IRI, the schema will not check the value +# against any URI pattern or logic. The OPDS Catalog schema overrides atom.rnc +# to provide a relatively accurate test. With the approval of XSD 1.1, the +# schema definition should change to xsd:anyURI to match what the spec text +# says. +include "atom.rnc" { + atomLink = + element atom:link { + atomCommonAttributes & + attribute href { atomUri } & + attribute type { atomMediaType }? & + attribute hreflang { atomLanguageTag }? & + attribute title { text }? & + attribute length { text }? & + ((attribute rel { "http://opds-spec.org/acquisition/buy" }, opdsPrice+ ) + | + (attribute rel { OPDSUrisExceptBuy }, opdsPrice*) + | + (attribute rel { atomNCName | ( atomUriExceptOPDS ) } ))? & + anyOPDSForeignElement* & + text + } + + # Here is where OPDS Catalogs use John Cowan's pragmatic evaluation of an + # IRI. This modifies xsd:anyURI in XSD 1.0 to exclude ASCII characters not + # valid in 1.1 or IRI's without being escaped. This matches the OPDS and Atom + # specs, but not the non-normative atom.rnc. + atomUri = xsd:anyURI - xsd:string {pattern = '.*[ <>{}|^`"\\\n\r\t].*'} + + # Here we override Atom to account for HTML abuse in the summary element, + # restricting it in OPDS Catalog to text: + atomSummary = + element atom:summary { + atomCommonAttributes, + attribute type { "text" }?, + text + } +} + + +anyOPDSForeignElement = + element * - ( atom:* | opds:* ) { + ( attribute * { text } + | text + | anyElement )* + } + +# An opds:price element should not contain a currency symbol; it is +# restricted to non-negative decimal numbers. +opdsPrice = + element opds:price { + atomCommonAttributes, + attribute currencycode { opdsPriceCurrencyCode }, + xsd:decimal { minInclusive="0.0" } + } + +# Instead of allowing every possible 3-letter or 3-digit combination as a +# currency code, here the permissible codes (as identified in ISO4217 as of +# 2010-08-25) are enumerated. In 2012 or so, that standard may add, remove or +# change some currency codes, thus requiring this schema to be updated. Note +# that codes for metals and funds are not included. +opdsPriceCurrencyCode = ( + "AED" | "AFN" | "ALL" | "AMD" | "ANG" | "AOA" | "ARS" | "AUD" | "AWG" | "AZN" | "BAM" | "BBD" | "BDT" | + "BGN" | "BHD" | "BIF" | "BMD" | "BND" | "BOB" | "BOV" | "BRL" | "BSD" | "BTN" | "BWP" | "BYR" | "BZD" | + "CAD" | "CDF" | "CHE" | "CHF" | "CHW" | "CLF" | "CLP" | "CNY" | "COP" | "COU" | "CRC" | "CUC" | "CUP" | + "CVE" | "CZK" | "DJF" | "DKK" | "DOP" | "DZD" | "EEK" | "EGP" | "ERN" | "ETB" | "EUR" | "FJD" | "FKP" | + "GBP" | "GEL" | "GHS" | "GIP" | "GMD" | "GNF" | "GTQ" | "GYD" | "HKD" | "HNL" | "HRK" | "HTG" | "HUF" | + "IDR" | "ILS" | "INR" | "IQD" | "IRR" | "ISK" | "JMD" | "JOD" | "JPY" | "KES" | "KGS" | "KHR" | "KMF" | + "KPW" | "KRW" | "KWD" | "KYD" | "KZT" | "LAK" | "LBP" | "LKR" | "LRD" | "LSL" | "LTL" | "LVL" | "LYD" | + "MAD" | "MDL" | "MGA" | "MKD" | "MMK" | "MNT" | "MOP" | "MRO" | "MUR" | "MVR" | "MWK" | "MXN" | "MXV" | + "MYR" | "MZN" | "NAD" | "NGN" | "NIO" | "NOK" | "NPR" | "NZD" | "OMR" | "PAB" | "PEN" | "PGK" | "PHP" | + "PKR" | "PLN" | "PYG" | "QAR" | "RON" | "RSD" | "RUB" | "RWF" | "SAR" | "SBD" | "SCR" | "SDG" | "SEK" | + "SGD" | "SHP" | "SLL" | "SOS" | "SRD" | "STD" | "SVC" | "SYP" | "SZL" | "THB" | "TJS" | "TMT" | "TND" | + "TOP" | "TRY" | "TTD" | "TWD" | "TZS" | "UAH" | "UGX" | "USD" | "USN" | "USS" | "UYI" | "UYU" | "UZS" | + "VEF" | "VND" | "VUV" | "WST" | "XAF" | "XAG" | "XAU" | "XBA" | "XBB" | "XBC" | "XBD" | "XCD" | "XDR" | + "XFU" | "XOF" | "XPD" | "XPF" | "XPT" | "XTS" | "XXX" | "YER" | "ZAR" | "ZMK" | "ZWL" | "008" | "012" | + "032" | "036" | "044" | "048" | "050" | "051" | "052" | "060" | "064" | "068" | "072" | "084" | "090" | + "096" | "104" | "108" | "116" | "124" | "132" | "136" | "144" | "152" | "156" | "170" | "174" | "188" | + "191" | "192" | "203" | "208" | "214" | "222" | "230" | "232" | "233" | "238" | "242" | "262" | "270" | + "292" | "320" | "324" | "328" | "332" | "340" | "344" | "348" | "352" | "356" | "360" | "364" | "368" | + "376" | "388" | "392" | "398" | "400" | "404" | "408" | "410" | "414" | "417" | "418" | "422" | "426" | + "428" | "430" | "434" | "440" | "446" | "454" | "458" | "462" | "478" | "480" | "484" | "496" | "498" | + "504" | "512" | "516" | "524" | "532" | "533" | "548" | "554" | "558" | "566" | "578" | "586" | "590" | + "598" | "600" | "604" | "608" | "634" | "643" | "646" | "654" | "678" | "682" | "690" | "694" | "702" | + "704" | "706" | "710" | "748" | "752" | "756" | "760" | "764" | "776" | "780" | "784" | "788" | "800" | + "807" | "818" | "826" | "834" | "840" | "858" | "860" | "882" | "886" | "894" | "901" | "931" | "932" | + "934" | "936" | "937" | "938" | "940" | "941" | "943" | "944" | "946" | "947" | "948" | "949" | "950" | + "951" | "952" | "953" | "955" | "956" | "957" | "958" | "959" | "960" | "961" | "962" | "963" | "964" | + "968" | "969" | "970" | "971" | "972" | "973" | "974" | "975" | "976" | "977" | "978" | "979" | "980" | + "981" | "984" | "985" | "986" | "990" | "997" | "998" | "999" +) diff --git a/test/res/opds_v1.1.rnc b/test/res/opds_v1.1.rnc new file mode 100644 index 000000000..9a0778ff5 --- /dev/null +++ b/test/res/opds_v1.1.rnc @@ -0,0 +1,151 @@ +# -*- rnc -*- +# RELAX NG Compact Syntax Grammar for OPDS Catalog Feed & Entry Documents +# Version 2010-08-18 +namespace atom = "http://www.w3.org/2005/Atom" +namespace opds = "http://opds-spec.org/2010/catalog" +namespace local = "" + +# The OPDS Catalog spec extends Atom (RFC4287), and the additions require some +# patterns not used in the Atom schema. The first is atomUriExceptOPDS, which +# is used to describe an atomLink whose rel value is an atomNCName (no-colon +# name) or any URI other than these from OPDS Catalogs. In these cases, no +# opds:price element should appear. +atomUriExceptOPDS = string - ( string "http://opds-spec.org/acquisition/buy" + | string "http://opds-spec.org/acquisition/borrow" + | string "http://opds-spec.org/acquisition/subscribe" + | string "http://opds-spec.org/acquisition/sample" ) + +# Next is OPDSUrisExceptBuy, which is used to describe an atomLink whose +# rel value is from OPDS Catalogs but is not ".../acquisition/buy". In such +# cases, an opds:price element is optional. +OPDSUrisExceptBuy = string "http://opds-spec.org/acquisition/borrow" + | string "http://opds-spec.org/acquisition/subscribe" + | string "http://opds-spec.org/acquisition/sample" + +# To simplify OPDS Catalog validation, we do not use Schematron to assert that +# any atom:link with a rel value of ".../acquisition/buy" must be accompanied +# by one or more opds:price elements. +# Instead we rely on Relax NG to describe one of three situations: +# - the rel value is ".../acquisition/buy" and at least one opds:price element +# is required +# - the rel value is ".../acquisition/borrow" or ".../acquisition/subscribe" or +# ".../acquisition/sample", in case opds:price elements may be +# included; or +# - the value of the rel attribute is any other URI or an Atom-defined no-colon +# name, and no opds:price element is permitted + +# Note that this OPDS Catalog schema includes atom.rnc, so that schema must be +# present for validation. +# +# Note also that atom.rnc defines atomUri as text and not as xsd:anyURI, and so +# wherever the Atom spec requires an IRI, the schema will not check the value +# against any URI pattern or logic. The OPDS Catalog schema overrides atom.rnc +# to provide a relatively accurate test. With the approval of XSD 1.1, the +# schema definition should change to xsd:anyURI to match what the spec text +# says. +include "atom.rnc" { + +undefinedAttribute = + attribute * - (xml:base | xml:lang | local:*| opds:* ) { text } + + atomLink = + element atom:link { + atomCommonAttributes , + attribute href { atomUri }, + attribute type { atomMediaType }? , + attribute hreflang { atomLanguageTag }? , + attribute title { text }? , + attribute length { text }? , + ((attribute rel { "http://opds-spec.org/facet" }, (attribute opds:facetGroup { text }? & attribute opds:activeFacet { "true" }? )) + | + (attribute rel { "http://opds-spec.org/acquisition/buy" }, opdsPrice+ ) + | + (attribute rel { OPDSUrisExceptBuy }, opdsPrice*) + | + (attribute rel { atomNCName | ( atomUriExceptOPDS ) } ))? , + (opdsIndirectAcquisition | + anyOPDSForeignElement | + text)* + } + + # Here is where OPDS Catalogs use John Cowan's pragmatic evaluation of an + # IRI. This modifies xsd:anyURI in XSD 1.0 to exclude ASCII characters not + # valid in 1.1 or IRI's without being escaped. This matches the OPDS and Atom + # specs, but not the non-normative atom.rnc. + atomUri = xsd:anyURI - xsd:string {pattern = '.*[ <>{}|^`"\\\n\r\t].*'} + + # Here we override Atom to account for HTML abuse in the summary element, + # restricting it in OPDS Catalog to text: + atomSummary = + element atom:summary { + atomCommonAttributes, + attribute type { "text" }?, + text + } +} + + +anyOPDSForeignElement = + element * - ( atom:* | opds:* ) { + ( attribute * { text } + | text + | anyElement )* + } + + +# An opds:indirectAcquisition should use strictly MIME media type for +#its type attribute +opdsIndirectAcquisition = + element opds:indirectAcquisition { + atomCommonAttributes, + attribute type { atomMediaType }, + ( anyOPDSForeignElement | + opdsIndirectAcquisition) * + } + + +# An opds:price element should not contain a currency symbol; it is +# restricted to non-negative decimal numbers. +opdsPrice = + element opds:price { + atomCommonAttributes, + attribute currencycode { opdsPriceCurrencyCode }, + xsd:decimal { minInclusive="0.0" } + } + + +# Instead of allowing every possible 3-letter or 3-digit combination as a +# currency code, here the permissible codes (as identified in ISO4217 as of +# 2010-08-25) are enumerated. In 2012 or so, that standard may add, remove or +# change some currency codes, thus requiring this schema to be updated. Note +# that codes for metals and funds are not included. +opdsPriceCurrencyCode = ( + "AED" | "AFN" | "ALL" | "AMD" | "ANG" | "AOA" | "ARS" | "AUD" | "AWG" | "AZN" | "BAM" | "BBD" | "BDT" | + "BGN" | "BHD" | "BIF" | "BMD" | "BND" | "BOB" | "BOV" | "BRL" | "BSD" | "BTN" | "BWP" | "BYR" | "BZD" | + "CAD" | "CDF" | "CHE" | "CHF" | "CHW" | "CLF" | "CLP" | "CNY" | "COP" | "COU" | "CRC" | "CUC" | "CUP" | + "CVE" | "CZK" | "DJF" | "DKK" | "DOP" | "DZD" | "EEK" | "EGP" | "ERN" | "ETB" | "EUR" | "FJD" | "FKP" | + "GBP" | "GEL" | "GHS" | "GIP" | "GMD" | "GNF" | "GTQ" | "GYD" | "HKD" | "HNL" | "HRK" | "HTG" | "HUF" | + "IDR" | "ILS" | "INR" | "IQD" | "IRR" | "ISK" | "JMD" | "JOD" | "JPY" | "KES" | "KGS" | "KHR" | "KMF" | + "KPW" | "KRW" | "KWD" | "KYD" | "KZT" | "LAK" | "LBP" | "LKR" | "LRD" | "LSL" | "LTL" | "LVL" | "LYD" | + "MAD" | "MDL" | "MGA" | "MKD" | "MMK" | "MNT" | "MOP" | "MRO" | "MUR" | "MVR" | "MWK" | "MXN" | "MXV" | + "MYR" | "MZN" | "NAD" | "NGN" | "NIO" | "NOK" | "NPR" | "NZD" | "OMR" | "PAB" | "PEN" | "PGK" | "PHP" | + "PKR" | "PLN" | "PYG" | "QAR" | "RON" | "RSD" | "RUB" | "RWF" | "SAR" | "SBD" | "SCR" | "SDG" | "SEK" | + "SGD" | "SHP" | "SLL" | "SOS" | "SRD" | "STD" | "SVC" | "SYP" | "SZL" | "THB" | "TJS" | "TMT" | "TND" | + "TOP" | "TRY" | "TTD" | "TWD" | "TZS" | "UAH" | "UGX" | "USD" | "USN" | "USS" | "UYI" | "UYU" | "UZS" | + "VEF" | "VND" | "VUV" | "WST" | "XAF" | "XAG" | "XAU" | "XBA" | "XBB" | "XBC" | "XBD" | "XCD" | "XDR" | + "XFU" | "XOF" | "XPD" | "XPF" | "XPT" | "XTS" | "XXX" | "YER" | "ZAR" | "ZMK" | "ZWL" | "008" | "012" | + "032" | "036" | "044" | "048" | "050" | "051" | "052" | "060" | "064" | "068" | "072" | "084" | "090" | + "096" | "104" | "108" | "116" | "124" | "132" | "136" | "144" | "152" | "156" | "170" | "174" | "188" | + "191" | "192" | "203" | "208" | "214" | "222" | "230" | "232" | "233" | "238" | "242" | "262" | "270" | + "292" | "320" | "324" | "328" | "332" | "340" | "344" | "348" | "352" | "356" | "360" | "364" | "368" | + "376" | "388" | "392" | "398" | "400" | "404" | "408" | "410" | "414" | "417" | "418" | "422" | "426" | + "428" | "430" | "434" | "440" | "446" | "454" | "458" | "462" | "478" | "480" | "484" | "496" | "498" | + "504" | "512" | "516" | "524" | "532" | "533" | "548" | "554" | "558" | "566" | "578" | "586" | "590" | + "598" | "600" | "604" | "608" | "634" | "643" | "646" | "654" | "678" | "682" | "690" | "694" | "702" | + "704" | "706" | "710" | "748" | "752" | "756" | "760" | "764" | "776" | "780" | "784" | "788" | "800" | + "807" | "818" | "826" | "834" | "840" | "858" | "860" | "882" | "886" | "894" | "901" | "931" | "932" | + "934" | "936" | "937" | "938" | "940" | "941" | "943" | "944" | "946" | "947" | "948" | "949" | "950" | + "951" | "952" | "953" | "955" | "956" | "957" | "958" | "959" | "960" | "961" | "962" | "963" | "964" | + "968" | "969" | "970" | "971" | "972" | "973" | "974" | "975" | "976" | "977" | "978" | "979" | "980" | + "981" | "984" | "985" | "986" | "990" | "997" | "998" | "999" +) \ No newline at end of file diff --git a/tools/alpinePrepare.sh b/tools/alpinePrepare.sh new file mode 100644 index 000000000..d2c7022d5 --- /dev/null +++ b/tools/alpinePrepare.sh @@ -0,0 +1,18 @@ +#!/bin/sh + +# apk --no-cache add git +# git clone https://github.com/seblucas/cops.git +# cd cops + +apk add --upgrade apk-tools + +# Deployment dependencies +apk --no-cache add php7 php7-phar php7-json php7-openssl php7-gd php7-xml php7-intl php7-mbstring php7-pdo_sqlite php7-xmlwriter php7-zip php7-ctype + +# Development dependencies +apk --no-cache add php7-tokenizer php7-simplexml php7-curl php7-dom openjdk7-jre + +wget http://getcomposer.org/composer.phar +php composer.phar install --optimize-autoloader + +./vendor/bin/phpunit \ No newline at end of file diff --git a/tools/export_file.txt b/tools/export_file.txt index f706a7f7f..3f5590101 100644 --- a/tools/export_file.txt +++ b/tools/export_file.txt @@ -1,71 +1,71 @@ -' Output a file -' If there is no translation then we output the line as a comment -' that starts with #EN# indicating that translation is required - - -Sub Export_File(sType, iCol As Integer) - - Dim oFile As Integer - Dim iRow As Integer - Dim iBlankLines As Integer - Dim sLangCode As String - Dim sOut As String - Dim sTemp As String - Dim bOut() As Byte - Dim shSheet As Worksheet: Set shSheet = Worksheets(sType) - - sFilename = sType & "_" & LCase$(shSheet.Cells(cLanguageCodeRow, iCol).Value) & ".json" - oFile = FreeFile() - sFullPath = Application.ActiveWorkbook.Path & "\" & sFilename - On Error Resume Next - Kill sFullPath - Open sFullPath For Output As #oFile - Close #oFile - On Error GoTo 0 - Open sFullPath For Binary Access Write As #oFile - ' Output comment on version as first line - sOut = "{" & vbCrLf - bOut = UnicodeToBytes(Worksheets(cConfiguration).Cells(cOutputFormatRow, cOutputFormatCol), sOut) - Put #oFile, , bOut - - iRow = cFirstDataRow - Do - sTemp = shSheet.Cells(iRow, cKeywordCol).Value - sOut = "// " & sTemp -' Print #oFile, sTemp; - If Len(sTemp) = 0 Then - iBlankLines = iBlankLines + 1 - Else - iBlankLines = 0 - If Not isComment(sTemp) And (Not (sTemp Like "config*") Or sTemp Like "config.Language*") And Not sTemp Like "gui*" And Not sTemp Like "error*" And Not sTemp Like "info*" And Not sTemp Like "stats*" Then - sOut = """" & sTemp & """" & ":" -' Print #oFile, "="; - sTemp = shSheet.Cells(iRow, iCol).Value - If Len(sTemp) > 0 Then - sOut = sOut & """" & sTemp & """," - sOut = sOut & vbCrLf - bOut = UnicodeToBytes(Worksheets(cConfiguration).Cells(cOutputFormatRow, cOutputFormatCol), sOut) - Put #oFile, , bOut -' Print #oFile, sTemp; - Else - ' If no language specific one supplied then - ' output English one as a comment starting with '#EN#' - ' (as long this is not the english column with empty value) - If iCol <> cEnglishLangCol Then - sOut = "// EN" & sOut - End If - sOut = sOut & shSheet.Cells(iRow, 3).Value -' Print #oFile, shSheet.Cells(iRow, 3).Value; - End If - End If - End If -' Print #oFile, "" ' Force new line - iRow = iRow + 1 - Loop Until (iBlankLines > 5) - - sOut = """fin"":""fin""" & vbCrLf & "}" & vbCrLf - bOut = UnicodeToBytes(Worksheets(cConfiguration).Cells(cOutputFormatRow, cOutputFormatCol), sOut) - Put #oFile, , bOut - - Close #oFile -End Sub +' Output a file +' If there is no translation then we output the line as a comment +' that starts with #EN# indicating that translation is required + + +Sub Export_File(sType, iCol As Integer) + + Dim oFile As Integer + Dim iRow As Integer + Dim iBlankLines As Integer + Dim sLangCode As String + Dim sOut As String + Dim sTemp As String + Dim bOut() As Byte + Dim shSheet As Worksheet: Set shSheet = Worksheets(sType) + + sFilename = sType & "_" & LCase$(shSheet.Cells(cLanguageCodeRow, iCol).Value) & ".json" + oFile = FreeFile() + sFullPath = Application.ActiveWorkbook.Path & "\" & sFilename + On Error Resume Next + Kill sFullPath + Open sFullPath For Output As #oFile + Close #oFile + On Error GoTo 0 + Open sFullPath For Binary Access Write As #oFile + ' Output comment on version as first line + sOut = "{" & vbCrLf + bOut = UnicodeToBytes(Worksheets(cConfiguration).Cells(cOutputFormatRow, cOutputFormatCol), sOut) + Put #oFile, , bOut + + iRow = cFirstDataRow + Do + sTemp = shSheet.Cells(iRow, cKeywordCol).Value + sOut = "// " & sTemp +' Print #oFile, sTemp; + If Len(sTemp) = 0 Then + iBlankLines = iBlankLines + 1 + Else + iBlankLines = 0 + If Not isComment(sTemp) And (Not (sTemp Like "config*") Or sTemp Like "config.Language*") And Not sTemp Like "gui*" And Not sTemp Like "error*" And Not sTemp Like "info*" And Not sTemp Like "stats*" Then + sOut = """" & sTemp & """" & ":" +' Print #oFile, "="; + sTemp = shSheet.Cells(iRow, iCol).Value + If Len(sTemp) > 0 Then + sOut = sOut & """" & sTemp & """," + sOut = sOut & vbCrLf + bOut = UnicodeToBytes(Worksheets(cConfiguration).Cells(cOutputFormatRow, cOutputFormatCol), sOut) + Put #oFile, , bOut +' Print #oFile, sTemp; + Else + ' If no language specific one supplied then + ' output English one as a comment starting with '#EN#' + ' (as long this is not the english column with empty value) + If iCol <> cEnglishLangCol Then + sOut = "// EN" & sOut + End If + sOut = sOut & shSheet.Cells(iRow, 3).Value +' Print #oFile, shSheet.Cells(iRow, 3).Value; + End If + End If + End If +' Print #oFile, "" ' Force new line + iRow = iRow + 1 + Loop Until (iBlankLines > 5) + + sOut = """fin"":""fin""" & vbCrLf & "}" & vbCrLf + bOut = UnicodeToBytes(Worksheets(cConfiguration).Cells(cOutputFormatRow, cOutputFormatCol), sOut) + Put #oFile, , bOut + + Close #oFile +End Sub diff --git a/tools/updateLang.pl b/tools/updateLang.pl index 66caca0ed..6e7feafd6 100644 --- a/tools/updateLang.pl +++ b/tools/updateLang.pl @@ -1,15 +1,15 @@ #!/usr/bin/perl -# Program : COPS localization string generator +# Program : COPS localization string generator # Version : 0.0.1 # -# Author : Sbastien Lucas +# Author : Sébastien Lucas # License : GPLv2 # use strict; -my @strings = (); +our @strings = (); my %values; my %allstrings; @@ -20,16 +20,16 @@ next if (-d $_ ); # skip directories next if (/^[.]/); # skip dot-files next if not (/(.+)[.]php$/); - + my $file = "../" . $_; debug ("text file: " . $_ . "\n"); my $content = loadFile ($file); - + while ($content =~ /localize\s*\("([\w\.]*?)"\)/igs) { $allstrings{$1} = ""; debug (" * $1 \n"); } - + while ($content =~ /localize\s*\("([\w\.]*?)"\s*,/igs) { $allstrings{$1 . ".none"} = ""; $allstrings{$1 . ".one"} = ""; @@ -43,50 +43,72 @@ # Load existing json files with strings and values +handleLanguageFile ("Localization_en.json"); + opendir (my($dirhandle), "../lang") or die ("Directory not found\n"); for (readdir ($dirhandle)) { next if (-d $_ ); # skip directories next if (/^[.]/); # skip dot-files next if not (/(.+)[.]json$/); - - my $file = "../lang/" . $_; - (my $lang = $_) =~ s/Localization_(\w\w)\.json/$1/; - debug ("language file: $_ / $lang \n"); - + next if (/en\.json$/); + + handleLanguageFile ($_); +} +closedir $dirhandle; + +sub handleLanguageFile { + my ($file) = @_; + (my $lang = $file) =~ s/Localization_(\w\w)\.json/$1/; + my $file = "../lang/" . $file; + my $total = 0; + my $translated = 0; + + debug ("language file: $file / $lang \n"); + my $content = loadFile ($file); - - while ($content =~ /"(.*?)"\:"(.*?)",/igs) { - #push @strings, $1; - $values{$lang}{$1} = $2; + + while ($content =~ /"\s*(.*?)"\:\s*"(.*?)",/igs) { + my $key = $1; + my $value = $2; + next if ($key =~ /^##TODO##/); + if ($lang eq "en" && $key =~ /^languages\.\w{3}$/) { + push (@strings, $key); + } + $values{$lang}{$key} = $value; #debug (" * $1 \n"); } - - open OUTPUT, ">$file.new"; - + + open OUTPUT, ">$file"; + print OUTPUT "{\n"; foreach my $name (@strings) { - print OUTPUT "\"$name\":\"$values{$lang}{$name}\",\n"; + $total++ if ($name !~ /^languages\.\w{3}$/); + if (not exists ($values{$lang}{$name})) { + print OUTPUT " \"##TODO##$name\": \"$values{en}{$name}\",\n"; + } else { + $translated++ if ($name !~ /^languages\.\w{3}$/); + print OUTPUT " \"$name\": \"$values{$lang}{$name}\",\n"; + } } - print OUTPUT "\"end\":\"end\"\n"; + my $percentage = ($translated * 100) / $total; + debug (" $translated / $total ($percentage %) \n"); + print OUTPUT " \"DO_NOT_TRANSLATE\": \"end\"\n"; print OUTPUT "}\n"; - + close OUTPUT; } -closedir $dirhandle; - - sub loadFile { my ($file) = @_; my $save = $/; $/ = undef; - + open INPUT, "<$file"; my $content = ; close INPUT; $/ = $save; - + return $content; } diff --git a/transliteration.php b/transliteration.php new file mode 100644 index 000000000..d15b6d1da --- /dev/null +++ b/transliteration.php @@ -0,0 +1,200 @@ += "\x80" && $c < "\xc0") { + // Legal tail bytes are nice. + $sequence .= $c; + } else { + if ($len == 0) { + // Premature end of string! Drop a replacement character into + // output to represent the invalid UTF-8 sequence. + $result .= $unknown; + break 2; + } else { + // Illegal tail byte; abandon the sequence. + $result .= $unknown; + // Back up and reprocess this byte; it may itself be a legal + // ASCII or UTF-8 sequence head. + --$i; + ++$len; + continue 2; + } + } + } while (--$remaining); + + $n = ord($head); + if ($n <= 0xdf) { + $ord = ($n - 192) * 64 + (ord($sequence[1]) - 128); + } elseif ($n <= 0xef) { + $ord = ($n - 224) * 4096 + (ord($sequence[1]) - 128) * 64 + (ord($sequence[2]) - 128); + } elseif ($n <= 0xf7) { + $ord = ($n - 240) * 262144 + (ord($sequence[1]) - 128) * 4096 + (ord($sequence[2]) - 128) * 64 + (ord($sequence[3]) - 128); + } elseif ($n <= 0xfb) { + $ord = ($n - 248) * 16777216 + (ord($sequence[1]) - 128) * 262144 + (ord($sequence[2]) - 128) * 4096 + (ord($sequence[3]) - 128) * 64 + (ord($sequence[4]) - 128); + } elseif ($n <= 0xfd) { + $ord = ($n - 252) * 1073741824 + (ord($sequence[1]) - 128) * 16777216 + (ord($sequence[2]) - 128) * 262144 + (ord($sequence[3]) - 128) * 4096 + (ord($sequence[4]) - 128) * 64 + (ord($sequence[5]) - 128); + } else { + $ord = $n; + } + $result .= _transliteration_replace($ord, $unknown, $source_langcode); + $head = ''; + } elseif ($c < "\x80") { + // ASCII byte. + $result .= $c; + $head = ''; + } elseif ($c < "\xc0") { + // Illegal tail bytes. + if ($head == '') { + $result .= $unknown; + } + } else { + // Miscellaneous freaks. + $result .= $unknown; + $head = ''; + } + } + } + return $result; +} + +/** + * Replaces a Unicode character using the transliteration database. + * + * @param $ord + * An ordinal Unicode character code. + * @param $unknown + * Replacement string for characters that do not have a suitable ASCII + * equivalent. + * @param $langcode + * Optional ISO 639 language code that denotes the language of the input and + * is used to apply language-specific variations. Defaults to the current + * display language. + * @return string + * ASCII replacement character. + */ +function _transliteration_replace($ord, $unknown = '?', $langcode = null) +{ + static $map = []; + + //GL: set language later + /* + if (!isset($langcode)) { + global $language; + $langcode = $language->language; + } + */ + + $bank = $ord >> 8; + + if (!isset($map[$bank][$langcode])) { + $file = './resources/transliteration-data/' . sprintf('x%02x', $bank) . '.php'; + if (file_exists($file)) { + $base = []; + $variant = []; + include $file; + if ($langcode != 'en' && isset($variant[$langcode])) { + // Merge in language specific mappings. + $map[$bank][$langcode] = $variant[$langcode] + $base; + } else { + $map[$bank][$langcode] = $base; + } + } else { + $map[$bank][$langcode] = []; + } + } + + $ord = $ord & 255; + + return $map[$bank][$langcode][$ord] ?? $unknown; +} diff --git a/util.js b/util.js new file mode 100644 index 000000000..48d82b07c --- /dev/null +++ b/util.js @@ -0,0 +1,519 @@ +// util.js +// copyright Sébastien Lucas +// https://github.com/seblucas/cops + +/*jshint curly: true, latedef: true, trailing: true, noarg: true, undef: true, browser: true, jquery: true, unused: true, devel: true, loopfunc: true */ +/*global LRUCache, doT, Bloodhound, postRefresh */ + +var templatePage, templateBookDetail, templateMain, templateSuggestion, currentData, before, filterList; + +var CLEAR_FILTER_ID = "_CLEAR_"; + +if (typeof LRUCache === 'undefined') { + console.log('ERROR: LRUCache module not loaded!'); +} +var cache = new LRUCache(30); + +$.ajaxSetup({ + cache: false +}); + +var copsTypeahead = new Bloodhound({ + datumTokenizer: Bloodhound.tokenizers.obj.whitespace('title'), + queryTokenizer: Bloodhound.tokenizers.whitespace, + limit: 30, + remote: { + url: 'getJSON.php?page=9&search=1&db=%DB&query=%QUERY', + replace: function (url, query) { + if (currentData.multipleDatabase === 1 && currentData.databaseId === "") { + return url.replace('%QUERY', query).replace('&db=%DB', ""); + } + return url.replace('%QUERY', query).replace('%DB', currentData.databaseId); + } + } +}); + +copsTypeahead.initialize(); + +var DEBUG = false; +var isPushStateEnabled = window.history && window.history.pushState && window.history.replaceState && + // pushState isn't reliable on iOS until 5. + !window.navigator.userAgent.match(/((iPod|iPhone|iPad).+\bOS\s+[1-4]|WebApps\/.+CFNetwork)/); + +function debug_log(text) { + if ( DEBUG ) { + console.log(text); + } +} + +/*exported updateCookie */ +function updateCookie (id) { + if ($(id).prop('pattern') && !$(id).val().match(new RegExp ($(id).prop('pattern')))) { + return; + } + var name = $(id).attr('id'); + var value = $(id).val (); + Cookies.set(name, value, { expires: 365 }); +} + +/*exported updateCookieFromCheckbox */ +function updateCookieFromCheckbox (id) { + var name = $(id).attr('id'); + if ((/^style/).test (name)) { + name = "style"; + } + if ($(id).is(":checked")) + { + if ($(id).is(':radio')) { + Cookies.set(name, $(id).val (), { expires: 365 }); + } else { + Cookies.set(name, '1', { expires: 365 }); + } + } + else + { + Cookies.set(name, '0', { expires: 365 }); + } +} + +/*exported updateCookieFromCheckboxGroup */ +function updateCookieFromCheckboxGroup (id) { + var name = $(id).attr('name'); + var idBase = name.replace (/\[\]/, ""); + var group = []; + $(':checkbox[name="' + name + '"]:checked').each (function () { + var id = $(this).attr("id"); + group.push (id.replace (idBase + "_", "")); + }); + Cookies.set(idBase, group.join (), { expires: 365 }); +} + + +function elapsed () { + var elapsedTime = new Date () - before; + return "Elapsed : " + elapsedTime; +} + +function retourMail(data) { + $("#mailButton :first-child").removeClass ("fas fa-spinner fa-pulse").addClass ("fas fa-envelope"); + alert (data); +} + +/*exported sendToMailAddress */ +function sendToMailAddress (component, dataid) { + var email = Cookies.get('email'); + if (!Cookies.get('email')) { + email = window.prompt (currentData.c.i18n.customizeEmail, ""); + if (email === null) + { + return; + } + Cookies.set('email', email, { expires: 365 }); + } + var url = 'sendtomail.php'; + if (currentData.databaseId) { + url = url + '?db=' + currentData.databaseId; + } + $("#mailButton :first-child").removeClass ("fas fa-envelope").addClass ("fas fa-spinner fa-pulse"); + $.ajax ({'url': url, 'type': 'post', 'data': { 'data': dataid, 'email': email }, 'success': retourMail}); +} + +function str_format () { + var s = arguments[0]; + for (var i = 0; i < arguments.length - 1; i++) { + var reg = new RegExp("\\{" + i + "\\}", "gm"); + s = s.replace(reg, arguments[i + 1]); + } + return s; +} + +function isDefined(x) { + return (typeof x !== 'undefined'); +} + +function getCurrentOption (option) { + if (!Cookies.get(option)) { + if (currentData && currentData.c && currentData.c.config && currentData.c.config [option]) { + return currentData.c.config [option]; + } + } + return Cookies.get(option); +} + +/*exported htmlspecialchars */ +function htmlspecialchars(str) { + return String(str) + .replace(/&/g, '&') + .replace(/"/g, '"') + .replace(/'/g, ''') + .replace(//g, '>'); +} + +/************************************************ + * All functions needed to filter the book list by tags + ************************************************ + */ + +function getTagList () { + var tagList = {}; + $(".se").each (function(){ + if ($(this).parents (".filtered").length > 0) { return; } + var taglist = $(this).text(); + + var tagarray = taglist.split (","); + for (var i in tagarray) { + if (!tagarray.hasOwnProperty(i)) { + continue; + } + var tag = tagarray [i].replace(/^\s+/g,'').replace(/\s+$/g,''); + tagList [tag] = 1; + } + }); + return tagList; +} + +function updateFilters () { + var tagList = getTagList (); + + // If there is already some filters then let's prepare to update the list + $("#filter ul li").each (function () { + var text = $(this).text (); + if (isDefined (tagList [text]) || $(this).attr ('class')) { + tagList [text] = 0; + } else { + tagList [text] = -1; + } + }); + + // Update the filter -1 to remove, 1 to add, 0 already there + for (var tag in tagList) { + if (!tagList.hasOwnProperty(tag)) { + continue; + } + var tagValue = tagList [tag]; + if (tagValue === -1) { + $("#filter ul li").filter (function () { return $.text([this]) === tag; }).remove(); + } + if (tagValue === 1) { + $("#filter ul").append ("
  • " + tag + "
  • "); + } + } + + $("#filter ul").append ("
  • " + currentData.c.i18n.filterClearAll + "
  • "); + + // Sort the list alphabetically + $('#filter ul li').sortElements(function(a, b){ + if (a.id === CLEAR_FILTER_ID) { + return 1; + } + if (b.id === CLEAR_FILTER_ID) { + return -1; + } + return $(a).text() > $(b).text() ? 1 : -1; + }); +} + +function doFilter () { + $(".books").removeClass("filtered"); + if (jQuery.isEmptyObject(filterList)) { + updateFilters (); + return; + } + + $(".se").each (function(){ + var taglist = ", " + $(this).text() + ", "; + var toBeFiltered = false; + for (var filter in filterList) { + if (!filterList.hasOwnProperty(filter)) { + continue; + } + var onlyThisTag = filterList [filter]; + filter = ', ' + filter + ', '; + var myreg = new RegExp (filter); + if (myreg.test (taglist)) { + if (onlyThisTag === false) { + toBeFiltered = true; + } + } else { + if (onlyThisTag === true) { + toBeFiltered = true; + } + } + } + if (toBeFiltered) { $(this).parents (".books").addClass ("filtered"); } + }); + + // Handle the books with no tags + var atLeastOneTagSelected = false; + for (var filter in filterList) { + if (!filterList.hasOwnProperty(filter)) { + continue; + } + if (filterList[filter] === true) { + atLeastOneTagSelected = true; + } + } + if (atLeastOneTagSelected) { + $(".books").not (":has(span.se)").addClass ("filtered"); + } + + updateFilters (); +} + +function handleFilterEvents () { + $("#filter ul").on ("click", "li", function(){ + var filter = $(this).text (); + var filterId = this.id; + console.log(filter, filterId); + if (filterId === CLEAR_FILTER_ID) { + filterList = {}; + $("#filter ul li").removeClass ("filter-exclude"); + $("#filter ul li").removeClass ("filter-include"); + doFilter (); + return; + } + switch ($(this).attr("class")) { + case "filter-include" : + $(this).attr("class", "filter-exclude"); + filterList [filter] = false; + break; + case "filter-exclude" : + $(this).removeClass ("filter-exclude"); + delete filterList [filter]; + break; + default : + $(this).attr("class", "filter-include"); + filterList [filter] = true; + break; + } + doFilter (); + }); +} + +/************************************************ + * Functions to handle Ajax navigation + ************************************************ + */ + +var updatePage, navigateTo; + +updatePage = function (data) { + var result; + filterList = {}; + data.c = currentData.c; + if (false && $("section").length && currentData.isPaginated === 0 && data.isPaginated === 0) { + // Partial update (for now disabled) + debug_log ("Partial update"); + result = templateMain (data); + $("h1").html (data.title); + $("section").html (result); + } else { + // Full update + result = templatePage (data); + $("body").html (result); + } + document.title = data.title; + currentData = data; + + debug_log (elapsed ()); + + if (Cookies.get('toolbar') === '1') { $("#tool").show (); } + if (currentData.containsBook === 1) { + $("#sortForm").show (); + if (getCurrentOption ("html_tag_filter") === "1") { + $("#filter ul").empty (); + updateFilters (); + handleFilterEvents (); + } + } else { + $("#sortForm").hide (); + } + + $('input[name=query]').typeahead( + { + hint: true, + minLength : 3 + }, + { + name: 'search', + displayKey: 'title', + templates: { + suggestion: templateSuggestion + }, + source: copsTypeahead.ttAdapter() + }); + + $('input[name=query]').bind('typeahead:selected', function(obj, datum) { + if (isPushStateEnabled) { + navigateTo (datum.navlink); + } else { + window.location = datum.navlink; + } + }); + + if(typeof postRefresh == 'function') + { postRefresh(); } +}; + +navigateTo = function (url) { + $("h1").append (" "); + before = new Date (); + var jsonurl = url.replace ("index", "getJSON"); + var cachedData = cache.get (jsonurl); + if (cachedData) { + window.history.pushState(jsonurl, "", url); + updatePage (cachedData); + } else { + $.getJSON(jsonurl, function(data) { + window.history.pushState(jsonurl, "", url); + cache.put (jsonurl, data); + updatePage (data); + }); + } +}; + +function link_Clicked (event) { + var currentLink = $(this); + if (!isPushStateEnabled || + currentData.page === "19") { + return; + } + event.preventDefault(); + var url = currentLink.attr('href'); + + if ($(".mfp-ready").length) + { + $.magnificPopup.close(); + } + + // The bookdetail / about should be displayed in a lightbox + if (getCurrentOption ("use_fancyapps") === "1" && + (currentLink.hasClass ("fancydetail") || currentLink.hasClass ("fancyabout"))) { + before = new Date (); + var jsonurl = url.replace ("index", "getJSON"); + $.getJSON(jsonurl, function(data) { + data.c = currentData.c; + var detail = ""; + if (data.page === "16") { + detail = data.fullhtml; + } else { + detail = templateBookDetail (data); + } + $.magnificPopup.open({ + items: { + src: detail, + type: 'inline' + } + }); + debug_log (elapsed ()); + }); + return; + } + navigateTo (url); +} + +function search_Submitted (event) { + if (!isPushStateEnabled || + currentData.page === "19") { + return; + } + event.preventDefault(); + var url = str_format ("index.php?page=9¤t={0}&query={1}&db={2}", currentData.page, encodeURIComponent ($("input[name=query]").val ()), currentData.databaseId); + navigateTo (url); +} + +/*exported handleLinks */ +function handleLinks () { + $("body").on ("click", "a[href^='index']", link_Clicked); + $("body").on ("submit", "#searchForm", search_Submitted); + $("body").on ("click", "#sort", function(){ + $('.books').sortElements(function(a, b){ + var test = 1; + if ($("#sortorder").val() === "desc") + { + test = -1; + } + return $(a).find ("." + $("#sortchoice").val()).text() > $(b).find ("." + $("#sortchoice").val()).text() ? test : -test; + }); + }); + + $("body").on ("click", ".headright", function(){ + if ($("#tool").is(":hidden")) { + $("#tool").slideDown("slow"); + Cookies.get('toolbar', '1', { expires: 365 }); + } else { + $("#tool").slideUp(); + Cookies.remove('toolbar'); + } + }); + $("body").magnificPopup({ + delegate: '.fancycover', // child items selector, by clicking on it popup will open + type: 'image', + gallery:{enabled:true, preload: [0,2]}, + disableOn: function() { + if( getCurrentOption ("use_fancyapps") === "1" ) { + return true; + } + return false; + } + }); +} + +window.onpopstate = function(event) { + if (!isDefined (currentData)) { + return; + } + + before = new Date (); + var data = cache.get (event.state); + updatePage (data); +}; + +$(document).keydown(function(e){ + if (e.keyCode === 37 && $("#prevLink").length > 0) { + navigateTo ($("#prevLink").attr('href')); + } + if (e.keyCode === 39 && $("#nextLink").length > 0) { + navigateTo ($("#nextLink").attr('href')); + } +}); + +/*exported initiateAjax */ +function initiateAjax (url, theme) { + $.when($.get('templates/' + theme + '/header.html'), + $.get('templates/' + theme + '/footer.html'), + $.get('templates/' + theme + '/bookdetail.html'), + $.get('templates/' + theme + '/main.html'), + $.get('templates/' + theme + '/page.html'), + $.get('templates/' + theme + '/suggestion.html'), + $.getJSON(url)).done(function(header, footer, bookdetail, main, page, suggestion, data){ + templateBookDetail = doT.template (bookdetail [0]); + + var defMain = { + bookdetail: bookdetail [0] + }; + + templateMain = doT.template (main [0], undefined, defMain); + + var defPage = { + header: header [0], + footer: footer [0], + main : main [0], + bookdetail: bookdetail [0] + }; + + templatePage = doT.template (page [0], undefined, defPage); + + templateSuggestion = doT.template (suggestion [0]); + + currentData = data [0]; + + updatePage (data [0]); + cache.put (url, data [0]); + if (isPushStateEnabled) { + window.history.replaceState(url, "", window.location); + } + handleLinks (); + }); +} diff --git a/verifyLogin.php b/verifyLogin.php new file mode 100644 index 000000000..8687d2e21 --- /dev/null +++ b/verifyLogin.php @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 000000000..ed9e32107 --- /dev/null +++ b/yarn.lock @@ -0,0 +1,63 @@ +# This file is generated by running "yarn install" inside your project. +# Manual changes might be lost - proceed with caution! + +__metadata: + version: 6 + cacheKey: 8 + +"dot@npm:^1.1.3": + version: 1.1.3 + resolution: "dot@npm:1.1.3" + bin: + dottojs: ./bin/dot-packer + checksum: 9a2ecf7b5ff8c5121481702e9fdc7eb802ebf5b9e318a73631f70cb9484c7bb6973322912c173f5fa52d1f9408eaef4d6468e9ef8af3899664f4d42091f5f868 + languageName: node + linkType: hard + +"jquery@npm:^1.12.4": + version: 1.12.4 + resolution: "jquery@npm:1.12.4" + checksum: 17641485debde58d8da6fef707487a75dc2999f272576b8dc0addc352ac7db090bb1706e235299304f95313122f964c78b10dc5a51929f881b080420864979a1 + languageName: node + linkType: hard + +"js-cookie@npm:^2.2.1": + version: 2.2.1 + resolution: "js-cookie@npm:2.2.1" + checksum: 9b1fb980a1c5e624fd4b28ea4867bb30c71e04c4484bb3a42766344c533faa684de9498e443425479ec68609e96e27b60614bfe354877c449c631529b6d932f2 + languageName: node + linkType: hard + +"lru-fast@npm:^0.2.2": + version: 0.2.2 + resolution: "lru-fast@npm:0.2.2" + checksum: 31b375e3ebb8daab10fe0d103e2a3f01f3d7c934d852f4530fd1efa74da41a0d0171c1ef76d739b5e7eb63aef9f10ae7bafab5f613a7e3edb9f8ad0dee7ff84c + languageName: node + linkType: hard + +"magnific-popup@npm:^1.1.0": + version: 1.1.0 + resolution: "magnific-popup@npm:1.1.0" + checksum: 97ff185208d5fc3c49ba2f7b22d9353c1d21ca1a6daf07fae0ef07dda07281f174e3da0ad4e7f04c5f5cf332a611f0f64c3db444002d12f9de37ab14999f0a06 + languageName: node + linkType: hard + +"normalize.css@npm:^8.0.1": + version: 8.0.1 + resolution: "normalize.css@npm:8.0.1" + checksum: 4698cae88ec35e3f3e82f9f9402e6ffb906c27ccd6373cad88e6b3f5634fc7a043cb38702472299e5edb73825cf8b18d5fd9283f58829eddda79ea97453049a2 + languageName: node + linkType: hard + +"seblucas-cops@workspace:.": + version: 0.0.0-use.local + resolution: "seblucas-cops@workspace:." + dependencies: + dot: ^1.1.3 + jquery: ^1.12.4 + js-cookie: ^2.2.1 + lru-fast: ^0.2.2 + magnific-popup: ^1.1.0 + normalize.css: ^8.0.1 + languageName: unknown + linkType: soft